How to change webpack settings set by vue-cli
I just tried out vue-cli
to set up a Vue project from scratch. I’ve mostly worked with Vue either in an established project or by sprinkling it into a simple HTML project. So this was a concept that needed filling in in my brain.
I’m not gonna cover using vue-cli to start a project, that was easy enough. I made a preset that was based on default but added dart-sass
, pwa
, and router
. But for our intents my setup is basically like default
.
Difference between vue-cli and manual webpack setup
In your JavaScript-centric front-end project, your package.json
is the master of the tasks that exist - the usual build/watch/serve/start stuff.
When you put webpack into a project, you will end up with some tasks that invoke it:
"scripts" : {
"start": "webpack --progress --config build/webpack.dev.conf.js",
"build": ...
}
…perhaps not directly, but at some layer of your build and start tasks you’ll find that you call upon webpack and pass it some config.
But in a vue-cli project, your tasks look like this:
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
So it begs the question: where is webpack gonna get its config from? You won’t find any .conf.js
files in your vue-cli project which relate to webpack.
Instead, any config tweaks you want to make need to go in the special vue.config.js
file. Let’s dig into that…
Using vue.config.js
and vue inspect
In their own words:
Since
@vue/cli-service
abstracts away the webpack config, it may be more difficult to understand what is included in the config, especially when you are trying to make tweaks yourself. …vue-cli-service
exposes theinspect
command for inspecting the resolved webpack config.
Ok, that makes sense at some level since we don’t all need to be webpack config geniuses, and who doesn’t like convention over configuration?
A worked example - switching on eslint auto fix
The default linter is eslint. It has a nice feature which is autofix for warnings, and I want to switch it on.
Usually, I would go into my base webpack config, find the eslint-loader
rule and add fix: true
into the options
object:
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('prettier'),
emitWarning: false,
fix: true
}
}
So let’s find the equivalent. I can run vue inspect > output.js
and then search that file for eslint
or eslint-loader
:
/* config.module.rule('eslint') */
{
enforce: 'pre',
test: /\.(vue|(j|t)sx?)$/,
exclude: [
/node_modules/,
'D:\\git\\vue-tests\\hello-world\\node_modules\\@vue\\cli-service\\lib'
],
use: [
/* config.module.rule('eslint').use('eslint-loader') */
{
loader: 'D:\\git\\vue-tests\\hello-world\\node_modules\\eslint-loader\\index.js',
options: {
/* Snipped for brevity */
}
}
]
}
Now I needed to Duck around to figure out how to set up vue.config.js
to modify all this…
Create vue.config.js
Make a new file in the root of your project (alongside package.json
and friends) and name it vue.config.js
- it isn’t created during project setup.
Now let’s consult the Vue CLI Webpack setup guide
At first I thought I could get away with their “simple configuration” option where you directly mutate the Webpack config. This didn’t work for me after quite some tinkering, so I moved onto the “chaining” approach.
By piecing together the following:
- The guide linked above
- The clues emitted by
vue inspect
- What we know about how we usually switch on the fix option
…I came up with this working snippet:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('eslint')
.use('eslint-loader')
.loader('eslint-loader')
.tap(options => {
options.fix = true
return options
})
}
}
You can use vue inspect
again to check that the config has changed, but because the serve
task reads the config only on startup, you need to restart the task to make your environment respect the change you made.
Things to remember
If I were doing this again in future, I’d bear in mind:
- Whatever loader I’m tweaking, I need to understand how it is normally configured (e.g.
eslint-loader
) - Vue inspect will give me half of the code to get to the solution
chainWebpack
seems to be the way to go- I can verify a change using
vue inspect
but have to restart theserve
task to see the effects