Next & Previous

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/",
  "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 the inspect 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: [
  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:

…I came up with this working snippet:

// vue.config.js
module.exports = {
    chainWebpack: config => {
          .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: