学习vue.config.js

434 阅读3分钟

调整 webpack 配置就是在 vue.config.js 中去设置,这个文件主要用于打包文件时候的一些配置。在根目录创建一个vue.config.js文件后就开启学习之旅

1. 查看默认的webpack配置

因为 @vue/cli-service 对 webpack 配置进行了抽象,所以理解配置中包含的东西会比较困难,vue-cli-service 暴露了 inspect 命令用于审查解析好的 webpack 配置.在控制台输入下面命令会得到相因的配置

vue inspect > output.js
//注意它输出的并不是一个有效的 webpack 配置文件,而是一个用于审查的被序列化的格式
//得到的是一个output.js文件
vue inspect module.rules.0
//只审查第一条规则
vue inspect --rule vue
vue inspect --plugin html
//指向一个规则或插件的名字:
vue inspect --rules
vue inspect --plugins
//列出所有规则和插件的名字:

2.基本的配置参数

module.exports ={ 
productionSourceMap: false,
publicPath: './',
outputDir: 'dist',
assetsDir: 'assets',
devServer: { port: 8090, host: '0.0.0.0', https: false, open: true }, 
// 其他配置 ...
  • productionSourceMap:生产环境是否要生成 sourceMap

  • publicPath:部署应用包时的基本 URL,用法和 webpack 本身的 output.publicPath 一致

    • 可以通过三元运算去配置devprod环境, publicPath: process.env.NODE_ENV === 'production' ? '/prod/' : './'
  • outputDir: build 时输出的文件目录

  • assetsDir: 放置静态文件夹目录

  • devServer: dev环境下,webpack-dev-server 相关配置

    • port: 开发运行时的端口
    • host: 开发运行时域名,设置成'0.0.0.0',在同一个局域网下,如果你的项目在运行,同时可以通过你的http://ip:port/...访问你的项目
    • https: 是否启用 https
    • open: npm run serve 时是否直接打开浏览器

3.配置方法一:简单的配置方式(configureWebpack)

在 vue.config.js 中的 configureWebpack 选项里写一个对象:该对象将会被 webpack-merge 合并入最终的 webpack 配置。

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      new MyAwesomeWebpackPlugin()
    ]
  }
}

想要切换环境,或者想要直接修改配置,那就换成一个函数 (该函数会在环境变量被设置之后懒执行)。该方法的第一个参数会收到已经解析好的配置。在函数内,你可以直接修改配置,或者返回一个将会被合并的对象:

// vue.config.js
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      // 为生产环境修改配置...
    } else {
      // 为开发环境修改配置...
    }
  }
}

4. 配置方法二:链式操作 (高级)

Vue CLI 内部的 webpack 配置是通过 webpack-chain 维护的。这个库提供了一个 webpack 原始配置的上层抽象,使其可以定义具名的 loader 规则和具名插件,并有机会在后期进入这些规则并对它们的选项进行修改。它允许我们更细粒度的控制其内部配置。

  • loader

(1)基本使用方法:

config.module
  .rule(name)
    .use(name)
      .loader(loader)
      .options(options)

(2)修改 Loader 选项(直接修改options)

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

(4)替换一个规则里的 Loader

如果你想要替换一个已有的基础 loader,例如为内联的 SVG 文件使用 vue-svg-loader 而不是加

// vue.config.js
module.exports = {
  chainWebpack: config => {
    const svgRule = config.module.rule('svg')

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

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

(5)添加一个新的 Loader


// vue.config.js
module.exports = {
  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()
  }
}

  • plugin

(1)基本使用情况

config
  .plugin(name)
  .use(WebpackPlugin, args)
  

(2)新增hot-hash-webpack-plugin

const HotHashWebpackPlugin = require('hot-hash-webpack-plugin');
module.exports = {
    chainWebpack: (config) => {
        // 新增一个`hot-hash-webpack-plugin`
        // 注意:这里use的时候不需要使用`new HotHashWebpackPlugin()`
        config.plugin('hotHash')
              .use(HotHashWebpackPlugin, [{ version: '1.0.0' }]);
    }
}

(3)删除console和debugger

const HotHashWebpackPlugin = require('hot-hash-webpack-plugin');
module.exports = {
    chainWebpack: (config) => {
        // 修改打包时css抽离后的filename及抽离所属目录
        config.plugin('extract-css')
                .tap(args => [{
                    filename: 'css/[name].[contenthash:8].css',
                    chunkFilename: 'css/[name].[contenthash:8].css'
                }]);
        
        // 正式环境下,删除console和debugger
        config.optimization
                .minimize(true)
                .minimizer('terser')
                .tap(args => {
                    let { terserOptions } = args[0];
                    terserOptions.compress.drop_console = true;
                    terserOptions.compress.drop_debugger = true;
                    return args
                });
    }
}

config.plugins.delete(name)//对于一些`webpack`默认的 `plugin` ,如果不需要可以进行删除

(4)用tap修改插件选项

config
    .plugin(name)
    .tap(args => newArgs)

5.一些常见的配置

  1. 定义全局全局变量,DefinePlugin 是 webpack 已经默认配置的,我们可以对参数进行修改
config.plugin('define').tap(args => [{ 
    ...args, 
    "window.isDefine": JSON.stringify(true),
    }]);

  1. 自定义filename
config.output.filename('./js/[name].[chunkhash:8].js');//自定义打包后js文件的路径及文件名字
  1. 设置别名alias

config.resolve.alias
        .set('@', resolve('src')) 
        .set('api', resolve('src/apis'))
        .set('common', resolve('src/common'))

//一份大佬的vue.config.js的配置
const path = require('path');
const HotHashWebpackPlugin = require('hot-hash-webpack-plugin');
const WebpackBar = require('webpackbar');
const resolve = (dir) => path.join(__dirname, '.', dir);

module.exports = {
    productionSourceMap: false,
    publicPath: './',
    outputDir: 'dist',
    assetsDir: 'assets',
    devServer: {
        port: 9999,
        host: '0.0.0.0',
        https: false,
        open: true
    },

    chainWebpack: (config) => {
        const types = ['vue-modules', 'vue', 'normal-modules', 'normal'];
        types.forEach(type => {
            let rule = config.module.rule('less').oneOf(type)
            rule.use('style-resource')
                .loader('style-resources-loader')
                .options({
                    patterns: [path.resolve(__dirname, './lessVariates.less')]
                });
        });

        config.resolve.alias
            .set('@', resolve('src')) 
            .set('api', resolve('src/apis'))
            .set('common', resolve('src/common'))

        config.module.rule('images').use('url-loader')
            .tap(options => ({
                name: './assets/images/[name].[ext]',
                quality: 85,
                limit: 0,
                esModule: false,
            }));

        config.module.rule('svg')
            .test(/\.svg$/)
            .include.add(resolve('src/svg'))
            .end()
            .use('svg-sprite-loader')
            .loader('svg-sprite-loader');

        config.plugin('define').tap(args => [{
            ...args, 
            "window.isDefine": JSON.stringify(true)
        }]);

        // 生产环境配置
        if (process.env.NODE_ENV === 'production') {
            config.output.filename('./js/[name].[chunkhash:8].js');
            config.output.chunkFilename('./js/[name].[chunkhash:8].js');
            config.plugin('extract-css').tap(args => [{
                filename: 'css/[name].[contenthash:8].css',
                chunkFilename: 'css/[name].[contenthash:8].css'
            }]);
            config.plugin('hotHash').use(HotHashWebpackPlugin, [{ version : '1.0.0'}]);
            config.plugin('webpackBar').use(WebpackBar);

            config.optimization.minimize(true)
                .minimizer('terser')
                .tap(args => {
                    let { terserOptions } = args[0];
                    terserOptions.compress.drop_console = true;
                    terserOptions.compress.drop_debugger = true;
                    return args
                });
            config.optimization.splitChunks({
                cacheGroups: {
                    common: {
                        name: 'common',
                        chunks: 'all',
                        minSize: 1,
                        minChunks: 2,
                        priority: 1
                    },
                    vendor: {
                        name: 'chunk-libs',
                        chunks: 'all',
                        test: /[\\/]node_modules[\\/]/,
                        priority: 10
                    }
                }
            });
        }
    }
};