團隊最近開始一個新項目,技術棧採用 Vue.js 2 框架。因爲是一個較複雜的大型單頁應用,決定使用官方推薦的 webpack 工程做爲應用工程腳手架。該工程模板中使用了 webpack 3 和 babel 6,因爲 webpack 4 已發佈,Babel 7 也出來挺長一段時間了,因此想對工程模板進行升級改造,以嘗試工程化開發工具的最新特性。css
2018/12/21 更新
最近已升級到Babel 7 GA 版本,詳情請看github項目
vue-cli已出v3版本,封裝了更加開箱即用的 cli-service,但若是想了解webpack與babel配置細節,仍是能夠動手嘗試自行配置,以後會整理出一個脫離官方工程模板的輕量化配置方案,敬請期待html
webpack工程模板自己是爲大型應用設計的,構建腳本和配置文件的結構相比通常項目稍顯複雜,添加了一些開發輔助工具,而且作了必定程度的封裝。本次升級也是沿用了此套結構,只是對升級後的幾個工具配置項作了調整。幾個關鍵調整:除了 webpack 4 和 Babel 7,配套的 vue-loader 也升級到了 v15(官方的文檔已是v15了);另外爲了配套 webpack 4,extract-text-webpack-plugin
插件也被替換成了mini-css-extract-plugin
,而且配合 css-hot-loader
可實現提取css文件的熱替換。主要配置項調整請看下文,先後配置代碼差別能夠見這裏,完整工程模板庫地址:https://github.com/xsbear/vue...,有須要的同窗能夠直接 clone。vue
這裏的主要變化是新的 vue-loader
配置,因爲新版配置選項發生變動,原來vue-loader.conf.js
裏的配置項基本已廢棄,本方案直接將transformAssetUrls
選項配置在了 vue-loader
的 rule options 裏;另外需引入vue-loader/lib/plugin
,以確保正確解析 .vue
文件 <script>
塊中的js代碼。webpack
webpack 4 的一個主要變化: 添加 mode
參數,值爲 development
,移除已廢棄的NamedModulesPlugin
,NoEmitOnErrorsPlugin
等插件,另外引入 mini-css-extract-plugin
做爲css文件提取插件。固然,若是你不打算在開發模式下使用css提取(使用 style-loader 替代),也能夠不引入此插件,且在調用utils.styleLoaders
方法配置css模塊規則時,extract
參數傳 false
。git
對 utils裏的 generateLoaders
方法作了調整,替換css提取插件,增長 hotReload
參數,供開發、生產模式選擇是否要執行css模塊熱加載。此方法能夠根據傳入的 usePostCSS
參數或 loader
參數組裝成自定義的css預處理或後處理的 loader 組合,結合 styleLoaders
方法再組裝完整的css模塊rules,如 .css
, .postcss
, .sass
等。cssLoaders
方法返回中,枚舉了多種css預處理格式,實際項目中可根據本身採用的預處理方案進行選擇,無需所有配置,如只使用postcss,後面幾個預處理格式均可以註釋。github
這裏的主要調整是爲適配 webpack 4 的新配置。一樣的,新增參數 mode: 'production';比較大的調整是 optimization
配置,替代了以前的 CommonsChunkPlugin
, UglifyJsPlugin
等插件。另外如 HashedModuleIdsPlugin
等插件也已廢棄,無需再配置。這裏的重點是替代 CommonsChunkPlugin
插件的 splitChunks
配置項,目前給出的配置是能夠知足 vendor 庫和業務公用代碼庫分離的典型場景,更多分離優化的配置,有須要的同窗可查找相關教程,因爲不是本文重點,這裏就不展開了。web
Babel 7 的相關依賴包須要加上 @babel
scope。一個主要變化是 presets 設置由原來的 env
換成了 @babel/preset-env
, 能夠配置 targets
, useBuiltIns
等選項用於編譯出兼容目標環境的代碼。其中useBuiltIns
若是設爲 "usage"
,Babel 會根據實際代碼中使用的ES6/ES7代碼,以及與你指定的targets,按需引入對應的 polyfill,而無需在代碼中直接引入 import '@babel/polyfill'
,避免輸出的包過大,同時又能夠放心使用各類新語法特性。chrome
{ "presets": [ ["@babel/preset-env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] }, "useBuiltIns": "usage" }] ], "plugins": ["transform-vue-jsx"] }
對於開發應用來講,直接使用上述的按需 polyfill 方案是比較方便的,但若是是開發工具、庫的話,這種方案未必適合(babel-polyfill
是經過向全局對象和內置對象的prototype上添加方法實現的,會形成全局變量污染)。Babel 提供了另一種方案 transform-runtime
,它在編譯過程當中只是將須要polyfill的代碼引入了一個指向 core-js
中對應模塊的連接(alias)。關於這兩個方案的具體差別和選擇,能夠自行搜索相關教程,這裏再也不展開,下面提供一個 transform-runtime
的參考配置方案。vue-cli
npm install --save-dev @babel/plugin-transform-runtime npm install --save @babel/runtime
plugin-transform-runtime
的配置{ "presets": [ ["@babel/preset-env", { "modules": false, "targets": { "browsers": ["chrome 65"] } }] ], "plugins": ["transform-vue-jsx", ["@babel/plugin-transform-runtime", { "useBuiltIns": true // "polyfill": false }] ] }
這裏解釋一下 useBuiltIns
(默認爲 false
) 和 polyfill
(默認爲 true
) 兩個選項,若是不配置或使用默認值,那 Babel 是會自動 polyfill 的(引入core-js
polyfill 的alias),哪怕你指定的 targets 只有最新版chrome,最終編譯出來的包會比較大,這不是咱們所但願的。解決辦法是經過配置 polyfill
爲 false
或 useBuiltIns
爲true
(二選一便可),從而不引入 core-js 的 polyfill 。若是目標環境是較新的瀏覽器,能夠按此配置,可是有一些最新的特性可能還須要單獨 polyfill。我的認爲,若是開發應用能夠直接使用 babel-polyfill
方案,相對來講簡單方便,編譯輸出的包大小也是可控的。npm
原工程中有測試模塊,引入了相關依賴包。這次升級,爲適配 webpack 4 和 babel 7 也調整了相關依賴及配置。若是你項目中不須要引入測試模塊,能夠考慮將如下依賴包移除:
"@babel/register" // 這個是 jest 爲兼容 Babel 7 的一個依賴,注意不是 @babel/core "babel-core": "^7.0.0-bridge.0" "babel-jest" "regenerator-runtime" "chromedriver" "selenium-server" "jest" "jest-serializer-vue" "nightwatch" "selenium-server" "vue-jest"
其餘的一些調整如 postcss.config.js
等,可自行查看相關差別,再也不贅述。
webpack 工程做爲一個針對大型應用設計的官方通用模板,爲了兼容幷包及開箱即用對工程配置作了必定程度的封裝及開發輔助工具的整合,加快了項目開發的上手速度,但也對編譯、構建工具的升級調整帶來了一些不便。具體到實際項目中,能夠根據狀況對 webpack 的相關配置進行簡化,好比只保留 webpack.base.conf
, webpack.dev.conf
與 webpack.prod.conf
3個配置文件的結構便可,便於維護。
本人對於 webpack,Babel 等工具的掌握也僅限於應用層面,只是想把這次摸索的成果與你們進行分享,如描述有誤或不到位的地方,歡迎指正交流。
參考:
Setting up a Vue.js Project with webpack 4 and Babel 7
Upgrade to Babel 7