本篇內(nèi)容主要講解“怎么從頭開(kāi)始設(shè)置webpack 5”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“怎么從頭開(kāi)始設(shè)置webpack 5”吧!
創(chuàng)新互聯(lián)公司是一家成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì),提供網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),網(wǎng)站制作,建網(wǎng)站,定制網(wǎng)站設(shè)計(jì),網(wǎng)站開(kāi)發(fā)公司,成立于2013年是互聯(lián)行業(yè)建設(shè)者,服務(wù)者。以提升客戶品牌價(jià)值為核心業(yè)務(wù),全程參與項(xiàng)目的網(wǎng)站策劃設(shè)計(jì)制作,前端開(kāi)發(fā),后臺(tái)程序制作以及后期項(xiàng)目運(yùn)營(yíng)并提出專業(yè)建議和思路。
如果你是從 webpack 4 升級(jí)到 webpack 5,這里有一些注意事項(xiàng):
webpack-dev-server命令現(xiàn)在換成webpack-serve
file-loader、raw-loader和url-loader不是必需的,可以使用內(nèi)置的Asset Modules
節(jié)點(diǎn) polyfill 不再可用,例如,如果遇到stream錯(cuò)誤,則可以將stream-browserify包作為依賴項(xiàng)添加,并將{stream:'stream-browserify'}添加到webpack配置中的alias屬性。
什么是 webpack?
現(xiàn)在,大多數(shù)網(wǎng)站不再只是單單的由原生JS+純HTML編寫(xiě)的,還涉及一些瀏覽器無(wú)法理解的語(yǔ)言,如果項(xiàng)目大,文件多,對(duì)應(yīng)的體積就大。所以要壓縮文件和翻譯成所有瀏覽器都能理解的東西,這就是webpack的用武之地。
webpack 可以看做是模塊打包器:它做的事情是,分析你的項(xiàng)目結(jié)構(gòu),找到JavaScript模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。
對(duì)于開(kāi)發(fā),webpack 還提供了一個(gè)開(kāi)發(fā)服務(wù)器,它可以在我們保存時(shí)動(dòng)態(tài)地更新模塊和樣式。vue create和create-response-app本質(zhì)上都依賴于 webpack。
webpac k可以做很多事情,本文只是幫助大家熟悉一些主要概念并進(jìn)行一些手動(dòng)的配置。
安裝
首先,創(chuàng)建一個(gè)目錄webpack-tutorial,相關(guān)命令如下:
mkdir webpack-tutorial cd webpack-tutorial npm init -y // 創(chuàng)建默認(rèn)的 package.json
安裝webpack和webpack-cli:
npm i -D webpack webpack-cli
接著,創(chuàng)建目錄 src,并在其里面創(chuàng)建 index.js,內(nèi)容如下:
console.log('Interesting!')
基本配置
在項(xiàng)目的根目錄中創(chuàng)建一個(gè)webpack.config.js。
Entry
entry是配置模塊的入口,可抽象成輸入,Webpack 執(zhí)行構(gòu)建的第一步將從入口開(kāi)始搜尋及遞歸解析出所有入口依賴的模塊。
entry 配置是必填的,若不填則將導(dǎo)致 Webpack 報(bào)錯(cuò)退出。這里,我們將src/index.js做為入口點(diǎn)。
const path = require('path') module.exports = { entry: { main: path.resolve(__dirname, './src/index.js'), }, }
Output
配置 output 選項(xiàng)可以控制 webpack 如何向硬盤(pán)寫(xiě)入編譯文件。注意,即使可以存在多個(gè)入口起點(diǎn),但只指定一個(gè)輸出配置。這里指定輸出的路徑為 'dist':
module.exports = { /* ... */ output: { path: path.resolve(__dirname, './dist'), filename: '[name].bundle.js', }, }
現(xiàn)在,我們具有構(gòu)建捆綁包所需的最低配置。在package.json中,我們可以創(chuàng)建一個(gè)運(yùn)行webpack命令的構(gòu)建腳本。
"scripts": { "build": "webpack" }
現(xiàn)在可以運(yùn)行它了:
npm run build
現(xiàn)在在 dist 目錄會(huì)生成一個(gè) main.bundle.js 文件
插件
webpack有一個(gè)插件接口,這使得它更加靈活。內(nèi)部webpack代碼和第三方擴(kuò)展使用插件,有一些主要的方法幾乎每個(gè)webpack項(xiàng)目都會(huì)用到。
HTML 模板文件
目前,我們有一個(gè)隨機(jī)的bundle文件,但它對(duì)我們還不是很有用。如果需要使用main.bundle.js,就要借助 HTML頁(yè)面來(lái)加載這個(gè) JS 包作為腳本。我們希望HTML文件自動(dòng)引入這個(gè)生成 js 文件,所以我們將使用html-webpack-plugin創(chuàng)建一個(gè)HTML模板。
安裝一下:
npm i -D html-webpack-plugin
在src文件夾中創(chuàng)建一個(gè)template.html文件,這里,我們自定義一個(gè)title,內(nèi)容如下:
src/template.html
<%= htmlWebpackPlugin.options.title %>
創(chuàng)建配置的plugins屬性,然后將插件,文件名添加到輸出(index.html),并鏈接到將基于該模板的模板文件。
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { /* ... */ plugins: [ new HtmlWebpackPlugin({ title: 'webpack Boilerplate', template: path.resolve(__dirname, './src/template.html'), // template file filename: 'index.html', // output file }), ], }
現(xiàn)在再次運(yùn)行構(gòu)建,會(huì)看到dist文件夾現(xiàn)在包含一個(gè)index.html,里面也自動(dòng)引入了我們打包好的 js 文件。用瀏覽器打開(kāi) index.html,會(huì)在控制臺(tái)看到 Interesting!。
接著,在index.js中我們動(dòng)態(tài)插入一些 dom 元素到頁(yè)面中,內(nèi)容如下:
// Create heading node const heading = document.createElement('h2') heading.textContent = 'Interesting!' // Append heading node to the DOM const app = document.querySelector('#root') app.append(heading)
重新構(gòu)建,在進(jìn)入 dist 目錄下面,用 http-server 運(yùn)行 html 文件。
http-server
可以在頁(yè)面上看到,我們注入的 "Interesting!",還會(huì)注意到捆綁文件已縮小。
注意:在安裝HtmlWebpackPlugin后,你會(huì)看到一個(gè)DeprecationWarning,因?yàn)椴寮谏?jí)到webpack 5后還沒(méi)有完全擺脫deprecation警告。
Clean
我們還需要設(shè)置clean-webpack-plugin,在每次構(gòu)建后清除dist文件夾中的所有內(nèi)容。這對(duì)于確保不遺留任何舊數(shù)據(jù)很重要。
clean-webpack-plugin-刪除/清理構(gòu)建文件夾
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const {CleanWebpackPlugin} = require('clean-webpack-plugin') module.exports = { /* ... */ plugins: [ /* ... */ new CleanWebpackPlugin(), ], }
Modules and Loaders
webpack 使用 loader 預(yù)處理一些加載的文件,如 js 文件、靜態(tài)資源(如圖像和CSS樣式)和編譯器(如TypeScript和Babel)。webpack 5也有一些內(nèi)置的資產(chǎn)加載器。
在我們的項(xiàng)目中,有一個(gè)HTML文件,該文件可以加載并引入一些 JS ,但實(shí)際上并沒(méi)有執(zhí)行任何操作。那么這個(gè)webpack配置要做的主要事情是什么?
將 JS 編譯為瀏覽器可以理解的版本
導(dǎo)入樣式并將 SCSS 編譯為 CSS
導(dǎo)入圖像和字體
(可選)設(shè)置React或Vue
Babel (JavaScript)
Babel是一個(gè)工具,可讓使用最新的 JS 語(yǔ)法。
建立一個(gè)規(guī)則來(lái)檢查項(xiàng)目中(node_modules之外)的任何.js文件,并使用babel-loader進(jìn)行轉(zhuǎn)換。Babel 還有一些其他的依賴項(xiàng):
babel-loader-使用 Babel 和 webpack 傳輸文件。
@babel/core-將ES2015+ 轉(zhuǎn)換為向后兼容的 JavaScript
@babel/preset-env-Babel 的智能默認(rèn)設(shè)置
@babel/plugin-proposal-class-properties-自定義 Babel 配置的示例(直接在類(lèi)上使用屬性)
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-env @babel/plugin-proposal-class-properties
webpack.config.js
module.exports = { /* ... */ module: { rules: [ // JavaScript { test: /\.js$/, exclude: /node_modules/, use: ['babel-loader'], }, ], }, }
如果是 TypeScript 項(xiàng)目,使用的是typescript-loader而不是babel-loader。
現(xiàn)在Babel已經(jīng)設(shè)置好了,但是我們的Babel插件還沒(méi)有??梢栽趇ndex.js中添加一些新的語(yǔ)法來(lái)證明它還不能正常工作。
// 創(chuàng)建沒(méi)有構(gòu)造函數(shù)的類(lèi)屬性 class Game { name = 'Violin Charades' } const myGame = new Game() // 創(chuàng)建 p 節(jié)點(diǎn) const p = document.createElement('p') p.textContent = `I like ${myGame.name}.` const heading = document.createElement('h2') heading.textContent = 'Interesting!' const app = document.querySelector('#root') app.append(heading, p)
要解決這個(gè)問(wèn)題,只需在項(xiàng)目的根目錄中創(chuàng)建一個(gè).babelrc文件??梢允褂胮reset-env和plugin-proposal-class-properties添加更多默認(rèn)值。
{ "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-proposal-class-properties"] }
Images
假設(shè)我們需要引用一張圖片并直接導(dǎo)入到 JS 文件中,這樣是無(wú)法正常工作的。為了演示,創(chuàng)建 src/ images 并向其中添加圖像,然后嘗試將其導(dǎo)入到index.js文件中。
src/index.js
import example from './images/example.png' /* ... */
運(yùn)行構(gòu)建時(shí),再次看到錯(cuò)誤:
webpack有一些內(nèi)置的asset modules ,可用于靜態(tài)資源。對(duì)于圖像類(lèi)型,我們將使用asset/resource,注意,這里是一個(gè)type,而不是loader。
webpack.config.js
module.exports = { /* ... */ module: { rules: [ // Images { test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource', }, ], }, }
構(gòu)建后,可以在dist文件夾查看。
字體和內(nèi)聯(lián)
webpack 還有一個(gè)asset module ,可以使用asset/inline內(nèi)聯(lián)某些數(shù)據(jù),例如svgs和字體。
src/index.js
import example from './images/example.svg' /* ... */
webpack.config.js
module.exports = { /* ... */ module: { rules: [ // Fonts and SVGs { test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline', }, ], }, }
Styles
同樣的需要使用 style loader才能在腳本中執(zhí)行類(lèi)似import 'file.css'的操作。
現(xiàn)在很多人都在使用CSS-in-JS、styled-components和其他工具來(lái)將樣式引入到他們的 JS 應(yīng)用程序中。
當(dāng)網(wǎng)站只有一個(gè) CSS 文件,僅能夠加載一個(gè)CSS文件就足夠了。但如果想使用PostCSS,為了能在任何瀏覽器中使用所有最新的CSS特性。或者想使用Sass, CSS預(yù)處理器,那就需要使用其它的 loader 處理。
我想使用這三種方法——在Sass中編寫(xiě),在PostCSS中處理,以及編譯到CSS。這需要引入一些加載器和依賴項(xiàng)。
sass-loader — 加載 SCSS 并編譯為CSS
node-sass — Node Sass
postcss-loader — 使用 PostCSS 處理 CSS
css-loader — 解析 css import
style-loader —— 將CSS注入到DOM中
npm i -D sass-loader postcss-loader css-loader style-loader postcss-preset-env node-sass
就像Babel一樣,PostCSS 也需要一個(gè)配置文件 postcss.config.js,在根目錄中創(chuàng)建它,并輸入以下內(nèi)容:
postcss.config.js
module.exports = { plugins: { 'postcss-preset-env': { browsers: 'last 2 versions', }, }, }
為了測(cè)試 Sass 和 PostCSS 是否正常工作,創(chuàng)建 src/styles/main.scss,并輸入以下內(nèi)容:
src/styles/main.scss
$font-size: 1rem; $font-color: lch(53 105 40); html { font-size: $font-size; color: $font-color; }
現(xiàn)在,將文件導(dǎo)入index.js并添加四個(gè) loader 。它們從最后編譯到第一個(gè),因此列表中最后一個(gè)是sass-loader,因?yàn)樾枰幾g,然后是PostCSS,然后是CSS,最后是style-loader,它將CSS注入到DOM 中。
src/index.js
import './styles/main.scss' /* ... */
webpack.config.js
module.exports = { /* ... */ module: { rules: [ // CSS, PostCSS, and Sass { test: /\.(scss|css)$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'], }, ], }, }
現(xiàn)在,重新構(gòu)建時(shí),項(xiàng)目中已經(jīng)應(yīng)用了Sass和PostCSS。
開(kāi)發(fā)
每次進(jìn)行更新時(shí)都要運(yùn)行npm run build,站點(diǎn)越大,構(gòu)建所需的時(shí)間就越長(zhǎng),這樣就十分的煩瑣。為此可以為 webpack 設(shè)置兩種配置:
生產(chǎn)配置,用于最小化,優(yōu)化和刪除所有源映射
開(kāi)發(fā)配置,該配置在服務(wù)器中運(yùn)行webpack,每次更改都會(huì)更新,并具有源映射
開(kāi)發(fā)模式下是在內(nèi)存中運(yùn)行所有內(nèi)容,而不是構(gòu)建一個(gè)dist文件,需要安裝 webpack-dev-server
npm i -D webpack-dev-server
出于演示目的,我們可以僅將開(kāi)發(fā)配置添加到正在構(gòu)建的當(dāng)前webpack.config.js文件中并對(duì)其進(jìn)行測(cè)試。但是,我們開(kāi)發(fā)一般要?jiǎng)?chuàng)建兩個(gè)配置文件:一個(gè)生產(chǎn)環(huán)境用的 mode: production,一個(gè)開(kāi)發(fā)環(huán)境用的mode: development。
const webpack = require('webpack') module.exports = { /* ... */ mode: 'development', devServer: { historyApiFallback: true, contentBase: path.resolve(__dirname, './dist'), open: true, compress: true, hot: true, port: 8080, }, plugins: [ /* ... */ // Only update what has changed on hot reload new webpack.HotModuleReplacementPlugin(), ], })
我們添加mode: development,并創(chuàng)建devServer屬性,其中,默認(rèn)端口將為8080,自動(dòng)打開(kāi)瀏覽器窗口,并使用hot-module-placement,這需要webpack.HotModuleReplacementPlugin插件。這樣模塊執(zhí)行更新而無(wú)需完全重新加載頁(yè)面-因此,如果你更新某些樣式,則這些樣式將發(fā)生變化,并且不用重新加載整個(gè) JS ,大大加快了開(kāi)發(fā)速度。
現(xiàn)在,可以使用webpack serve命令來(lái)啟動(dòng)項(xiàng)目。
package.json
"scripts": { "start": "webpack serve" }
npm start
運(yùn)行此命令時(shí),將在瀏覽器中自動(dòng)彈出一個(gè)指向localhost:8080的鏈接?,F(xiàn)在,您可以更新Sass和JavaScript,并觀看其動(dòng)態(tài)更新。
到此,相信大家對(duì)“怎么從頭開(kāi)始設(shè)置webpack 5”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!