团队最近开始一个新项目,技术栈采用 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