1. 程式人生 > >React編譯環境配置:webpack3遷移至webpack4

React編譯環境配置:webpack3遷移至webpack4

這次我們以inputPassword元件為例,將編譯配置環境 從webpack3遷移至webpack4,新裝的webpack版本是4.14,但是配置檔案還是用的webpack3的配置。

先來看看pack.json檔案:

{
  "name": "react-inputpassword",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack --config ./build/webpack.config.js",
    "start": "webpack-dev-server --config ./build/webpack.config.js",
    "dev": "webpack --config ./build/webpack.dev.config.js",
    "build": "webpack --progress --profile --colors --config ./build/webpack.pro.config.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jean0218/react-inputPassword.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/jean0218/react-inputPassword/issues"
  },
  "homepage": "https://github.com/jean0218/react-inputPassword#readme",
  "dependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "^0.28.11",
    "enzyme-adapter-inferno": "^1.3.0",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-test-renderer": "^16.4.1",
    "style-loader": "^0.21.0",
    "webpack": "^4.14.0",
    "webpack-dev-server": "^3.1.4",
    "webpack-merge": "^4.1.3"
  },
  "devDependencies": {
    "babel-jest": "^23.2.0",
    "enzyme": "^3.3.0",
    "enzyme-adapter-react-16": "^1.1.1",
    "jest": "^23.3.0"
  }
}

找到webpack配置檔案,放在build目錄下,原有webpack檔案配置如下:

webpack.base.config.js(webpack基礎配置)

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const fileEntry = require('./fileEntry.js');

const webpackBaseConfig = {
    resolve: {
        extensions: [".js", ".json", ".jsx"],
        alias: {
            images: path.resolve(__dirname, '../examples/static/images'),
        }
    },

    entry: {
        examples:path.resolve(__dirname, '../examples/index.js'),
        demo01:path.resolve(__dirname, '../examples/demo01.js')
    },
    
    module: {
        noParse: /node_modules\/(jquey\.js)/,
        rules: [{
            test: /\.(js|jsx)$/,
            use: [{
                loader: 'babel-loader',
                options: {
                    "presets": [
                        "es2015", 'stage-0', 'react'
                    ]
                }
            }]       
        },{
            test: /\.(png|jpg|gif)$/,
            use: [{
                loader: 'file-loader',
                options: {
                    limit: 25000,
                    name: 'images/[name][hash:6].[ext]',
                    // 我們選擇載入的圖片格式為png,jpg,jpeg,gif,並限定當檔案小於25kb,轉換為base64編碼。
                    // 優勢:將一些小並且不常更新的圖片轉換base64編碼後,可以減少一次或多次http請求。
                    // 但這個limit應該定義成一個合適的值,因為如果將稍大些的圖片轉為base64後,會生成大量字元,
                    // 反而降低我們的載入速度。
                }
            }]
        },{
            test: /\.(woff|woff2|eot|ttf|svg|otf)$/,
            loader: 'file-loader',
            options: {
                name: 'fonts/[name].[ext]'
            }
        }]
    },

    plugins: [
        new webpack.optimize.ModuleConcatenationPlugin(),
    ],
}

fileEntry.map(function(item) {//新檔案輸出 
    webpackBaseConfig.entry[item.fileName] =  path.resolve(__dirname, item.sourceFile);
    const chunksSort = item.chunks
    const htmlPackage = new HtmlWebpackPlugin({
        //favicon: 'path/to/yourfile.ico',//給生成的 html 檔案生成一個 favicon
        title: item.title, //生成的html文件的標題
        template: path.resolve(__dirname, item.template),
        filename: item.targetFile, //輸出檔案的檔名稱,預設為index.html,可以配置輸出檔案指定目錄位置,例如'html/index.html'
        //filename配置的html檔案目錄是相對於webpackConfig.output.path路徑而言的,不是相對於當前專案目錄結構的。
        //指定生成的html檔案內容中的link和script路徑是相對於生成目錄下的,寫路徑的時候請寫生成目錄下的相對路徑。
        //hash: false,//true|false,是否為所有注入的靜態資源新增webpack每次編譯產生的唯一hash值
        showErrors: true, //是否將錯誤資訊輸出到html頁面中,便於除錯
        //inject: 'body', //所有JavaScript資源插入到body元素的底部
        chunks: item.chunks,
        //允許插入到模板中的一些chunk,不配置此項預設會將entry中所有的thunk注入到模板中。
        //在配置多個頁面時,每個頁面注入的thunk應該是不相同的,需要通過該配置為不同頁面注入不同的thunk;
        //excludeChunks: ,//這個與chunks配置項正好相反,用來配置不允許注入的thunk。
        chunksSortMode: (argument, argument2) =>{
            //none | auto| function,預設auto; 允許指定的thunk在插入到html文件前進行排序。
            //function值可以指定具體排序規則;auto基於thunk的id進行排序; none就是不排序
            var aIndex = chunksSort.indexOf(argument.names[0]);
            var bIndex = chunksSort.indexOf(argument2.names[0]);
            aIndex = aIndex < 0 ? chunksSort.length + 1 : aIndex;
            bIndex = bIndex < 0 ? chunksSort.length + 1 : bIndex;
            return aIndex - bIndex;
        } 
    });           
    webpackBaseConfig.plugins.push(htmlPackage);
});

module.exports = webpackBaseConfig;

其中的fileEntry.js檔案主要用於生成html檔案,這裡就不再貼出來了。

webpack.config.js(本地執行環境配置)

const webpack = require('webpack');
const path = require('path');
const webpackBaseConfig = require('./wepback.base.config.js');
const merge = require('webpack-merge');
const outputDir = 'dist';



const webpackConfig = merge(webpackBaseConfig, {
    devtool: 'cheap-module-eval-source-map',
    output: {
        path: path.resolve(__dirname, '../' + outputDir + '/'),
        filename: 'js/[name].js',
        chunkFilename: 'js/[name].chunks.js',
    },
    module: {
        rules: [
            {
                test: /\.css$/, 
                use:[
                    'style-loader',
                    'css-loader'
                ]
            }
        ],
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
    ],
});


module.exports = webpackConfig;

我們來看看webpack4相對於3新增了哪些內容:

1、不止需要安裝webpack,還需要安裝webpack-cli

在webpack3中,webpack本身和它的cli以前都在同一個包中,但在第4版中,它們兩者已經分開,所以我們的webpack需要安裝兩個包,全域性安裝webpack

 npm install webpack -g

再全域性安裝webpack-cli

npm install webpack-cli -g

安裝完成後出現版本提示,就說明該包已經安裝成功。

(這個安裝是在配置react-loadList元件時截圖的,除了專案不同其它都是一樣的)

2、新增了mode引數來表示生產還是開發

按照以上配置,我們執行 npm run start,檔案能正常編譯,但會看到如下警告:

這個警告告訴我們,'mode'選項沒有被設定,必須設定'mode'選項。webpack4新增了mode引數來表示生產還是開發,新增的引數有兩個可選值:development和production。不可預設,預設就會像上圖一樣報警告,其中

production 模式:

  • 預設提供所有可能的優化,如程式碼壓縮/作用域提升等

  • 不支援 watching

  • process.env.NODE_ENV 的值不需要再定義,預設是 production

development 模式:

  • 主要優化了增量構建速度和開發體驗

  • process.env.NODE_ENV 的值不需要再定義,預設是 development

  • 開發模式下支援註釋和提示,並且支援 eval 下的 source maps

可以在pack.json中配置

webpak --mode development

也可以配置檔案中配置:

mode:'development',
devtool: 'cheap-module-eval-source-map',

如果原有的檔案中有new webpack.DefinePlugin,加上mode選項後,則需要刪除 

new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") })

再執行npm run start,這個時候警告已經沒有了。

3、rules中需要增加type型別,指定模組型別

webpack 4之前,js 是 webpack 中的唯一模組型別,因而不能有效地打包其它型別的檔案。而 webpack 4 則提供了 5 種模組型別:

  • javascript/auto: (webpack 3中的預設型別)支援所有的JS模組系統:CommonJS、AMD、ESM
  • javascript/esm: EcmaScript 模組,在其他的模組系統中不可用(預設 .mjs 檔案)
    • 相較於javascript/auto模式更嚴格,匯入的名稱必須存在於匯入的模組中
    • 動態的模組(非ESM, 如CommonJs)只能通過import匯入,其它方式的匯入都會報錯
  • javascript/dynamic: 僅支援 CommonJS & AMD,EcmaScript 模組不可用
  • json: 可通過 require 和 import 匯入的 JSON 格式的資料(預設為 .json 的檔案)
  • webassembly/experimental: WebAssembly 模組(處於試驗階段,預設為 .wasm 的檔案)

(我在看到這塊時,產生了一個疑問,這些都是js的模型,圖片、字型類的不需要增加type型別麼?待以後有機會再補充)

5、CommonsChunkPlugin需要替換

     本次更新內容中沒有這一項,暫時不編寫,以後更新。

這樣,我們的webpack3成功遷移至4了,相對於2遷移至3是不是簡單了很多。

參考: