vue cli修改默认webpack配置
背景
Vue CLI
作为一个Vue
的脚手架,帮助我们做了很多工作,比起create-react-app
脚手架,丝毫察觉不到有webpack
的身影,对于简单的开发工作,我们无需关注如何去修改他的默认配置,但是如果我们想做一些定制化的开发,比如修改一些公共变量或者添加一个插件,其实Vue CLI文档都有介绍,但是说实话为了理解这些东西我查了不少文档,说实话我认为作为官方文档还是不够接地气,下面给大家分享一下我的认知,一步一步的。
开始
首先呢,初始化的项目并没有为我们提供一个修改配置的入口文件,需要我们在项目根目录下新建一个vue.config.js
文件,这个文件是可选的,他会被@vue/cli-service
自动加载,所有配置文件的修改都在这里了。
最简单的配置,configureWebpack
比如我们自己开发了一个插件或者网上找了个webpack
插件,我们想将这个插件应用到项目中,我们可以:
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new MyWebpackPlugin()
]
}
}
这个配置方式将通过webpack-merge
,将结果合并到最终的webpack
配置中。
开放webpack配置文件
许多读者朋友可能会比较好奇默认的配置文件到底配置了些什么,可以通过命令行方式将配置文件开放出来,在项目路径下运行
vue inspect > output.js
运行成功该命令行后,可以发现根目录多了一个output.js
文件,打开后就可以看到原始的配置文件了。
初识webpack-chain
Vue CLI
提供了一个维护入口来维护webpack
内部配置,可以通过它来维护。下面粘贴一个官网的例子,来介绍一下这个函数的使用方法。
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
// modify the options...
return options
})
}
}
看到上面的代码,大家可能会产生以下几个疑问:
- config 这个参数是什么含义
- config 修改参数时,如何做到一步一步往下链式修改内容
下面通过几个小例子来解释这个链式调用的使用方式:
(1) 修改html-webpack-plugin配置
首先在output.js
中查询html-webpack-plugin
的默认配置信息,如下所示:
/* config.plugin('html') */
new HtmlWebpackPlugin(
{
title: 'vue20218',
templateParameters: function () { /* omitted long function */ },
template: 'F:\\vue20218\\public\\index.html'
}
),
其中的title和template是我创建项目时输入的名称和模板地址,这里重点关注注释的部分config.plugin('html')
。细心的小伙伴可能会发现,在public/index.html这个模板中,title的名称是:
<title><%= htmlWebpackPlugin.options.title %></title>
读取的是动态的值,我现在想改变title的值,那么我就可以在vue.config.js
中这样写:
module.exports = {
chainWebpack: (config) => {
config.plugin('html')
.tap(args => {
args[0].title = '123'
return args
})
},
}
可以发现,config.plugin('html')
有tap函数,函数参数为html-webpack-plugin
的各个变量,通过变更然后返回参数来完成变量的修改。
(2) 修改alias值
首先在output.js中查询关键字 alias
,结果如下
resolve: {
alias: {
'@': 'F:\\vue20218\\src',
vue$: 'vue/dist/vue.runtime.esm.js',
'@mixins': 'F:\\vue20218\\src\\mixins'
},
...
}
可以发现默认的路径解析,@可以作为F:/vue20218/src
路径的替代,然后我们再添加一个。
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack: (config) => {
config.resolve.alias
.set('@mixins', resolve('src/mixins'))
config.plugin('html')
.tap(args => {
args[0].title = '123'
return args
})
},
}
其中 path 和 resolve是辅助下面功能的引用和方法。从这个修改方式可以发现,这种层级引用的变量,可以通过a.b.set
的方式来设置,其中set接收键值对,如果想继续设置,可以在set基础上再调用set方法,类似
config.resolve.alias
.set('@mixins', resolve('src/mixins'))
.set('@okk', resolve('src/okk'))
(3) 修改babel-loader的行为
首先在output.js中查询关键字 babel-loader
,结果如下
/* config.module.rule('js').use('babel-loader') */
{
loader: 'F:\\vue20218\\node_modules\\babel-loader\\lib\\index.js'
}
其中再次关注被注释的部分,如果想修改,可以用下面这种方式:
const merge = require('webpack-merge')
module.exports = {
chainWebpack: config => {
config.module.rule('js')
.use('babel-loader')
.loader('F:\\vue20218\\node_modules\\babel-loader\\lib\\index.js')
.tap(options => {
return merge(options, {
plugins: [
["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }]
]
})
})
}
}
熟悉上述代码的可能知道,这句话的作用就是将antd按需加载,小贴士:要实现该功能,别忘了安装babel-plugin-import
。
细心的大家一定发现了合并时我们用到了merge函数,而且可以发现一直到.use('url-loader')
都是一致的,为什么又加了一个.loader('F:\\vue20218\\node_modules\\babel-loader\\lib\\index.js')
呢?
因为处理一种文件,可能存在多个loader,这句话正是唯一确定要修改的loader对象!
总结:
以上总结了Vue CLI下修改webpack普通对象的值、loader的值以及plugin的值,希望有困惑的朋友们能够解惑,有什么问题也可以留言讨论,谢谢观看。