前言
升級webpack4,一定要去看文件,特別是更新說明,不要自持用過原本webpack就自己開始折騰。折騰到後面,可能就默默流下眼淚了。
webpack4的變化
webpack-cli抽離
webpack-cli被單獨拆了出來,使用的時候如果只是全域性裝了CLI,直接執行的時候是可以的。
webpack --config ./config/webpack.dev.js
複製程式碼
如果是寫在npm hook裡面會發現有點問題:
//package.json
"scripts": {
"dev": "webpack --config ./config/webpack.dev.js"
}
//shall
npm run dev
複製程式碼
此時就會給提示:
One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:
- webpack-cli (https://github.com/webpack/webpack-cli)
The original webpack full-featured CLI.
- webpack-command (https://github.com/webpack-contrib/webpack-command)
A lightweight, opinionated webpack CLI.
We will use "npm" to install the CLI via "npm install -D".
Which one do you like to install (webpack-cli/webpack-command):
複製程式碼
如果是我沒有全域性裝,我肯定會意識到要選一個,這個坑關鍵是我全域性裝了。所以就在那折騰半天。
其實官方文件開頭就說明了。
npm install webpack webpack-cli --save-dev
複製程式碼
安裝完成之後,繼續執行發現有warning:
WARNING in configuration
The `mode` option has not been set, webpack will fallback to `production` for this value. Set `mode` option to `development` or `production` to enable defaults for each environment.
You can also set it to `none` to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
複製程式碼
mode規則
配置規則:必須在production 和 development之間選擇一種,以便webpack 使用相應模式的內建優化
- production支援所有型別的優化已生成最優bundles
- development允許註釋、提示和eval devtooldevtool的差別可以參考這裡
- production不支援watching、development針對快速增量重建進行了優化
- production支援 module concatenating(Scope Hoisting)即作用域提升,可以將模組打包在一個函式裡,這樣減少了函式宣告,檔案體積也會減小。詳細參考看這裡
- process.env.NODE_ENV被設定用來區分環境(僅僅在構建程式碼而非config裡面)
- 有一個hidden none mode的模式可以禁用所有內容
用法:
-
配置檔案中:
module.exports = { entry: Entrys, mode: `development` } 複製程式碼
-
cli 引數傳入
webpack --mode=development 複製程式碼
兩種方式都是可行的,不過我遇到過一個很坑的問題,困擾自己好幾天,最後知道真相的自己眼淚掉下來後面再提這個問題。
零配置快速開始
因為一直被吐槽配置太累,加上parcel給的壓力,webpack4也支援零配置打包了。
如果沒有配置檔案,會預設以./src/index.js作為entry開始打包。
如果配置了webpack.config.js或者指定了–config 的檔案路徑,則依據對應配置檔案開始。
問題表現
在webpack.config.js中配置了entry、mode等相關屬性,配置檔案如下:
module.export = {
mode:`production`,
entry:{
app:`./src/test.js`,
index:`./src/test.js`
},
output: {
path: process.cwd() + `/dist`,
filename: `[name].[hash].js`,
chunkFilename: `[name].[chunkhash].js`,
crossOriginLoading: `anonymous`
},
cache: true,
devtool: `cheap-source-map`,
externals: {
jquery: `jQuery`
},
module: {
rules: [
{
test: /.(js|jsx)?$/,
include: [
path.resolve(__dirname, "../src")
],
exclude: [
`node_modules`,
path.resolve(__dirname, "../node_modules")
],
use: [
{
loader: `babel-loader`,
options:{
presets:[`es2015`]
}
}
]
}
]
},
resolve: {
modules: [
`node_modules`
],
extensions: [".js", ".json", ".jsx", ".css"],
},
devServer: {
proxy: { // proxy URLs to backend development server
`/api`: `http://localhost:3000`
},
contentBase: path.resolve(__dirname, "../dist"),
hot: true,
open:true
},
plugins: [
new CleanWebpackPlugin([`dist`]),
new HtmlWebpackPlugin({
title:`test`
}),
new webpack.HotModuleReplacementPlugin()
]
}
複製程式碼
package.json命令配置:
"scripts": {
"build": "webpack --config webpack.prod.js"
}
//執行打包
npm run build
複製程式碼
發現始終會有上面選擇mode型別的提示,這讓人不能接受,另外提示沒有./src/index.js檔案,但是我的配置入口是別的檔案,這樣讓人很莫名
ERROR in Entry module not found: Error: Can`t resolve `./src` in `/Users/****`
複製程式碼
本著跟著提示解決問題的原則,少檔案那就建一個唄(後來發現這種思維有時候有用,有時候還真要慎重),問題表現雖然一致,實質可能有所不同。
新建之後是可以執行了但是我們的配置檔案好像沒起作用,
dist下的打包檔案是預設的main.js
而非我們指定的app和index
為了確保進入配置檔案,我打了幾個log,竟然都有輸出,說明進去了,這問題就詭異了。
console.log(path.resolve(__dirname, `./src`)) //輸出正確路徑
module.export = {
//*****//
}
複製程式碼
版本統一
初步猜想是版本問題,確實也有issue上提到過某些版本存在問題,對照著官方demo鎖定版本之後問題依然存在。
猜測:應該是配置檔案存在錯誤
配置檢查
將官方最基本的配置拉進來拷貝進來試了一下,依然存在問題沒能解決。
猜測:本地的環境存在問題,npm,node等版本
檢視之後發現版本都是滿足的。
執行demo
將demo拉到本地並啟動,demo正常打包,說明本地環境是ok的。那麼問題就明顯了,我的配置檔案或者專案搭建有問題,對照著demo的配置項,配置項沒有明顯問題,這樣的話將,配置資訊放入到demo中去,修改之後發現起作用,我又重新審視了下我的配置檔案,不僅僅侷限於配置部分的時候,發現
//我的寫法,這樣webpack拿到的就是undefined了。
module.export
//別人的demo
module.exports
複製程式碼
webpack的相容處理
webpack會將 webpack –config 傳入的檔案與本身預設配置進行merge,保證本身打包不出錯。為了證明我們的推論,將配置檔案只剩下output屬性,並加上src/index.js
module.exports = {
output: {
path: process.cwd() + `/dist1`,
// 直接的入口模zzz塊名
filename: `[name].js`,
// 非入口模組,也就是不需要打包到一起的,但又可能會用到,
// 這不就是按需載入的麼
chunkFilename: `[name].[chunkhash].js`,
crossOriginLoading: `anonymous`
}
}
複製程式碼
執行之後會發現打包到/dist1下面。所以上面寫錯module.exports的時候,走的完全是預設配置。前面的log打在了module.exports之前執行是正確的。
結尾
當遇到不可思議的問題的時候,建議靜下心看一看,不要盲目搜尋,另外最可靠的參考就是官方文件和例項,注意對比版本和環境,如果都沒問題,那麼再去嘗試網上的各種解決方法。
這裡總結一下給自己一個記錄,希望解決思路能幫助其他人。