摘要:想要使用階段的語法需要多帶帶引用對應的,上面的配置只加了幾個處于階段的,老項目建議使用升級,自動添加依賴添加配置文件按需引入增加配置其他問題下面是我公司項目中遇到的問題,各位升級過程中如果遇到同樣的問題可以參考一下解決思路。
0. 前言
早在 2016 年我就發布過一篇關于在多頁面下使用 Webpack + Vue 的配置的文章,當時也是我在做自己一個個人項目時遇到的配置問題,想到別人也可能遇到跟我同樣的問題,就把配置的思路分享出來了,傳送門在這里。
因為那份配置直到現在還有人在關注,同時最近公司幫助項目升級了 Webpack 4,趁機也把之前的配置也升級了一下,而且博客荒廢了這么久,都快 9102 年了,不能連年均一篇博文都不到,所以有了下面的分享。
下面的配置主要是給在多頁面下使用 Webpack 的同學在升級 Webpack 時提供一點思路,多頁面的配置思路請點擊上面的傳送門。
下面代碼的地址 https://github.com/cnu4/Webpack-Vue-MultiplePage
1. Webpack 升級 4.x 1.1. 升級和安裝相關依賴webpack 升級
webpack-cli webapck4.x 需要新加的依賴
mini-css-extract-plugin 取代 extract-text-webpack-plugin
其他相關 loader 和 plugin
css-loader
file-loader
url-loader
vue-style-loader
vue-template-compiler(注意要保持與 vue 版本一直)
html-webpack-plugin@next
1.2 修改配置 mode 構建模式設置 mode 構建模式,比如 development 會將 process.env.NODE_ENV 的值設為 development
mini-css-extract-plugin刪除原 extract-text-webpack-plugin 配置,增加 mini-css-extract-plugin 配置
module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: "css/[name].css" }), ], } module.exports = { module: { rules: [ { test:/.vue$/, loader: "vue-loader", }, { test: /.css$/, use: [ // 開發模式下使用 vue-style-loader,以便使用熱重載 process.env.NODE_ENV !== "production" ? "vue-style-loader" : MiniCssExtractPlugin.loader, "css-loader" ] }, ] } }optimization
這是 webpack 4 一個比較大的變動點,webpack 4 中刪除了 webpack.optimize.CommonsChunkPlugin,并且使用 optimization 中的splitChunk來替代,下面的配置代替了之前的 CommonsChunkPlugin 配置,同意能提取 JS 和 CSS 文件
module.exports = { optimization: { splitChunks: { vendors: { name: "venders", chunks: "all", minChunks: chunks.length } } }vue-loader 升級
vue-loader 15 注意要配合一個 webpack 插件才能正確使用
const { VueLoaderPlugin } = require("vue-loader") module.exports = { plugins: [ new VueLoaderPlugin() ] }html-webpack-plugin 升級
升級到 next,否則開發下無法正常注入資源文件
文件壓縮optimize-css-assets-webpack-plugin
terser-webpack-plugin
壓縮的配置也移動到了 optimization 選項下,值得注意的是壓縮工具換成了 terser-webpack-plugin,這是 webpack 官方也推薦使用的,估計在 webpack 5 中會變成默認的配置,實測打包速度確實變快了很多。
配置
module.exports = { minimizer: [ new TerserPlugin({ // 壓縮js cache: true, parallel: true } }), new OptimizeCSSAssetsPlugin({ // 壓縮css cssProcessorOptions: { safe: true } }) ] } }2. 打包速度優化
可以使用下面的插件看看打包時間主要耗時在哪
speed-measure-webpack-plugin
2.1 相關 plugin 開啟 parallel 選項TerserPlugin 壓縮插件可以開啟多線程,見上面配置
2.2 HappyPack 和 thread-loader 開啟 Loader 多進程轉換github 的 Demo 中沒有引入,有興趣的同學可以嘗試,在一些耗時的 Loader 確實可以提高速度
vue-loader 不支持 HappyPack,官方建議用 thread-loader
const HappyPack = require("happypack"); exports.module = { rules: [ { test: /.js$/, // 1) replace your original list of loaders with "happypack/loader": // loaders: [ "babel-loader?presets[]=es2015" ], use: "happypack/loader", include: [ /* ... */ ], exclude: [ /* ... */ ] } ] }; exports.plugins = [ // 2) create the plugin: new HappyPack({ // 3) re-add the loaders you replaced above in #1: loaders: [ "babel-loader?presets[]=es2015" ] }) ];2.3 提前打包公共代碼 DllPlugin
使用 DllPlugn 將 node_modules 或者自己編寫的不常變的依賴包打一個 dll 包,提高速度和充分利用緩存。相當于 splitChunks 提取了公共代碼,但 DllPlugn 是手動指定了公共代碼,提前打包好,免去了后續 webpack 構建時的重新打包。
首先需要增加一個 webpack 配置文件 webpack.dll.config.js 專門針對 dll 打包配置,其中用到 webpack.DllPlugin。
執行 webpack --config build/webpack.dll.config.js 后,webpack會自動生成 2 個文件,其中vendor.dll.js 即合并打包后第三方模塊。另外一個 vendor-mainifest.json 存儲各個模塊和所需公用模塊的對應關系。
接著修改我們的 webpack 配置文件,在 plugin 配置中增加 webpack.DllReferencePlugin,配置中指定上一步生成的 json 文件,然后手動在 html 文件中引用上一步的 vendor.dll.js 文件。
后面如果增刪 dll 中的依賴包時都需要手動執行上面打包命令來更新 dll 包。下面插件可以自動完成這些操作。
AutoDllPlugin安裝依賴 autodll-webpack-plugin
AutoDllPlugin 自動同時相當于完成了 DllReferencePlugin 和 DllPlugin 的工作,只需要在我們的 webpack 中添加配置。AutoDllPlugin 會在執行 npm install / remove / update package-name 或改變這個插件配件時重新打包 dll。需要注意的是改變 dll 中指定的依賴包不會觸發自動重新打包 dll。
實際打包中生成環境是沒問題的,但開發模式下在有緩存的情況下,autodll 插件不會生成新的文件,導致 404,所以在 Demo 中暫時關了這個插件。不過 dll 提前打包了公共文件,確實可以提高打包速度,有興趣的同學可以研究下開發模式下的緩存問題,歡迎在評論中分享。
module.exports.plugins.push(new AutoDllPlugin({ inject: true, // will inject the DLL bundles to html context: path.join(__dirname, "."), filename: "[name].dll.js", debug: true, inherit: true, // path: "./", plugins: [ new TerserPlugin({ cacheL true, parallel: true }), new MiniCssExtractPlugin({ filename: "[name].css" }) ], entry: { vendor: ["vue/dist/vue.esm.js", "axios", "normalize.css"] } }));3. 增加 ES6+ 支持 3.1 安裝依賴
@babel/core
@babel/plugin-proposal-class-properties
@babel/plugin-proposal-decorators
@babel/plugin-syntax-dynamic-import
@babel/plugin-transform-runtime
@babel/preset-env
@babel/runtime
babel-loader
@babel/polyfill
由于項目中是第一次配置 babel,一步到位直接使用新版 7,新版 babel 使用新的命名空間 @babel,如果是老項目升級 babel 7,可以使用工具 babel-upgrade,讀一下 升級文檔
這里說下上面依賴的作用和升級 babel 7 的改動。
@babel/runtime, @babel/plugin-transform-runtime新版中 @babel/runtime 只包含了一些 helpers,如果需要 core-js polyfill 瀏覽器不支持的 API,可以用 transform 提供的選項 {"corejs": 2} 并安裝依賴 @babel/runtime-corejs2。即使默認的 polyfill 沒了,但 @babel/plugin-transform-runtime 依然可以為我們分離輔助函數,減少代碼體積
@babel/polyfill使用 @babel/runtime 的 polyfill 不會污染全局 API,因為不會改動原生對象的原型,它只是創建一個輔助函數在當前作用于生效,所以諸如 [1, 2].includes(1) 這樣的語法也無法被 polyfill。如果不是開發第三方庫,可以使用 @babel/polyfill,相反他的 polyfill 會影響到瀏覽器全局的對象原型
@babel/preset-env 提供了一個 useBuiltIns 選項來按需引入 polyfill,而不需要引入全部。另一種方法是直接引用 core-js 包下的特定 polyfill。
stage presets現在需要手動安裝 @babel/plugin-proposal 開頭的依賴是因為 babel 在新版中移除了 stage presets,為的是后續更好維護處于 proposal 階段的語法。想要使用 proposal 階段的語法需要多帶帶引用對應的 plugin, 上面的配置只加了幾個處于 stage 3 階段的 plugin,老項目建議使用 babel-upgrade 升級,自動添加依賴
3.2 添加配置文件 .babelrc{ "presets": [ [ "@babel/preset-env", { "modules": false, "targets": { "browsers": [ "> 1%", "last 2 versions", "ie >= 11" ] }, "useBuiltIns": "usage" // 按需引入 polyfill } ] ], "plugins": [ "@babel/plugin-transform-runtime", "@babel/plugin-syntax-dynamic-import", ["@babel/plugin-proposal-class-properties", { "loose": false }], ["@babel/plugin-proposal-decorators", { "legacy": true }], ] }3.3 增加 webpack 配置
module.exports = { modules: { rules: [ { test: /.js$/, loader: "babel-loader", exclude: /node_modules/ } ] } }4. 其他問題
下面是我公司項目中遇到的問題,各位升級過程中如果遇到同樣的問題可以參考一下解決思路。
4.1 json-loaderwebpack4 內置的json-loader 有點兼容性問題,安裝 json-loader 依賴和更改配置
解決:
{ test: /.json$/, //用于匹配loaders所處理文件拓展名的正則表達式 use: "json-loader", //具體loader的名稱 type: "javascript/auto", exclude: /node_modules/ }4.2 vue-loader
vue-loader 升級到 15.x 后,會導致舊的 commonjs 寫法加載有問題,需要使用 require("com.vue").default 的方式引用組件
13的版本還可以設置 esModule,14 以后的版本不能設置了,vue 文件導出的模塊一定是 esModule
解決:使用 require("com.vue").default 或者 import 的方式引用組件
esModule option stopped working in version 14 · Issue #1172 · vuejs/vue-loader · GitHub
尤大大建議可以自己寫一個 babel 插件,遇到 require vue 文件的時候自動加上 default 屬性,這樣就不用改動所有代碼,我們在項目中也是這樣處理的。
4.3 提取公共 css 代碼scss 中 import 的代碼不能被提取到公共 css 中。scss 中的 @import 是使用 sass-loader 處理的,處理后已經變成 css 文件,webpack 已經不能判斷是否是同一個模塊,所以不能提取到公共的 css 中,但多頁面中我們還是希望一些公共的 css 能被提取到公共的文件中。
解決:將需要提取到公共文件的 css 改到 js 中引入就可以,詳見下面 issue
mini-css-extract-plugin + sass-loader + splitChunks · Issue #49
4.4 mini-css-extract-plugin filename 不支持函數mini-css-extract-plugin 的 filename 選項不支持函數,但我們有時候還是希望能多帶帶控制公共 css 文件的位置,而不是和其他入口文件的 css 使用一樣的目錄格式
解決:使用插件 FileManagerPlugin 在構建后移動文件,等 filename 支持函數后再優化
feat: allow the option filename to be a function · Issue #143 · webpack-contrib/mini-css-extract-plugin · GitHub
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100558.html
摘要:以為例,編寫來幫助我們完成重復的工作編譯壓縮我只要執行一下就可以檢測到文件的變化,然后為你執行一系列的自動化操作,同樣的操作也發生在這些的預處理器上。的使用是針對第三方類庫使用各種模塊化寫法以及語法。 showImg(https://segmentfault.com/img/bVbtZYK); 一:前端工程化的發展 很久以前,互聯網行業有個職位叫做 軟件開發工程師 在那個時代,大家可能...
摘要:前言本文基于,主要涉及基本概念基本配置和實際項目打包優化。關于概念方面參考官網,常用配置來自于網絡資源,在文末有相關參考鏈接,實踐部分基于自己的項目進行優化配置。同一文件中,修改某個影響其他。 前言:本文基于weboack4.x,主要涉及webpack4 基本概念、基本配置和實際項目打包優化。關于概念方面參考官網,常用配置來自于網絡資源,在文末有相關參考鏈接,實踐部分基于自己的項目進行...
摘要:根據依賴關系,按照配置文件把模塊函數分組打包成若干個。會隨著自身的的修改,而發生變化。只需要在命令行運行時帶上參數就搞定一些插件的廢除和替換廢棄了頂替者用屬性變化壓縮優化代碼分割,下面詳解還有一些新的插件,。 1. 前端工程化項目打包歷史 前端工程化之前的時代略過 1. 半自動執行腳本來壓縮合并文件 自從xmlhttprequest被挖掘出來,網頁能夠和服務端通訊,js能做的事越來越多...
摘要:根據依賴關系,按照配置文件把模塊函數分組打包成若干個。會隨著自身的的修改,而發生變化。只需要在命令行運行時帶上參數就搞定一些插件的廢除和替換廢棄了頂替者用屬性變化壓縮優化代碼分割,下面詳解還有一些新的插件,。 1. 前端工程化項目打包歷史 前端工程化之前的時代略過 1. 半自動執行腳本來壓縮合并文件 自從xmlhttprequest被挖掘出來,網頁能夠和服務端通訊,js能做的事越來越多...
閱讀 1662·2019-08-30 12:51
閱讀 656·2019-08-29 17:30
閱讀 3696·2019-08-29 15:17
閱讀 852·2019-08-28 18:10
閱讀 1355·2019-08-26 17:08
閱讀 2169·2019-08-26 12:16
閱讀 3429·2019-08-26 11:47
閱讀 3497·2019-08-23 16:18