在上一篇 Webpack 快速上手中慷嗜,我們對(duì) Webpack 已經(jīng)有了一個(gè)大概的了解洞斯,現(xiàn)在我們開(kāi)始了解 Webpack 的配置屡萤。
webpack.config.js
const path = require('path');
// 引入 html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入 clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const time = new Date().getTime()
module.exports = {
// 入口
// entry: './src/index.js',
entry: {
index: './src/index.js',
print: './src/print.js',
another: './src/another_module.js'
},
devServer: {
contentBase: './dist', // 資源位置
host: 'localhost', // 服務(wù)器地址先匪,如果需要在其他 PC 上訪問(wèn)坤按,則將 'localhost' 改為 '0.0.0.0'
port: '8080',
hot: true // 熱加載
},
devtool: 'eval-cheap-module-source-map', // source-map 模式
// 插件
plugins: [
// 清理 ./dist 目錄無(wú)用的文件
new CleanWebpackPlugin(),
// new webpack.HotModuleReplacementPlugin(),
// 生成 html 文檔,并自動(dòng)引入「輸出」文檔
new HtmlWebpackPlugin({
title: '管理輸出'
})
],
// 輸出
output: {
// filename: 'main.js',
filename: '[name].bundle.' + time + '.js', // 輸出文件名格式
path: path.resolve(__dirname, 'dist') // 輸出文件位置
},
// 代碼分離盲厌,將重復(fù)引用的代碼分離出來(lái)
optimization: {
splitChunks: {
chunks: 'all'
}
},
// 模塊
module: {
rules: [
{
// 樣式加載模塊
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
// 圖像加載模塊
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
},
{
// 字體加載模塊
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource'
},
/*********** 數(shù)據(jù)加載模塊 >>> ************/
{
// csv 加載模塊
test: /\.(csv|tsv)$/i,
use: ['csv-loader']
},
{
// xml 加載模塊
test: /\.xml$/i,
use: ['xml-loader']
}
// json 加載模塊:因 nodejs 默認(rèn)支持 JSON 加載署照,所以無(wú)需再安裝第三方模塊
/*********** <<< 數(shù)據(jù)加載模塊 ************/
, {
// babel 加載模塊
test: /\.js$/,
// exclude: /(node_mod)/
loader: 'babel-loader',
// include: [resolve('src'), resolve('node_modules/webpack-dev-server/client')]
// use: {
// loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
// }
}
]
}
}
對(duì)應(yīng)的 package.json
{
"name": "webpack-test",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"_start": "webpack serve --open firefox",
"start": "webpack serve --inline --progress",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"csv-loader": "^3.0.3",
"html-webpack-plugin": "^4.5.0",
"style-loader": "^2.0.0",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0",
"xml-loader": "^1.2.1"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"lodash": "^4.17.20"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
分步講解
入口
entry
在此我們可以看到,entry
由單條更改為了對(duì)象方式吗浩,也就是說(shuō)建芙,我們的入口不僅僅可以只有一個(gè),更是可以擁有多個(gè)入口拓萌。通過(guò)上一篇文章的學(xué)習(xí)岁钓,我們知道 webpack 可以打包使用了的資源,而entry
提供了一個(gè)打包的入口微王,通過(guò)這個(gè)入口屡限,就可以將入口文件里面所有相關(guān)的資源(遞歸搜索)打包在一起。-
開(kāi)發(fā)模式下的小服務(wù)器
devServer
webpack-dev-server
提供了一個(gè)簡(jiǎn)單的 web 服務(wù)器炕倘,并且能夠?qū)崟r(shí)重新加載(live reloading)钧大。執(zhí)行命令安裝
webpack-dev-server
:
npm install webpack-dev-server -D --registry=https://registry.npm.taobao.org
進(jìn)行如上配置之后,可以在 package.json
中增加腳本啟動(dòng)方式 start
:
{
"name": "webpack_test",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --inline --progress",
"build": "webpack"
},
"keywords": [],
"...": ...
}
然后在命令行中執(zhí)行如下命令啟動(dòng)服務(wù)器
npm start
此處僅為示例罩旋,更多配置請(qǐng)參考 webpack-dev-server
-
開(kāi)發(fā)工具
devtool
此選項(xiàng)控制是否生成啊央,以及如何生成 source map眶诈。我們打包過(guò)后的代碼和我們自己寫(xiě)的源碼是不一樣的,如果沒(méi)有 source map 瓜饥,那么在開(kāi)發(fā)過(guò)程中調(diào)試程序的時(shí)候逝撬,代碼報(bào)錯(cuò)時(shí),我們無(wú)法將錯(cuò)誤準(zhǔn)確的定位到我們的源碼中乓土。
有關(guān)詳細(xì)信息請(qǐng)參考 Devtool
-
插件
plugins
plugins
選項(xiàng)用于以各種方式自定義 webpack 構(gòu)建過(guò)程宪潮。webpack 附帶了各種內(nèi)置插件,可以通過(guò)webpack.[plugin-name]
訪問(wèn)這些插件趣苏。請(qǐng)查看 插件頁(yè)面 獲取插件列表和對(duì)應(yīng)文檔狡相, 但請(qǐng)注意這只是其中一部分,社區(qū)中還有許多插件食磕。如果你想自己寫(xiě)一個(gè)插件尽棕,請(qǐng)參考如何 編寫(xiě)一個(gè)插件
這里我緊用了幾個(gè)插件示例。
html-webpack-plugin
插件:可以為我們動(dòng)態(tài)生成 html 文檔彬伦,并自動(dòng)引入「output」打包之后的文檔到該 html 文檔中滔悉。clean-webpack-plugin
插件:在我們每次打包工程之前,它將為我們清空目標(biāo)輸出目錄媚朦,以保證輸出目錄中的資源都是我們最后需要的氧敢。 -
輸出
output
可以通過(guò)配置 output 選項(xiàng)日戈,告知 webpack 如何向硬盤(pán)寫(xiě)入編譯文件询张。注意,即使可以存在多個(gè) entry 起點(diǎn)浙炼,但只能指定一個(gè) output 配置份氧。此屬性的最低要求,是為其配置一個(gè)輸出文件的文件名
output.filename
output: {
filename: 'bundle.js',
}
如果是多個(gè)入口起點(diǎn)
output: {
// filename: 'main.js',
// 輸出文件名格式
filename: '[name].bundle.' + time + '.js',
// 輸出文件位置
path: path.resolve(__dirname, 'dist')
}
更多配置請(qǐng)參考 output
-
代碼分離
optimization
此特性能夠把代碼分離到不同的 bundle 中弯屈,然后可以按需加載或并行加載這些文件蜗帜。代碼分離可以用于獲取更小的 bundle,以及控制資源加載優(yōu)先級(jí)资厉,如果使用合理厅缺,會(huì)極大影響加載時(shí)間。常用的代碼分離方法有三種:
-
入口起點(diǎn):使用
entry
配置手動(dòng)地分離代碼宴偿。 -
防止重復(fù):使用 Entry dependencies 或者
SplitChunksPlugin
去重和分離 chunk湘捎。 - 動(dòng)態(tài)導(dǎo)入:通過(guò)模塊的內(nèi)聯(lián)函數(shù)調(diào)用來(lái)分離代碼。
這里用了「防止重復(fù)」的方式窄刘,并使用了
SplitChunksPlugin
插件窥妇,可以將公共的依賴模塊提取到已有的入口 chunk 中,或者提取到一個(gè)新生成的 chunk娩践。 -
入口起點(diǎn):使用
-
模塊
module
模塊 選項(xiàng)決定了如何處理項(xiàng)目中的 不同類(lèi)型的模塊活翩。在這里我使用了一些加載模塊
loader
烹骨,都在rules
中配置。這些loader
可能來(lái)自第三方材泄,需要我們單獨(dú)安裝它們才能正常使用沮焕。[Rule]
創(chuàng)建模塊時(shí),匹配請(qǐng)求的規(guī)則數(shù)組拉宗。這些規(guī)則能夠修改模塊的創(chuàng)建方式遇汞。 這些規(guī)則能夠?qū)δK(module)應(yīng)用 loader,或者修改解析器(parser)簿废。