目前負責的項目,是未經過腳手架和其餘框架搭建的 react 項目。開發過程當中,啓動項目和熱更新速度都不是很理想;打包構建時,速度也比較緩慢且因爲單個文件過大,用戶在訪問時,加載動畫的時間也比較長。因此打算對其進行部分優化工做。 本着提高 webpack 性能,最直接的方式就是升級 webpack 版本的思路。對項目中的進行了一系列的升級和優化。升級和優化的結果以下: 編譯速度方面:javascript
體積方面:css
查看性能相關的插件:java
speed-measure-webpack-plugin
測量 plugin、loader 等時間;webpack-bundle-analyzer
打包分析工具。// 檢查過期的依賴包
npm outdated
// 安裝最新版本依賴包
npm install package@latest
複製代碼
// 若是不存在默認的 webpack.config.js 配置,則須要 --config 指定配置文件
node --trace-deprecation node_modules/webpack/bin/webpack.js
複製代碼
添加如下配置選項,檢查構建是否正常運行(完成後刪除這些配置選項)。node
module.exports = {
node: {
Buffer: false,
process: false
},
}
複製代碼
npm install webpack@latest -D
複製代碼
具體注意事項查看官方遷移指南:To v5 from v4react
asset
代替file-loader url-loader raw-loader
。terser-webpack-plugin
。cache: filesystem
持久緩存。可以大大提高二次構建速度(修改配置文件除外)。{
cache: {
type: "filesystem",
buildDependencies: {
// config 添加爲 buildDependency,以便在改變 config 時得到緩存無效
config: [__filename],
},
name: process.env.NODE_ENV,
version: "1.0.0",
},
}
複製代碼
thread-loader
進行多進程構建。// worker 啓動有必定的消耗,
// 能夠預熱 worker 池
const jsWorkerPool = {
workerParallelJobs: 80,
poolTimeout: 2000,
};
const cssWorkerPool = {
workerParallelJobs: 10,
poolTimeout: 2000,
};
threadLoader.warmup(jsWorkerPool, ["babel-loader"]);
threadLoader.warmup(cssWorkerPool, ["css-loader", "less-loader"]);
複製代碼
devServer: {
...
watchOptions: {
// 延遲構建
aggregateTimeout: 1500,
ignored: /node_modules/,
},
},
複製代碼
style-loader
,能夠實現模塊熱替換;[react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin)
插件;{
plugins: [
new ReactRefreshWebpackPlugin()
]
}
複製代碼
// .babelrc
{
"plugins": [
...,
"react-hot-loader/babel"
]
}
// index.js
import { hot } from 'react-hot-loader';
...
const App = hot(module)(() => ...);
render(<App />, document.getElementById('root'));
複製代碼
打包後體積優化,主要是使用 Gzip 壓縮,將打包後體積較大的文件使用 Gzip 壓縮。項目中的兩個大文件體積分別減小了 77%和 86% 左右,大大加快了頁面的加載速度。 webpack
Gzip(GNU- ZIP) 是一種壓縮技術。通過壓縮的頁面能大大加快瀏覽器端的加載速度。 啓用 Gzip 須要服務器端和瀏覽器端都支持:服務器端壓縮(提供壓縮的文件),瀏覽器端解壓。 注意:git
其餘體積優化須要修改業務相關代碼較多,就暫未進行優化。github
DeprecationWarning:[DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK] DeprecationWarning: Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader
speed-measure-webpack-plugin
插件兼容性問題,目前尚未徹底和 webpack5 兼容,能夠在優化完成後移除相關配置。web
Error: Cannot find module 'webpack-cli/bin/config-yargs
npm
4.X版本的 webpack-cli 移除了yargs包,須要使用 webpack serve
啓動webpack-dev-server
。
// package.json
{
"script": {
"dev": "webpack serve --config webpack.dev.js"
}
}
複製代碼
Support for the experimental syntax 'classProperties' isn't currently enabled
@babel/preset-env
不包含小於 Stage 3 的語法提案,須要手動安裝相應插件。須要安裝插件@babel/plugin-proposal-class-properties
。
//.babelrc
{
"plugin":[
"@babel/plugin-proposal-class-properties"
]
}
複製代碼
Support for the experimental syntax 'decorators-legacy' isn't currently enabled
緣由同上,須要安裝插件@babel/plugin-proposal-decorators
。
//.babelrc
{
"plugin":[
["@babel/plugin-proposal-decorators", {"legacy": true}]
]
}
複製代碼
expose-loader
升級後,報錯:ValidationError: Invalid options object. Expose Loader has been initialized using an options object that does not match the API schema.
// webpack 配置文件
module: {
rules:[
...,
{
use: {
loader: "expose-loader",
options: {
exposes: "videojs"
}
}
}
]
}
// **.js 使用
require('videojs');
複製代碼
webpack.HotModuleReplacementPlugin
和hot: true
共同使用時,沒法熱更新。 hot: true
會自動添加webpack.HotModuleReplacementPlugin
插件,無需再次添加配置。 7. speed-measure-webpack-plugin
插件在 build 時,沒法使用。 8. webpack5 再也不爲 Node.js 提供自動引入polyfills。
根據錯誤提示修改便可。
生產環境中構建完成,可是未退出命令
thread-loader
插件在生產環境中,預熱 worker 池會致使此問題。
升級後,webpack 對代碼要求更加嚴格,須要按需修改。