以新手视角,详细介绍各个步骤内容,不深入讲步骤涉及的原理,主要介绍如何操作。
本文示例工程 GitHub:https://github.com/qinshenxue/vue2-vue-router2-webpack2
2017-09-30 升级了 Vue(2.4.4)和 Webpack(3.6.0),github 项目已更新。
2017-11-02 修复了 babel 配置为”presets”: [[“env”, { “modules”: false }]]后,无法使用 import 动态导入功能的问题,在「异步组件(懒加载)」章节已更新解决方法。
新建工程目录 vue2practice,在目录下执行npm init -y来创建一个 package.json,在 package.json 中先添加以下必备模块:
- {
- "name": "vue2-vue-router2-webpack3",
- "version": "1.0.0",
- "devDependencies": {
- "vue": "^2.4.2",
- "vue-loader": "^13.0.2",
- "vue-router": "^2.7.0",
- "vue-template-compiler": "^2.4.2",
- "webpack": "^3.4.1",
- "webpack-dev-server": "^2.6.1"
- }
- }
其中 vue-template-compiler 是 vue-loader 的 peerDependencies,npm3 不会自动安装 peerDependencies,然而 vue-template-compiler 又是必备的,那为什么作者不将其放到 dependencies 中呢?有人在 github 上提过这个问题,我大致翻译一下作者的回答(仅供参考):这样做的原因是因为没有可靠的方式来固定嵌套依赖的关系,怎么理解这句话?首先 vue-template-compiler 和 vue 的版本号是一致的(目前是同步更新),将 vue-template-compiler 指定为 vue-loader 的 dependencies 并不能保证 vue-template-compiler 和 vue 的版本号是相同的,让用户自己指定版本才能保证这一点。查看作者的回答(英文) 。如果两者版本不一致,运行时会出现下图所示的错误提示。
新建目录结构如下,新增的目录及文件先空着,后面的步骤会说明添加什么内容。
- vue2pratice
- |-- package.json
- |-- index.html // 启动页面
- |-- webpack.config.js // webpack配置文件
- |-- src
- |-- views // vue页面组件目录
- |-- main.js // 入口文件
- |-- router.js // vue-router配置
- |-- app.vue // 工程首页组件
Webpack 默认读取 webpack.config.js,文件名不能随便改,其中 entry 是必须配置的。
- module.exports = {
- entry: './src/main.js',
- output: {
- path: __dirname + '/dist',
- publicPath: '/static/',
- filename: 'build.js'
- }
- }
Webpack 2+ 要求output.path必须为绝对路径。关于 Webpack 的各种路径在《详解Webpack2的那些路径》有详细的介绍。
配置 webpack-dev-server,只需在 package.json 添加以下启动命令即可。
- "scripts": {
- "dev": "webpack-dev-server --hot --open"
- }
webpack-dev-server 2 默认为 inline 模式,热模块替换仍需自己设置。
在 index.html 中添加测试代码,引入打包后的 JS 文件。
- Hello, Webpack 3.
在 main.js 中添加测试代码。
- // main.js
- document.write('来自main.js的问候!')
执行下面的命令来安装模块并启动服务器。
- // 安装依赖
- npm install
- // 运行
- npm run dev
启动后浏览器会自动打开http://localhost:8080,如果控制台没有报错,页面正确显示 main.js 和 index.html 的内容,改动 main.js 后浏览器不刷新能看到效果,则表示配置没问题。
在 views 目录下新建 index.vue。
webpack 1 需要特定的 loader 来转换 ES 2015 import/export,webpack 2 起可以开箱即用。但是 ES6 的新语法还是需要 loader 来转换,在没有配置前,先不要用新语法。用了也没报错(比如 let,const等),那是因为你的浏览器已经支持了 ES6 语法(新版本浏览器都已经支持)。
将 vue-router 实例化传入的参数new VueRouter(参数)提取到 router.js 形成路由配置文件。
- import index from './views/index.vue'export
- default {
- routes:
- [{
- path:
- '/index',
- component: index
- }]
- }
从 vue-loader@13.0.0,不能用 require 来引入 .vue 文件,因为 .vue 文件最终会被编译成 ES6 module。
首页引入 ouput 配置的 JS,添加 Vue 实例的挂载目标。
入口JS完成路由配置、初始化 Vue 实例。
- import Vue from 'vue';
- import VueRouter from 'vue-router';
- import App from './app.vue';
- import routerConfig from './router';
- Vue.use(VueRouter);
- var router = new VueRouter(routerConfig)
- new Vue({
- el: '#app',
- router: router,
- render: h => h(App)
- });
从 Vue 2.2.0 后使用 require(‘vue’) 会报错,应使用 ES6 module(import),具体原因请参考 Vue 更新说明 https://github.com/vuejs/vue/releases,截图如下:
在首页组件 app.vue 中添加路由链接、路由视图组件。
配置 vue 文件对应的 loader。
- module: {
- rules: [
- {
- test: /\.vue$/,
- use: ["vue-loader"]
- }
- ]
- }
Webpack2 必须在 module.rules 下配置 loader。’-loader’不能省略,必须将 loader 名写全。可以使用 Rule.use 或 Rule.loader 来配置 loader(Rule.loader 是 Rule.use: [ { loader } ] 的简写),建议用 use。
上面完成了新增页面及访问该页面所需的配置,下面来测试下是否能正常访问/index。执行npm run dev,浏览器显示如图界面。
安装 css-loader 后即可在 vue 文件中使用
- npm i css - loader - D
想要支持import / require引入CSS文件,则需要配置对应的 Rule。
- {
- test: /\.css$/,
- use: ["vue-style-loader", "css-loader"]
- }
以 stylus 为例,安装 stylus 及 stylus-loader。
- npm install stylus stylus - loader - D
增加 .styl 文件对应的 loader 配置。
- {
- test: /\.styl$/,
- use: ["vue-style-loader", "css-loader", "stylus-loader"]
- }
使用示例:
使用淘宝镜像:npm set disturl https://npm.taobao.org/dist
也可以单独设置node-sass镜像:npm set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass
安装图片及图标字体依赖的loader。
- npm install url - loader file - loader - D
增加图片及图标字体的loader配置。
- {
- test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
- use: [{
- loader: "url-loader",
- options: {
- limit: 10000,
- name: 'images/[name].[hash:7].[ext]' // 将图片都放入images文件夹下,[hash:7]防缓存
- }
- }]
- },
- {
- test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- use: [{
- loader: "url-loader",
- options: {
- limit: 10000,
- name: 'fonts/[name].[hash:7].[ext]' // 将字体放入fonts文件夹下
- }
- }]
- }
添加打包命令如下:
- "build": "webpack --progress --colors"
执行npm run build开始构建,完成后,可以看到工程目录下多了dist目录以及 dist/build.js。
在之前的文章提到过,打开未压缩版的build.js,你会发现ES6的语法没有被转化为ES5,因此需要安装babel 套件来完成语法的转化,否则压缩的时候就会报错。之前广泛使用的转码规则为 babel-preset-es2015,但 Babel 的官网上在9月宣布 ES2015 / ES2016/ ES2017 等等 ES20xx 时代的 presets 通通被废弃(deprecated),取而代之的是 babel-preset-env,并且承诺它将成为“未来不会过时的(future-proof)”解决方案。
- npm i babel - loader babel - core babel - preset - env - D
增加babel的配置文件.babelrc。
- {
- "presets": [["env", {
- "modules": false
- }]],
- "comments": false
- }
将 modules 设置为 false,即交由 Webpack 来处理模块化,通过其 TreeShaking 特性将有效减少打包出来的 JS 文件大小,可以自行对比下前后打包出来的文件的大小,效果还是不错的。
comments 即是否保留注释。
接着配置 JS 文件的 loader。
- {
- test: /\.js$/,
- use: "babel-loader",
- include: [path.resolve(__dirname, 'src')]
- }
注意:Webpack2建议尽量避免exclude,更倾向于使用include。
压缩 JS 采用webpack.optimize.UglifyJsPlugin,配置如下:
- new webpack.optimize.UglifyJsPlugin()
官网称warnings默认为false,你可能会遇到即使没有配置warnings: true,控制台仍显示警告,看下面这段源码就知道了。查看源码
只有当options.compress !== false时 warnings 才会被设置默认值 false,所以一旦配置了 compress 其它选项,那就需同时配置warnings: false。
warnings作用是当插件在压缩过程中移除的无效代码或定义是显示警告信息(display warnings when dropping unreachable code or unused declarations etc.)。
使用extract-text-webpack-plugin插件提取CSS。更改 css 及 less 的 loader 配置如下。
- // 安装插件
- npm i extract - text - webpack - plugin - D
- // var ExtractTextPlugin = require("extract-text-webpack-plugin")
- {
- test: /\.css$/,
- use: ExtractTextPlugin.extract({
- use: "css-loader"
- })
- },
- {
- test: /\.styl$/,
- use: ExtractTextPlugin.extract({
- use: ["css-loader", "stylus-loader"]
- })
- }
上述配置并不能提取 vue 文件中的 style,需要设置 vue-loader 参数才可以。
- {
- test: /\.vue$/,
- use: {
- loader: "vue-loader",
- options: {
- loaders: {
- css: ExtractTextPlugin.extract({
- use: 'css-loader'
- }),
- stylus: ExtractTextPlugin.extract({
- use: ["css-loader", "stylus-loader"]
- })
- }
- }
- }
- }
初始化插件,filename 可以指定 CSS 文件的目录。
- new ExtractTextPlugin({
- filename: "css/style.css"
- })
安装 postcss-loader 及 postcss 插件。
- npm i postcss - loader cssnano - D
配置 loader 如下:
- // css-loader配置改为
- use: ['css-loader', "postcss-loader"]
- // stylus-loader配置改为
- use: ["css-loader", "postcss-loader", "stylus-loader"]
postcss-loader 要放在 css-loader 和 style-loader 之后,CSS 预处理语言 loader 之前(stylus-loader)。
新增 postcss.config.js 来配置postcss插件,这样就不用给每个 postcss-loader 去配置。更多 postcss-loader 的配置方式请参考 postcss-load-config。
- module.exports = {
- plugins: [
- require('cssnano')
- ]
- }
cssnano 使用了一系列 postcss 插件,包含了常用的 autoprefixer 等,如何传入 autoprefixer 的配置?
- require('cssnano')({
- autoprefixer: {
- add: true,
- browsers: ['> 5%']
- }
- })
其中有一个插件 postcss-zindex 使用中发现有些问题。如果想禁用这个插件的话,配置如下:
- require('cssnano')({
- zindex: {
- disable: true
- }
- })
附:postcss插件分类搜索网站:http://postcss.parts/
安装 html-webpack-plugin 插件。
- npm i html - webpack - plugin - D
初始化插件。
- // var HtmlWebpackPlugin = require('html-webpack-plugin');
- new HtmlWebpackPlugin({
- filename: 'index.html',
- template: 'index.tpl.html'
- })
Webpack3 新增的作用域提升。
- new webpack.optimize.ModuleConcatenationPlugin()
指定生产环境,以便在压缩时可以让 UglifyJS 自动删除代码块内的警告语句。
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify('production')
- })
因为这个插件直接做的文本替换,给定的值必须包含字符串本身内的实际引号。通常,有两种方式来达到这个效果,使用 ‘”production”‘, 或者使用 JSON.stringify(‘production’)。
你完全可以在自己的代码中使用process.env.NODE_ENV来区分开发和生产,从而针对不同的环境做一些事情。不用担心这部分代码会被保留,最终会被 UglifyJS 删除。例如:
- if (process.env.NODE_ENV != "production") {
- // 开发环境
- }
- // webpack.DefinePlugin插件替换后,上述代码会变成
- if ("production" != "production") {
- // 开发环境
- }
- // 输出
- if (false) {
- // 开发环境
- }
- // UglifyJS 会删除这段无效代码
使用上述插件后再次构建,会发现生成的JS相比原来的体积小了不少。
friendly-errors-webpack-plugin 是一个更友好显示 webpack 错误信息的插件。插件 github 地址:https://github.com/geowarin/friendly-errors-webpack-plugin
一般在开发环境下使用。
- var FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
- var webpackConfig = {
- // ...
- plugins: [
- new FriendlyErrorsWebpackPlugin(),
- ],
- // ...
- }
效果如下图:
显示构建进度插件:webpack.ProgressPlugin
- {
- // ...
- plugins: [
- new webpack.ProgressPlugin(),
- ],
- // ...
- }
效果如下图:
美化 webpack 编译控制台打印的信息的插件webpack-dashboard
将开发和生产配置文件分离,方便增加各个环境下的个性配置。Webpack2文档中也详细阐述了如何为多环境配置webpack。基本思路如下:
webpack.base.config.js 内容如下:
- var webpack = require('webpack');
- var path = require('path');
- var utils = require('./utils');
- function resolve(relPath) {
- return path.resolve(__dirname, relPath);
- }
- module.exports = {
- entry: {
- app: resolve('../src/main.js')
- },
- output: {
- filename: 'js/[name].js'
- },
- module: {
- rules: [{
- test: /\.js$/,
- use: "babel-loader",
- include: [resolve('../src')]
- },
- {
- test: /\.vue$/,
- use: {
- loader: "vue-loader",
- options: utils.vueLoaderOptions()
- }
- },
- {
- test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
- use: {
- loader: "url-loader",
- options: {
- limit: 10000,
- name: 'images/[name].[hash:7].[ext]'
- }
- }
- },
- {
- test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- use: [{
- loader: "url-loader",
- options: {
- limit: 10000,
- name: 'fonts/[name].[hash:7].[ext]'
- }
- }]
- }]
- }
- }
为什么要将vue-loader的options提取出来?其主要是用来配置CSS及CSS预处理语言的loader,开发环境可以不用配置,但是生产环境需要提取CSS、增加postcss-loader等,因此需要提取出来针对不同环境返回相应的options。后面会列出utils.vueLoaderOptions的内容。
为什么没有配置CSS的loader?理由和上面的vue-loader一样。
为什么没有配置path和publicPath?一方面是个性化参数,另外开发和生产可能不相同,因此在webpack.dev.config和webpack.prod.config中分别配置更为合适。
webpack.dev.config.js 内容如下:
- var webpack = require('webpack');
- var merge = require('webpack-merge');
- var HtmlWebpackPlugin = require('html-webpack-plugin');
- var baseWebpackConfig = require('./webpack.base.config');
- var utils = require('./utils');
- var config = require('./config');
- Object.keys(baseWebpackConfig.entry).forEach(function(name) {
- baseWebpackConfig.entry[name] = [
- `webpack-dev-server/client?http://localhost:${config.dev.port}/`,
- "webpack/hot/dev-server"
- ].concat(baseWebpackConfig.entry[name])
- });
- module.exports = merge(baseWebpackConfig, {
- output: {
- path: config.dev.outputPath,
- publicPath: config.dev.outputPublicPath
- },
- module: {
- rules: utils.styleLoaders()
- },
- plugins: [
- new webpack.HotModuleReplacementPlugin(),
- new HtmlWebpackPlugin({
- filename: 'index.html',
- template: 'index.html',
- inject: true
- })
- ]
- })
添加了HtmlWebpackPlugin后,index.html中就不需要在自己去引用打包的JS了,会自动根据打包的JS添加引用,这样更加方便,关于HtmlWebpackPlugin的配置,需要说明两点:
1.template的路径是相对于webpack编译时的上下文目录,说白了就是项目根目录,因此上面可以直接配置index.html,其指向的就是根目录下的index.html;
2.filename则是相对于webpack配置项output.path(打包资源存储路径)。
html-webpack-plugin关于template和filename路径源码如下:
- // https://github.com/jantimon/html-webpack-plugin/blob/master/index.js
- // template
- this.options.template = this.getFullTemplatePath(this.options.template, compiler.context);
- // filename
- this.options.filename = path.relative(compiler.options.output.path, filename);
config.js内容如下:
- module.exports = {
- dev: {
- outputPath: path.resolve(__dirname, '../static'),
- outputPublicPath: '/',
- port: 8000
- },
- prod: {
- outputPath: path.resolve(__dirname, '../static'),
- outputPublicPath: '/static/'
- }
- }
utils.js内容如下:
- var ExtractTextPlugin = require('extract-text-webpack-plugin');
- var isProd = process.env.NODE_ENV === "production";
- // 根据项目需求添加CSS预处理语言并安装相应的loader,以stylus-loader为例
- var cssLang = [{
- name: 'css',
- reg: /\.css$/,
- loader: 'css-loader'
- },
- {
- name: 'stylus',
- reg: /\.styl$/,
- loader: "stylus-loader"
- }];
- function genLoaders(lang) {
- var loaders = ['css-loader', 'postcss-loader'];
- if (lang.name !== 'css') {
- loaders.push(lang.loader);
- }
- if (isProd) {
- // 生产环境需要提取CSS
- loaders = ExtractTextPlugin.extract({
- use: loaders
- });
- } else {
- // 开发环境需要vue-style-loader将CSS提取到页面头部
- loaders.unshift('vue-style-loader');
- }
- return loaders;
- }
- // 各种CSS的loader
- exports.styleLoaders = function() {
- var output = [];
- cssLang.forEach(lang = >{
- output.push({
- test: lang.reg,
- use: genLoaders(lang)
- })
- }) return output;
- };
- // vue-loader的options
- exports.vueLoaderOptions = function() {
- var options = {
- loaders: {}
- };
- cssLang.forEach(lang = >{
- options.loaders[lang.name] = genLoaders(lang);
- });
- return options;
- }
接下来就是如何启动webpack-dev-server,vue-cli的webpack模板工程用的express及webpack中间件做开发服务器,其实用webpack-dev-server就能满足需求,当然用express能够做更多的事情,毕竟webpack-dev-server是一个轻量级的express。dev.js内容如下:
- var webpack = require('webpack');
- var webpackDevServer = require('webpack-dev-server');
- var devConfig = require("./webpack.dev.config");
- var config = require("./config");
- var compiler = webpack(devConfig);
- var server = new webpackDevServer(compiler, {
- hot: true,
- noInfo: true,
- publicPath: config.dev.outputPublicPath,
- stats: { colors: true }
- });
- server.listen(config.dev.port, "0.0.0.0");
- var url = `http://localhost:${config.dev.port}/`;
- // 需先安装 opn 模块 npm i opn -D
- var opn = require('opn');
- // 打包完毕后启动浏览器
- server.middleware.waitUntilValid(function() {
- console.log(`> Listening at ${url}`);
- opn(`${url}`);
- })
生产配置文件(webpack.prod.config.js)内容如下:
- // 设定为生产环境
- process.env.NODE_ENV = 'production';
- var webpack = require('webpack');
- var merge = require('webpack-merge');
- var HtmlWebpackPlugin = require('html-webpack-plugin');
- var ExtractTextPlugin = require('extract-text-webpack-plugin');
- var baseWebpackConfig = require('./webpack.base.config');
- var utils = require('./utils');
- var config = require('./config');
- module.exports = merge(baseWebpackConfig, {
- output: {
- path: config.prod.outputPath,
- publicPath: config.prod.outputPublicPath
- },
- module: {
- rules: utils.styleLoaders()
- },
- plugins: [
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': '"production"'
- }),
- new webpack.optimize.UglifyJsPlugin(),
- new ExtractTextPlugin({
- filename: "css/style.css?[contenthash:8]"
- }),
- new HtmlWebpackPlugin({
- filename: 'index.html',
- template: 'index.html',
- inject: true
- })
- ]
- })
生产构建(prod.js)内容如下:
- var webpack = require("webpack");
- var webpackProdConfig = require('./webpack.prod.config');
- webpack(webpackProdConfig, function(err, stats) {
- process.stdout.write(stats.toString());
- });
对应在package.json中添加开发和生产构建的命令如下:
- "scripts": {
- "dev": "node build/dev.js",
- "build": "node build/prod.js"
- }
参照vue-cli及webpack文档的提取公共代码的方式,利用插件webpack.optimize.CommonsChunkPlugin将来自node_modules下的模块提取到vendor.js(一般来讲都是外部库,短时间不会发生变化)。于是有如下代码:
- new webpack.optimize.CommonsChunkPlugin({
- name: 'vendor',
- minChunks: function(module, count) {
- return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
- }
- })
如果你查看未压缩版的vendor.js,会发现不仅包含vue的代码,还包含了webpackBootstrap(webpack模块加载器)的代码,按理说放在vendor里面也没啥问题,毕竟后面的模块都需要依赖于此,但是如果你的chunk使用了hash,一旦app代码发生了改变,相应的hash值会发生变化,webpackBootstrap的代码也会发生变化(如图),而我们提取vendor的初心就是这部分代码改变频率不大,显然这不符合我们的目标,那么应当将webpackBootstrap再提取到一个文件中,代码如下:
- new webpack.optimize.CommonsChunkPlugin({
- name: 'manifest',
- chunks: ['vendor']
- })
vue 2.2.0 后不能直接使用 require 来加载 vue,那么到底改是该使用 ES6 Module 还是 CommonJS 呢?,先看一个对比图:
全部使用 ES6 Module,即import、export default,最终打包的app.js为1.20KB。
全部使用 CommonJS(除了vue),即require、module.exports,最终打包的app.js为1.12KB。
虽然两者大小相差不大,但是这不禁让人觉得用 CommonJS 似乎是一条优化措施,那么代码层面到底是怎么回事呢?
为了一探究竟,注释了压缩插件,以about.vue最终构建的代码来看,使用 CommonJS 的代码如下:
- (function(module, exports, __webpack_require__) {
- "use strict";
- module.exports = {
- data: function data() {
- return {
- page: 'about'
- };
- }
- };
- }),
这基本上和 about.vue 中的代码相差无几,而使用 ES6 Module 构建的代码如下:
- (function (module, exports, __webpack_require__) {
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = {
- data: function data() {
- return {
- page: 'about'
- };
- }
- };
- }),
对比两种规范下构建后的代码,使用 ES6 Module 主要是多了 Object.defineProperty 那一部分,从而导致了最终打包的文件大一点儿。那是不是为了最终文件体积能小些就全部使用 CommonJS 呢?这个需要你充分理解 CommonJS 和 ES6 Module 的区别,引用《ECMAScript 6入门》这本书的解释如下:
ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。
为了更清楚的理解这段话,我们稍微做一下测试,在 src 下增加一个test.js,内容如下(分别将两种写法列出):
- // CommonJS
- var counter = 1;
- function incCounter() {
- counter++;
- }
- module.exports = {
- counter: counter,
- incCounter: incCounter,
- };
- // ES6 Module
- export let counter = 1;
- export
- function incCounter() {
- counter++;
- }
在about.vue中测试如下:
- // CommonJS
- var test = require('../test');
- export default {
- created() {
- console.log(test.counter); // 1
- test.incCounter();
- console.log(test.counter); // 1
- }
- }
- // ES6 Module
- import { counter, incCounter } from '../test';
- export default {
- created() {
- console.log(counter); // 1
- incCounter();
- console.log(counter); // 2
- }
- }
最终的输出值也印证了前面的解释,更详细的解读请查阅相关资料或书籍。只有深入理解了两者的区别,自然就能明白何时该使用何种规范。当然 ES6 作为未来的趋势,我们应该去做更多的尝试。
之前用懒加载的方式是:require.ensure,在 webpack2 中引入了 Code Splitting-Async 的新方法 import(),用于动态引入 ES Module。require.ensure 可以指定 chunkFilename,但是 import 没有很好的途径去指定,webpack3 为了解决这个问题,提出了用魔法注释的方式来指定模块名。
结合 vue-router 可以轻松实现懒加载,配置路由指向异步组件即可实现懒加载,比如:
- {
- path: '/async',
- component: () => import(/* webpackChunkName: "async" */'./views/async.vue')
- }
如果你发现使用 import() 运行时报错,有几种情况:
1.babel presets 配置为 es2015,则不支持动态导入功能,因此需要安装支持动态导入的 presets(npm i babel-preset-stage-2 -D),或者 babel 插件(npm i babel-plugin-syntax-dynamic-import -D);
2.babel presets 配置为 env,但是 modules 配置为 false,babel 则不会解析 import,可以安装插件 (npm i babel-plugin-syntax-dynamic-import -D)解决。
魔法注释虽然指定了块名,但是 webpack 默认的块名配置为 [id].js,即用的模块的 id 作为块名,因此需要我们手动改下配置。
修改 webpack.base.config.js 的 output:
- output: {
- filename: 'js/[name].js',
- chunkFilename: "js/[name].[chunkhash].js"
- }
效果如下图:
如果发现魔法注释没有生效,要检查下 .babelrc 的配置项 comments 是否设为 true。或者不配置 comments(默认为true)
extract-text-webpack-plugin 默认不会提取异步模块中的 CSS,需要加上配置:
- new ExtractTextPlugin({
- allChunks: true,
- filename: "css/style.css?[contenthash:8]"
- })
后面还会陆续补充webpack打包性能优化、单元测试配置等章节。
《vue2 vue-router2 webpack1》中提出了文章会和vue最新版保持一致,本文将继续和vue及webpack最新版本(限小版本调整),敬请持续关注。
来源: http://www.jqhtml.com/9541.html