1. 程式人生 > >一次webapck4 配置檔案無效的解決歷程

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

前言

升級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之前執行是正確的。

結尾

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