您好,登錄后才能下訂單哦!
如何輸出Webpack構建分析
輸出Webpack構建信息的.json文件:webpack --profile --json > stats.json
--profile
:記錄構建中的耗時信息--json
:以json格式輸出構建結果,最后只輸出一個json文件(包含所有的構建信息)web可視化查看構建分析:得到了webpack構建信息文件stats.json,如何進行很好的可視化查看?
webpack-bundle-analyzer
工具npm i -g webpack-bundle-analyzer
,生成stats.json后直接在其文件夾目錄執行webpack-bundle-analyzer
后,瀏覽器會打開對應網頁并展示構建分析webpack-bundle-analyzer stats.json -p 8888
文檔地址webpack-bundle-analyzernpm i -D webpack-jarvis
webpack.config.js
配置:
const Jarvis = require("webpack-jarvis"); plugins: [ new Jarvis({ watchOnly: false, port: 3001 // optional: set a port }) ];
port:監聽的端口,默認1337,監聽面板將監聽這個端口,通常像http://localhost:port/
host:域名,默認localhost,不限制域名。
watchOnly:僅僅監聽編譯階段。默認為true,如果高為false,jarvis不僅僅運行在編譯階段,在編譯完成后還保持運行狀態。
界面:看到構建時間為:Time: 11593ms
(作為優化時間對比)
webpack配置優化
webpack在啟動時會從配置的Entry出發,解析出文件中的導入語句,再遞歸解析。
對于導入語句Webpack會做出以下操作:
針對這兩點可以優化查找途徑
1、優化Loader配置
Loader處理文件的轉換操作是很耗時的,所以需要讓盡可能少的文件被Loader處理
{ test: /\.js$/, use: [ 'babel-loader?cacheDirectory',//開啟轉換結果緩存 ], include: path.resolve(__dirname, 'src'),//只對src目錄中文件采用babel-loader exclude: path.resolve(__dirname,' ./node_modules'),//排除node_modules目錄下的文件 },
2、優化resolve.modules配置
resolve.modules
用于配置webpack去哪些目錄下尋找第三方模塊,默認是['node_modules']
,但是,它會先去當前目錄的./node_modules
查找,沒有的話再去../node_modules
最后到根目錄;
所以當安裝的第三方模塊都放在項目根目錄時,就沒有必要安默認的一層一層的查找,直接指明存放的絕對位置
resolve: { modules: [path.resolve(__dirname, 'node_modules')], }
3、優化resolve.extensions配置
在導入沒帶文件后綴的路徑時,webpack會自動帶上后綴去嘗試詢問文件是否存在,而resolve.extensions
用于配置嘗試后綴列表;默認為extensions:['js','json']
;
及當遇到require('./data')
時webpack會先嘗試尋找data.js
,沒有再去找data.json
;如果列表越長,或者正確的后綴越往后,嘗試的次數就會越多;
所以在配置時為提升構建優化需遵守:
因為項目中用的jsx
較多,所以配置extensions: [".jsx",".js"],
基本配置后查看構建速度:Time: 10654ms
;配置前為Time: 11593ms
使用DllPlugin優化
在使用webpack進行打包時候,對于依賴的第三方庫,如react,react-dom等這些不會修改的依賴,可以讓它和業務代碼分開打包;
只要不升級依賴庫版本,之后webpack就只需要打包項目業務代碼,遇到需要導入的模塊在某個動態鏈接庫中時,就直接去其中獲取;而不用再去編譯第三方庫,這樣第三方庫就只需要打包一次。
接入需要完成的事:
接入工具(webpack已內置)
DllPlugin插件:用于打包出一個個單獨的動態鏈接庫文件;
DllReferencePlugin:用于在主要的配置文件中引入DllPlugin
插件打包好的動態鏈接庫文件
配置webpack_dll.config.js構建動態鏈接庫
const path = require('path'); const DllPlugin = require('webpack/lib/DllPlugin'); module.exports = { mode: 'production', entry: { // 將React相關模塊放入一個動態鏈接庫 react: ['react','react-dom','react-router-dom','react-loadable'], librarys: ['wangeditor'], utils: ['axios','js-cookie'] }, output: { filename: '[name]-dll.js', path: path.resolve(__dirname, 'dll'), // 存放動態鏈接庫的全局變量名,加上_dll_防止全局變量沖突 library: '_dll_[name]' }, // 動態鏈接庫的全局變量名稱,需要可output.library中保持一致,也是輸出的manifest.json文件中name的字段值 // 如react.manifest.json字段中存在"name":"_dll_react" plugins: [ new DllPlugin({ name: '_dll_[name]', path: path.join(__dirname, 'dll', '[name].manifest.json') }) ] }
webpack.pro.config.js中使用
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin'); ... plugins: [ // 告訴webpack使用了哪些動態鏈接庫 new DllReferencePlugin({ manifest: require('./dll/react.manifest.json') }), new DllReferencePlugin({ manifest: require('./dll/librarys.manifest.json') }), new DllReferencePlugin({ manifest: require('./dll/utils.manifest.json') }), ]
注意:在webpack_dll.config.js
文件中,DllPlugin
中的name參數必須和output.library
中的一致;因為DllPlugin
的name參數影響輸出的manifest.json的name;而webpack.pro.config.js中的DllReferencePlugin
會讀取manifest.json
的name,將值作為從全局變量中獲取動態鏈接庫內容時的全局變量名
執行構建
webpack --progress --colors --config ./webpack.dll.config.js
webpack --progress --colors --config ./webpack.prod.js
html中引入dll.js文件
構建時間對比:["11593ms","10654ms","8334ms"]
HappyPack并行構建優化
核心原理:將webpack中最耗時的loader文件轉換操作任務,分解到多個進程中并行處理,從而減少構建時間。
HappyPack
接入HappyPack
安裝:npm i -D happypack
重新配置rules
部分,將loader
交給happypack
來分配:
const HappyPack = require('happypack'); const happyThreadPool = HappyPack.ThreadPool({size: 5}); //構建共享進程池,包含5個進程 ... plugins: [ // happypack并行處理 new HappyPack({ // 用唯一ID來代表當前HappyPack是用來處理一類特定文件的,與rules中的use對應 id: 'babel', loaders: ['babel-loader?cacheDirectory'],//默認設置loader處理 threadPool: happyThreadPool,//使用共享池處理 }), new HappyPack({ // 用唯一ID來代表當前HappyPack是用來處理一類特定文件的,與rules中的use對應 id: 'css', loaders: [ 'css-loader', 'postcss-loader', 'sass-loader'], threadPool: happyThreadPool }) ], module: { rules: [ { test: /\.(js|jsx)$/, use: ['happypack/loader?id=babel'], exclude: path.resolve(__dirname,' ./node_modules'), }, { test: /\.(scss|css)$/, //使用的mini-css-extract-plugin提取css此處,如果放在上面會出錯 use: [MiniCssExtractPlugin.loader,'happypack/loader?id=css'], include:[ path.resolve(__dirname,'src'), path.join(__dirname, './node_modules/antd') ] }, }
參數:
threads
:代表開啟幾個子進程去處理這一類文件,默認是3個;
verbose
:是否運行HappyPack輸出日志,默認true;
threadPool:代表共享進程池,即多個HappyPack示例使用一個共享進程池中的子進程去處理任務,以防資源占有過多
代碼壓縮用ParallelUglifyPlugin代替自帶的 UglifyJsPlugin插件
自帶的JS壓縮插件是單線程執行的,而webpack-parallel-uglify-plugin可以并行的執行
配置參數:
uglifyJS: {}
:用于壓縮 ES5 代碼時的配置,Object 類型test: /.js$/g
:使用正則去匹配哪些文件需要被 ParallelUglifyPlugin 壓縮,默認是 /.js$/include: []
:使用正則去包含被壓縮的文件,默認為 [].exclude: []
: 使用正則去包含不被壓縮的文件,默認為 []cacheDir: ''
:緩存壓縮后的結果,下次遇到一樣的輸入時直接從緩存中獲取壓縮后的結果并返回,默認不會緩存,開啟緩存設置一個目錄路徑workerCount: ''
:開啟幾個子進程去并發的執行壓縮。默認是當前運行電腦的 CPU 核數減去1sourceMap: false
:是否為壓縮后的代碼生成對應的Source Map, 默認不生成... minimizer: [ // webpack:production模式默認有配有js壓縮,但是如果這里設置了css壓縮,js壓縮也要重新設置,因為使用minimizer會自動取消webpack的默認配置 new optimizeCssPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), cssProcessorOptions: { discardComments: { removeAll: true } }, canPrint: true }), new ParallelUglifyPlugin({ cacheDir: '.cache/', uglifyJS:{ output: { // 是否輸出可讀性較強的代碼,即會保留空格和制表符,默認為輸出,為了達到更好的壓縮效果,可以設置為false beautify: false, //是否保留代碼中的注釋,默認為保留,為了達到更好的壓縮效果,可以設置為false comments: false }, compress: { //是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認為輸出 warnings: false, //是否刪除代碼中所有的console語句,默認為不刪除,開啟后,會刪除所有的console語句 drop_console: true, //是否內嵌雖然已經定義了,但是只用到一次的變量,比如將 var x = 1; y = x, 轉換成 y = 1, 默認為否 collapse_vars: true, } } }), ]
構建結果對比:["11593ms","10654ms","8334ms","7734ms"]
整體構建速度從12000ms
降到現在的8000ms
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。