vue2之vue.config.js配置

3,311 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

最近在写项目的时候,突然发现打包出了点小问题,在看vue-cli文档排查问题的过程中,便有了这篇文档,主要介绍vue.config.js的常见配置内容。

vue.config.js文件

vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。

vue.config.js其实主要目的就是导出一个对象,这个对象里面有很多配置。

// vue.config.js
module.exports = {

}

以我项目中代码为例,vue.config.js中的内容如下:

const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

const path = require('path');
const resolve = dir => path.join(__dirname, dir);

const isProduction = process.env.NODE_ENV === 'production';
const isDevelopment = process.env.NODE_ENV === 'development';

module.exports = {
  // 基于部署应用包时的基本URL
  publicPath: '/',
  productionSourceMap: false,
  configureWebpack: config => {
    // elementplus按需引入
    const plugins = [
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      })
	  ];
    config.plugins.push(...plugins);
    // 为生产环境修改配置...
    if (process.env.NODE_ENV === 'production') {
      config.mode = 'production';
      // 打包文件大小配置
      config.performance = {
        maxEntrypointSize: 10000000,
        maxAssetSize: 30000000
      }
    }
  },
  chainWebpack: config => {
    // 添加别名
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@apis', resolve('src/apis'))
      .set('@assets', resolve('src/assets'))
      .set('@scss', resolve('src/assets/scss'))
      .set('@components', resolve('src/components'))
      .set('@mixins', resolve('src/mixins'))
      .set('@plugins', resolve('src/plugins'))
      .set('@router', resolve('src/router'))
      .set('@store', resolve('src/store'))
      .set('@utils', resolve('src/utils'))
      .set('@config', resolve('src/config'))
      .set('@views', resolve('src/views'));

    // code splitting
    config.optimization.splitChunks({
      cacheGroups: {
        // 第三方组件
        vendors: {
          // 指定chunks名称
          name: `chunk-vendors`,
          // 符合组的要求就给构建
          test: /[\\/]node_modules[\\/]/,
          // 优先级:数字越大优先级越高,因为默认值为0,所以自定义的一般是负数形式,决定cacheGroups中相同条件下每个组执行的优先顺序。
          priority: -10,
          // 仅限于最初依赖的第三方
          chunks: 'initial'
        },
        // 公共组件
        common: {
          name: `chunk-common`,
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          //这个的作用是当前的chunk如果包含了从main里面分离出来的模块,则重用这个模块,这样的问题是会影响chunk的名称。
          reuseExistingChunk: true
        },
        // // 将elementplus单独拆分出来
        element: {
          name: `element-plus`,
          test: /element-plus/,
          priority: 20,
          chunks: 'all'
        },
        // 将vue相关的单独拆分出来
        vue: {
          name: `vue`,
          test: /vue/,
          priority: 20,
          chunks: 'initial'
        }
      }
    });

    // 资源配置:在生产环境和开发环境配上title
    if (isProduction || isDevelopment) {
      config.plugin('html')
        .tap(args => {
          args[0].title = 'test';
          return args;
        });
    }

    // 打包分析
    if (isProduction) {
      if (process.env.npm_config_report) {
        config
          .plugin('webpack-bundle-analyzer')
          .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
          .end();
        config.plugins.delete('prefetch');
      }
    }
  },
  css: {
    // 是否使用css分离插件 ExtractTextPlugin
    // 是否将组件中的 CSS 提取至一个独立的 CSS 文件中 (而不是动态注入到 JavaScript 中的 inline 代码)。
    extract: true,
    // 开启 CSS source maps? 
    sourceMap: false,
    loaderOptions: {
      scss: {
        // 向全局sass样式传入共享的全局变量, $src可以配置图片cdn前缀
        // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
        prependData: `
          @import '@scss/variables.scss';
          @import '@scss/mixins.scss';
          @import '@scss/function.scss';
          $src: '${process.env.VUE_APP_BASE_API}';`
      }
    }
  },
  devServer: {
    // 让浏览器 overlay 同时显示警告和错误
    overlay: {
      warnings: true,
      errors: true
    },
    // open: false, // 是否打开浏览器
    host: '',
    port: '8180', // 代理端口
    // https: false,
    hotOnly: true, // 热更新
    proxy: {
      '/ins': {
        target: 'http://pre-fundbackend.jinfuzi.cn/',
      },
      '/alc': {
        target: 'http://10.3.20.64:8090/'
        // target: 'http://192.168.172.113:8090/'
      },
      '/sys': {
        target: 'http://192.168.20.120:27730'
      }
    }
  },
  // 构建时开启多进程处理 babel 编译
  parallel: require('os').cpus().length > 1,
  // https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
  pwa: {},
  // 第三方插件配置
  pluginOptions: {}
}

vue.config.js配置项

publicPath

这个属性是用来配置部署应用包时的基本URL,属性值是字符串类型,默认是'/'。如果是部署在www.my-app.com上,那么访问路径就是https://www.my-app…', 那么访问路径就是www.my-app.com/my-app/。

一般我们不修改, 保持默认的'/'

publicPath: '/',

outputDir

当运行 vue-cli-service build 时生成的生产环境构建文件的目录(也就是说执行 npm run build时生成的目录名)。属性值也是字符串类型,默认值是'dist'。

一般我们也不修改,保持默认的dist

outputDir: 'dist'

assetsDir

放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。也就是说在dist中单独再分出一个静态资源的目录。属性值也是字符串类型,默认值是''。 不过需要注意的是如果我们配置打包时设置filename 或 chunkFilename 时,assetsDir 会被忽略。

一般我们也不修改,保持默认的’‘

assetsDir: ''

indexPath

指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径。属性值是字符串,默认是'index.html'。

一般我们也不修改,保持默认的'index.html'

indexPath: 'index.html'

filenameHashing

是否对生成的静态资源在它们的文件名中包含 hash 值。属性值是布尔型。默认是true,也就是文件名带有hash值。

一般我们也不修改,保持默认的true

filenameHashing: true

pages

在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。因此可以使用这个属性来配置,属性值是个对象。

一般我们的项目都是单页面应用,因此不需要配置这个,如果是多页面应用,需要配置,参考如下:

pages: {
    index: {
      // page 的入口
      entry: 'src/index/main.js',
      // 模板来源
      template: 'public/index.html',
      // 在 dist/index.html 的输出
      filename: 'index.html',
      // 当使用 title 选项时,
      // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
      title: 'Index Page',
      // 在这个页面中包含的块,默认情况下会包含
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // 当使用只有入口的字符串格式时,
    // 模板会被推导为 `public/subpage.html`
    // 并且如果找不到的话,就回退到 `public/index.html`。
    // 输出文件名会被推导为 `subpage.html`。
    subpage: 'src/subpage/main.js'
  }

lintOnSave

是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码。这个值会在 @vue/cli-plugin-eslint 被安装之后生效。属性值类型是boolean | 'warning' | 'default' | 'error',默认是'default'.

  • true或‘warning’: eslint-loader 会将 lint 错误输出为编译警告。默认情况下,警告仅仅会被输出到命令行,且不会使得编译失败。
  • 'default': 强制 eslint-loader 将 lint 错误输出为编译错误,同时也意味着 lint 错误将会导致编译失败。
  • 'error': eslint-loader 把 lint 警告也输出为编译错误,这意味着 lint 警告将会导致编译失败。

如果你想要浏览器overlay 同时显示警告和错误,配置如下:

devServer: {
  overlay: {
    warnings: true,
    errors: true
  }
}

runtimeCompiler

是否使用包含运行时编译器的 Vue 构建版本。属性值是布尔类型。默认是false。如果设置了true,你就相当于有了完整版vue,可以在new Vue中使用template选项。 默认情况下我们是不能使用template的,通过渲染函数h()来完成。

productionSourceMap

生产环境下是否生成source map。source map意味着我们可以查看源码,帮助我们debugger查看问题,这也意味着如果使用的话会增加编译时间。默认为true。

一般情况下,我们会设置成false, 来加速生产环境的编译。

productionSourceMap: false

configureWebpack

configureWebpack是用来配置webpack的,属性值可以是对象或者函数。

  • 对象:会通过 webpack-merge 合并到最终的配置中。
  • 函数:会接收被解析的配置作为参数。该函数既可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。
// 对象形式
configureWebpack: {
  plugins: [
    new MyAwesomeWebpackPlugin()
  ]
}

// 函数形式
configureWebpack: config => {
  if (process.env.NODE_ENV === 'production') {
    // 为生产环境修改配置...
  } else {
    // 为开发环境修改配置...
  }
}

configureWebpack应用

问题描述: 项目打包的时候,有两个提示,说文件打包太大,如图所示

企业微信截图_860cd092-c7c9-4e38-8ac5-2ad5edf3a18e.png

解决方式 在configureWebpack中配置打包文件大小

configureWebpack: config => {
  // 为生产环境修改配置...
  if (process.env.NODE_ENV === 'production') {
    config.mode = 'production';
    // 打包文件大小配置
    config.performance = {
      maxEntrypointSize: 10000000,
      maxAssetSize: 30000000
    }
  }
}

这时候,我之前在configureWebpack中配置过elementplus的按需引入插件是按照对象的形式配置的,如下:

configureWebpack: {
  plugins: [
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ]
}

如何将对象形式和函数形式合并呢 对象里面是没法加函数的,但是函数里面可以有对象呀,因此主体还是函数默认,只是需要在参数上将对象内容push进去。

configureWebpack: config => {
  // elementplus按需引入
  const plugins = [
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    })
  ];
  config.plugins.push(...plugins);
  // 为生产环境修改配置...
  if (process.env.NODE_ENV === 'production') {
    config.mode = 'production';
    // 打包文件大小配置
    config.performance = {
      maxEntrypointSize: 10000000,
      maxAssetSize: 30000000
    }
  }
}

具体其他操作参考webpack

chainWebpack

是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。一般这里面可以定义具名的loader规则和具名插件。

1. 添加loader

chainWebpack: config => {
  // GraphQL Loader
  config.module
    .rule('graphql')
    .test(/\.graphql$/)
    .use('graphql-tag/loader')
      .loader('graphql-tag/loader')
      .end()
    // 你还可以再添加一个 loader
    .use('other-loader')
      .loader('other-loader')
      .end()
}

2. 替换一个规则里的loader

chainWebpack: config => {
  const svgRule = config.module.rule('svg')

  // 清除已有的所有 loader。
  // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
  svgRule.uses.clear()

  // 添加要替换的 loader
  svgRule
    .use('vue-svg-loader')
      .loader('vue-svg-loader')
}

3. 修改loader选项

chainWebpack: config => {
  config.module
    .rule('vue')
    .use('vue-loader')
      .tap(options => {
        // 修改它的选项...
        return options
      })
}

4. 修改插件选项

chainWebpack: config => {
  config
    .plugin('html')
    .tap(args => {
      return [/* 传递给 html-webpack-plugin's 构造函数的新参数 */]
    })
}

具体其他操作参考webpack

css.requireModuleExtension

默认情况下,只有 *.module.[ext] 结尾的文件才会被视作 CSS Modules 模块。设置为 false 后你就可以去掉文件名中的 .module 并将所有的 *.(css|scss|sass|less|styl(us)?) 文件视为 CSS Modules 模块。默认值是true.

css.extract

是否将组件中的css提取出来,放到一个单独的css文件中,而不是以js的形式注入到inline代码中。属性值是布尔和对象类型,默认情况下生产环境是true, 开发环境是false。

一般情况下我们设置为true

css: {
  extract: true
}

css.sourceMap

和productionSourceMap差不多,只是这个是针对css代码的。属性值是布尔型的。默认是false.

为了提高构建性能,我们一般不设置或者设置为false.

css: {
  sourceMap: false
}

css.loaderOptions

这个属性是用来给loder配置选项的。属性值是对象。 loder主要是以下几种:

  • css-loader
  • postcss-loader
  • sass-loader
  • less-loader
  • stylus-loader
// 全局使用预处理器定义的变量
css: {
  loaderOptions: {
    scss: {
      // 向全局sass样式传入共享的全局变量, $src可以配置图片cdn前缀
      // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
      prependData: `
        @import '@scss/variables.scss';
        @import '@scss/mixins.scss';
        @import '@scss/function.scss';
        $src: '${process.env.VUE_APP_BASE_API}';`
    }
  }
}

pluginOptions

用来给第三方插件传递选项,属性值是对象。

pluginOptions: {
  foo: {
    // 插件可以作为 `options.pluginOptions.foo` 访问这些选项。
  }
}

devServer

这个是用来配置开发服务器的一些选项,比如host, port, https等,具体可以参考webpack-dev-server 的选项。

devServer.proxy

这个是用来配置代理的,前面我们已经介绍过,具体可以参考我的另一篇文章。