通過不斷的調整和測試,關於 react 的 webpack 配置終於新鮮出爐。本次的重點主要集中在開發環境上,生產環境則是使用 webpack 的 production 默認模式。css
本次配置主要有:node
講真,對於初次接觸 webpack 的同窗,怕的可能不是 webpack 的配置,而是長長的 package.json。依賴那麼多,你怎麼就知道須要哪些依賴呢。不開玩笑,我還真知道。
webpack 的依賴主要是一些 loader 和 plugins。咱們知道單頁面引用被打包後,原有的結構基本上不復存在了。而以前引用的圖片或字體資源還按照以前的路徑查找,確定是找不到的。那麼咱們就須要轉換工具(順便轉換資源)—— url-loader
|file-loader
。
大多數人寫樣式時,喜歡使用 css、less、sass。這時也會有對應的工具 style-loader
, css-loader
, less-loader
。
想要使用 JavaScript 新特性或處理兼容性,就用 babel-loader
。以上這些基本上能夠應付一些簡單的項目。可實際上呢?react
我信你個鬼,你這個糟老頭壞的很!
看文檔啊,看官方介紹啊。本次也是經過看 babel 文檔,和一些依賴文檔來配置 webpack 的,全程無壓力,並且很正宗。因此,文檔很重要。webpack
若是時團隊合做,代碼規範是很重要的。能夠經過 eslint+prettier 規範。這兩個工具各有側重點,不過官網也提供了二者結合的方案。詳細介紹見官網。我我的不習慣建立太多的配置文件,因此都放在了 package.json 文件中。es6
// webpack.common.js { enforce: "pre", test: /\.m?jsx?$/, exclude: /node_modules/, loader: "eslint-loader", options: { fix: true, cache: true, formatter: require("eslint-friendly-formatter"), } },
"eslintConfig": { "parser": "babel-eslint", "env": { "browser": true, "es6": true, "node": true }, "parserOptions": { "ecmaVersion": 6, "sourceType": "module" }, "extends": [ "plugin:prettier/recommended" ] }, "prettier": { "singleQuote": true, "semi": true },
開發環境沒什麼好說的了,簡單易配置,官網很詳細。web
// webpack.dev.js plugins: { //... new webpack.HotModuleReplacementPlugin() }, devtool: "eval-source-map", devServer: { contentBase: path.resolve(__dirname, '..', 'dist'), port: APP_CONFIG.port, hot: true, open: true } // index.js // 入口處要配置這些,別忘了。 // 由於有冒泡的機制,因此在頂端加一個就好。 if (module.hot) { module.hot.accept('./views/login/index.js', () => { render(App) // 渲染應用 }) }
這個配置是用來分割包的。在性能優化上,請求數和請求包的大小也是很重要的優化點。請求數量和請求數據大小要控制在合理的範圍內。
不過一般狀況下,咱們會將包分割爲內容不變的部分和內容變化的部分。這不單單是爲了將大的包分割成更小的包,也是爲了可以充分利用緩存機制。npm
// webpack.common.js runtimeChunk: 'single', splitChunks: { cacheGroups: { verdor: { test: /[\\/]node_modules[\\/]/, name: 'verdors', chunks: 'all', priority: -10, }, common: { name: 'common', chunks: 'all', minChunks: 2, priority: -20, } } }
轉換文件算是打包過程當中比較耗時的事情,經過 happypack 能夠將這件事分攤給多個 node 進程,這樣就會大大縮短了打包時間(同理,能夠考慮使用 thread-loader
)。不過進程之間的通訊是要開銷的,這是一個優化方向,要不要採用,還須要酌情考慮。json
// loader { test: /\.m?jsx?$/, exclude: /node_modules/, use: 'happypack/loader?id=js', } // plugins new HappyPack({ id: 'js', threadPool: happyThreadPool, loaders: [{ loader: 'babel-loader', options: { cacheDirectory: true, presets: [['@babel/preset-env', { "useBuiltIns": "usage", "corejs": 3 }], "@babel/preset-react"], plugins: ['@babel/transform-runtime', "@babel/plugin-proposal-class-properties", [ "import", { "libraryName": "antd", "style": true } ] ] } }] })
不喜歡單獨的 babel 文件,因此 babel 的配置都在這裏了。其實,關於 babel 要配置的內容仍是挺多的。不過不要怕,babel 的官方文檔有詳細說明。瀏覽器
以前也提到過,一般咱們會使用 optimization.splitChunks
來處理第三方庫,將其分割成不變的部分。但是,每次打包的時候都須要重複這一步驟。
這時候咱們就想啊,不變的部分打包一次不就能夠了麼,以後就只打包那些常常變化的部分,這樣不就能提升效率了麼?是的, DllReferencePlugin & DllPlugin
基本上要作的就是這麼一回事。因此,咱們會針對這兩部分作不一樣的配置。緩存
// webpack.dll.js new webpack.DllPlugin({ context: process.cwd(), path: path.join(__dirname, '..', 'dist', 'dll', '[name]-manifest.json'), name: '[name]_[hash]' }) // webpack.common.js new webpack.DllReferencePlugin({ context: process.cwd(), manifest: require(path.resolve(__dirname, '..', 'dist', 'dll', "vendor-manifest.json")) }),
multi-spa-webpack-cli
已經發布到 npm,只要在 node 環境下安裝便可。一路按 Enter,所有源碼都在裏面!!!
npm install multi-spa-webpack-cli -g
使用步驟以下:
# 1. 初始化項目 multi-spa-webpack-cli init spa-project # 2. 進入文件目錄 cd spa-project # 3. 安裝依賴 npm install # 4. 打包不變的部分 npm run build:dll # 5. 啓動項目(手動打開瀏覽器:localhost:8090) npm start
webpack 系列: