一次webapck4 配置檔案無效的解決歷程

瀟湘待雨發表於2019-02-28

前言

升級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 使用相應模式的內建優化

  1. production支援所有型別的優化已生成最優bundles
  2. development允許註釋、提示和eval devtooldevtool的差別可以參考這裡
  3. production不支援watching、development針對快速增量重建進行了優化
  4. production支援 module concatenating(Scope Hoisting)即作用域提升,可以將模組打包在一個函式裡,這樣減少了函式宣告,檔案體積也會減小。詳細參考看這裡
  5. process.env.NODE_ENV被設定用來區分環境(僅僅在構建程式碼而非config裡面)
  6. 有一個hidden none mode的模式可以禁用所有內容

用法:

  1. 配置檔案中:

    module.exports = {
    entry: Entrys,
    mode: `development`
    }
    複製程式碼
  2. 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之前執行是正確的。

結尾

當遇到不可思議的問題的時候,建議靜下心看一看,不要盲目搜尋,另外最可靠的參考就是官方文件和例項,注意對比版本和環境,如果都沒問題,那麼再去嘗試網上的各種解決方法。
這裡總結一下給自己一個記錄,希望解決思路能幫助其他人。

相關文章