Webpack 知識梳理
-
entry(入口)
單入口——單頁面應用
多入口——多頁面應用
-
output(輸出)
path: 輸出路徑(必須是絕對路徑) path.resolve
filename: 輸出檔名
-
loaders
編譯檔案
-
plugins(外掛)
webpack 功能擴充套件
1.2 相關知識(Node.js & ES6 模組化)
1.2.1 Node.js
Node.js 是 javascript的伺服器版本,Webpack 在執行打包壓縮時是依賴 Node.js 的。
1.2.2 ES6 模組化
1.2.2.1 export 匯出
//分別匯出一個或幾個變數(函式) export let a = 1; export const b = 2; export function fn(){ console.log('fn') } //匯出一個物件 let a = 1; const b = 2; function fn(){ console.log('fn') } export { a, b, fn }; //匯出預設成員——僅能匯出一個,預設引入的就是這一個 export default let a = 1; 複製程式碼
1.2.2.2 import 匯入
//引入所有成員(as —— 給引入的值重新命名) import * as name from 'xxx'; //引入 default 成員 import a from 'xxx'; //只引入:引入 css 或 函式 import 'xxx'; //非同步引入 let a =import("./util"); 複製程式碼
2.開始使用 Webpack —— 搭建專案
2.1 新建專案,安裝 Webpack 依賴。
npm init npm i webpack webpack-cli --save-dev 複製程式碼
安裝 webpack-cli 才能在命令列執行 webpack 命令。
2.2 建立並配置 webpack.config.js
- 單入口 | 單輸出 根目錄內新建
src
資料夾,新建index.js
檔案。
index.js 檔案:
console.log('index') 複製程式碼
webpack.config.js 檔案
const path = require('path') module.exports = { entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.min.js' } } 複製程式碼
- 多入口 | 多輸出 根目錄內新建
src
資料夾,新建index.js
及home.js
檔案。
index.js 檔案:
console.log('index') 複製程式碼
home.js 檔案:
console.log('home') 複製程式碼
webpack.config.js 檔案
const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 } } 複製程式碼
2.3 配置 package.json 檔案,驗證基本配置
- 修改
script
屬性:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, 複製程式碼
- 執行
npm run build
執行webpack
命令,驗證輸入輸出配置。 根目錄內會生成dist
資料夾,裡面有對應的檔案生成。
2.4 在 index.html 中引入打包好的 js 檔案
方式一:手動引入新建 index.html,並直接手動引入 js 檔案。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> <script src='./dist/index.min.js'></script> <script src='./dist/home.min.js'></script> </html> 複製程式碼
開啟 index.html,即已成功引入編譯好的 index.min.js 及 home.min.js,執行裡面的程式碼。
3.plugins —— 擴充套件 webpack 功能
前面已經可以使用 webpack ,但開發過程中,每次都要手動引用 js 檔案,更改程式碼後還要重新編譯是很麻煩的,所以我們接下來看下 webpack 的 plugins,來便於開發。
3.1 自動生成 html
可通過外掛 html-webpack-plugin
,由指定的 html
模板生成新的 html
檔案,並自動引入所需 js
等內容。 1)執行 npm i html-webpack-plugin --save-dev
命令,安裝依賴。 2)新建 index.ejs
檔案
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> </body> </html> 複製程式碼
3)修改 webpack.config.js
的配置:
const HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 }, plugins: [ new HtmlWebpackPlugin({ // 打包輸出HTML title: 'New HTML',//打包後生成 html 的 title minify: { // 壓縮 HTML 檔案 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的檔名 template: 'index.ejs' // 根據此模版生成 HTML 檔案 }) ] } 複製程式碼
4)重新執行 npm run build
,生成新的 dist
包,包內會生成一個新的 index.html
檔案,並自動引入了 index.min.js
檔案。

index.html 檔案
<!DOCTYPE html><html><head><meta http-equiv="Content-type" content="text/html; charset=utf-8"><title>New HTML</title></head><body><div id="root"></div><script type="text/javascript" src="index.min.js"></script><script type="text/javascript" src="home.min.js"></script></body></html> 複製程式碼
3.2 再次打包時刪除舊檔案
3.2.1 修改 webpack.config.js
將輸出的 index.html
檔名改為其他的,如 indexNew.html

npm run build
,生成的
dist
內檔案列表如下:

index.html
還在,這裡可以使用外掛
clean-webpack-plugin
來刪除
webpack.config.js
中
output.path
目錄中的所有檔案。
3.2.2 執行 npm install clean-webpack-plugin --save-dev
安裝依賴。
3.2.3 修改 webpack.config.js
配置。

3.2.4 再次執行 npm run build
,生成的 dist
內檔案列表如下:

index.html
檔案已被刪除。
3.3 自動開啟 html
檔案,支援熱更新
3.3.1安裝依賴
npm i open-browser-webpack-plugin webpack-dev-server --save-dev
3.3.2 修改 webpack.config.js
配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin') const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動開啟瀏覽器 const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 }, plugins: [ new HtmlWebpackPlugin({ // 打包輸出HTML title: 'New HTML', //打包後生成 html 的 title minify: { // 壓縮 HTML 檔案 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的檔名 template: 'index.ejs' // 根據此模版生成 HTML 檔案 }), // 預設情況下,此外掛將刪除 webpack output.path目錄中的所有檔案。 new CleanWebpackPlugin(), new OpenBrowserPlugin({ url: 'http://localhost:8080' }) ] } 複製程式碼
3.3.3 修改 package.json
新增 start
,使得執行 npm run start
可直接執行 webpack-dev-server
命令。
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server", "build": "webpack" }, 複製程式碼
3.3.4 測試
執行 npm run start
: 1)瀏覽器會自動開啟 http://localhost:8080
; 2)修改 index.js
檔案,儲存檔案,瀏覽器會自動重新整理,更新內容。
3.4 程式碼除錯定位 —— sourcemap
程式碼經過編譯、打包後,與原始碼已有很大差異,不便於除錯。
source-map 會解決這個問題,生成 .map 檔案,便於錯誤定位除錯。
開啟方法:在 webpack.config.js 檔案中新增一行配置: devtool: "source-map"
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin') const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動開啟瀏覽器 const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 }, plugins: [ new HtmlWebpackPlugin({ // 打包輸出HTML title: 'New HTML', //打包後生成 html 的 title minify: { // 壓縮 HTML 檔案 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的檔名 template: 'index.ejs' // 根據此模版生成 HTML 檔案 }), // 預設情況下,此外掛將刪除 webpack output.path目錄中的所有檔案。 new CleanWebpackPlugin(), new OpenBrowserPlugin({ url: 'http://localhost:8080' }) ], //編譯前檔案除錯 devtool: "source-map" } 複製程式碼
如上,即可。可通過列印等方式進行測試。
4. loader
loader ——檔案編譯。
4.1 ES6 & React 編譯 —— babel-loader
Babel 是一個 JavaScript 編譯器,Webpack 使用 babel-loader 來編譯 ES6。 此處我們要建立一個 React 專案,所以同時也要見天 React 的相關依賴即配置。
4.1.1 安裝依賴
yarn add babel babel-core [email protected] babel-preset-env babel-preset-react
注: 現在直接安裝 babel-core 和 babel-loader,安裝的版本不對應會報錯,所以我在安裝時指定了 babel-loader 的版本,避免這個問題。
4.1.2 修改 webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin') const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動開啟瀏覽器 const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 }, plugins: [ new HtmlWebpackPlugin({ // 打包輸出HTML title: 'New HTML', //打包後生成 html 的 title minify: { // 壓縮 HTML 檔案 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的檔名 template: 'index.ejs' // 根據此模版生成 HTML 檔案 }), // 預設情況下,此外掛將刪除 webpack output.path目錄中的所有檔案。 new CleanWebpackPlugin(), new OpenBrowserPlugin({ url: 'http://localhost:8080' }) ], module: { rules: [ { test: /\.(js|jsx)$/i, use: [{ loader: "babel-loader", options: { presets: ["env", "react"], } }], exclude: /node_modules/ } ] } } 複製程式碼
4.1.3 修改 index.js 及 home.js 檔案為 react 語法
home.js檔案
import React, { Component } from 'react'; export default class Home extends Component { render() { return ( <div style={{backgroundColor: '#0f0'}}> home page </div> ); } } 複製程式碼
index.js檔案
import React from 'react'; import { render } from 'react-dom'; import Home from './home'; render(<Home/>, document.getElementById('root')); 複製程式碼
此時,頁面效果如下:

如上,React 語法被成功編譯。
4.2 處理 CSS 檔案 —— style-loader & css-loader
4.2.1 建立 index.css 檔案
.container { background-color: aquamarine } 複製程式碼
修改 home.js 檔案如下:
import React, { Component } from "react"; import './index.css' export default class Home extends Component { render() { return ( <div className="container"> home page </div> ); } } 複製程式碼
4.2.2 npm run start
重新啟動專案,專案會報錯如下:

4.2.3 安裝依賴
npm i style-loader css-loader --save-dev
4.2.4 修改 webpack.config.js 配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin') const OpenBrowserPlugin = require('open-browser-webpack-plugin') //自動開啟瀏覽器 const path = require('path') module.exports = { entry: { index: './src/index.js', home: './src/home.js', }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].min.js' //name為對應入口檔案的檔名 }, plugins: [ new HtmlWebpackPlugin({ // 打包輸出HTML title: 'New HTML', //打包後生成 html 的 title minify: { // 壓縮 HTML 檔案 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的檔名 template: 'index.ejs' // 根據此模版生成 HTML 檔案 }), // 預設情況下,此外掛將刪除 webpack output.path目錄中的所有檔案。 new CleanWebpackPlugin(), new OpenBrowserPlugin({ url: 'http://localhost:8080' }) ], module: { rules: [ { test: /\.(js|jsx)$/i, use: [{ loader: "babel-loader", options: { presets: ["env", "react"], } }], exclude: /node_modules/ }, { test: /\.css$/i, // 針對 .css 字尾的檔案設定 loader use: ['style-loader', 'css-loader'] } ] } } 複製程式碼
添加了針對 .css 檔案的 loader,來對 .css 檔案進行處理。

- css-loader:讀取並編譯 js 中引入的 css 檔案
- style-loader: html 中建立一個
<style></style>
標籤,裡面是 css-loader 解析出的 css 樣式。 - webpack 配置中,style-loader 必須在 css-loader 之前, 順序不可變 ,即必須先由 css-loader 處理,再由 style-loader 處理。
4.3 處理 LESS 檔案 —— less-loader
4.3.1 建立 index.less 檔案如下:
.container { background-color: aquamarine } 複製程式碼
修改 home.js 檔案如下:
import React, { Component } from "react"; import './index.less' export default class Home extends Component { render() { return ( <div className="container"> home page </div> ); } } 複製程式碼
4.3.2 安裝依賴
npm i less less-loader --save-dev
4.3.3 修改 webpack.config.js 配置,module/rules 下新增對於 less 檔案的解析:
{ test: /\.less$/, // 針對 .less 字尾的檔案設定 loader use: ['style-loader', 'css-loader', 'less-loader'] } 複製程式碼
4.3.4 重新啟動專案,less 檔案生效,頁面效果如下:

4.4 新增瀏覽器字首 —— postcss-loader & autoprefixer
autoprefixer 按照瀏覽器使用量決定需要新增哪些瀏覽器字首,postcss-loader 按照 autoprefixer 的結果來新增瀏覽器字首。
4.4.1 修改 index.less 檔案如下:
.container { background-color: aquamarine; transform: rotate(0deg); transition-duration: 1000ms; } .container:hover { background-color: aquamarine; transform: rotate(360deg) } 複製程式碼
4.4.2 安裝依賴
npm i less postcss-loader autoprefixer --save-dev
4.4.3 修改 webpack.config.js 配置,給 css、less 檔案新增 postcss-loader 的解析,
有兩種方式: 1)在 webpack.config.js 的 modele/rules 內指定 postcss-loader 的配置
{ test: /\.css$/, // 針對 .css 字尾的檔案設定 loader use: ['style-loader', 'css-loader', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }] }, { test: /\.(less|css)$/, // 針對 .less 字尾的檔案設定 loader use: ['style-loader', 'css-loader', 'less-loader', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }] } 複製程式碼
2)修改 webpack.config.js,並單獨建立 postcss.config.js ,進行配置 修改webpack.config.js 檔案,modele/rules 新增如下配置:
{ test: /\.css$/, // 針對 .css 字尾的檔案設定 loader use: ['style-loader', 'css-loader', 'postcss-loader'] }, { test: /\.(less|css)$/, // 針對 .less 字尾的檔案設定 loader use: ['style-loader', 'css-loader', 'less-loader', 'postcss-loader'] } 複製程式碼
postcss.config.js 檔案
module.exports = { plugins: [require('autoprefixer')] } 複製程式碼
相對比而言,我更傾向於第一種,以免建立太多的配置檔案,造成混亂。
4.4.4 重新啟動專案,檢視瀏覽器元素,樣式字首已新增成功。

如有需要,可以自己進行支援的瀏覽器版本配置,有兩種方式: 1)新增 .broserslistrc 檔案,進行配置
last 3 version//支援每個版本的最近三個版本 >2%//大於百分之二的使用者使用 複製程式碼
2)無需建立新檔案,直接在 package.json 檔案內新增屬性進行配置
"browserslist": [ "last 5 version", " >1%" ] 複製程式碼
重新啟動,效果如下:

按照設定的規則重新對我們的 css 樣式添加了字首。
4.5 處理圖片 —— file-loader & url-loader
4.5.1 引入圖片
src 資料夾下建立 images 資料夾,並新增 bg.png 圖片

修改 index.less 檔案如下:
.container { width: 100%; height: 600px; background: url('./images/bg.png'); background-size: 100%; background-repeat: no-repeat; } 複製程式碼
重新啟動專案,會報錯如下:

4.5.2 安裝依賴 —— file-loader
如上,需要配置對應的 loader 來解析圖片。
執行 npm i file-loader --save-dev
,安裝依賴。
4.5.3 更改配置 —— file-loader
修改 webpack.config.js 配置, modole/rule 下新增配置如下:
{ test: /\.(png|jpg|jpeg|gif)$/i, // 針對 .png|.jpg|.jpeg | .gif 字尾的圖片設定 loader use: [{ loader: 'file-loader', options: { outputPath: 'imgs/', //相對於 output.path 的輸出目錄 } }] } 複製程式碼
重啟專案,則引入圖片成功,效果如下:

file-loader 可以解析專案中的圖片引入,根據配置,將圖片輸出到相應路徑,並修改打包後文件中的引用路徑,使其指向打包後的檔案。
4.5.4 安裝依賴 —— url-loader
針對圖片引用,url-loader 封裝了 file-loader。 增加了 limit 屬性,檔案大小大於 limit 值,會呼叫 file-loader 進行處理; 檔案大小小於 limit 值,會將檔案轉為 base64 格式,以減少檔案請求次數。 安裝 url-loader 依賴
npm i url-loader --save-dev
4.5.5 更改配置 —— url-loader
修改 webpack.config.js 配置, modole/rule 下新增配置如下:
{ test: /\.(png|jpg|jpeg|gif)$/i, // 針對 .png|.jpg|.jpeg | .gif 字尾的圖片設定 loader use: [{ loader: 'url-loader', options: { outputPath: 'imgs/', //相對於 output.path 的輸出目錄 limit: 8*1024 //大於此數值依舊用 file-loader處理,打包到 imgs 裡面,小於此數值的轉為 base64,以減少檔案請求次數 } }] } 複製程式碼
重啟專案,圖片引用成功,執行 npm run build
,可發現,大於 8k 的圖片會被打包到 dist/imgs 資料夾內,小於 8k 的則不會被打包輸出,而是轉為 base64 。

4.6 處理文字 —— file-loader & url-loader
4.6.1 引入字型
src 資料夾下一個字型檔案——difital-7.ttf,這是一個液晶字型檔案,修改 index.less 檔案如下:

@font-face{ font-family: "digital"; src: url(./digital-7.ttf); } .container { width: 100%; height: 600px; background: url('./images/bgimg.jpg'); background-size: 100%; background-repeat: no-repeat; font-family: "digital" } 複製程式碼
儲存專案編譯後,會報錯如下:

4.6.2 更改配置
同圖片,需要配置對應的 url-loader 來解文字片,修改 webpack.config.js 配置, modole/rule 下新增配置如下:
{ test: /\.(eot|svg|ttf|woff|woff2)$/i, // 針對 eot|svg|ttf|woff|woff2 字尾的字型設定 loader use: [{ loader: 'url-loader', options: { outputPath: 'fonts/', //相對於 output.path 的輸出目錄 limit: 4*1024 //大於此數值依舊用 file-loader處理,打包到 fonts 裡面,小於此數值的轉為 base64,以減少檔案請求次數 } }] } 複製程式碼
重新啟動專案,則字型引用成功,效果如下:

通過修改 limit 值,重新打包,可測試 limit 值設定是否有效。
未完待續...