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的值,希望有困惑的朋友們能夠解惑,有什麼問題也可以留言討論,謝謝觀看。