vue-cli 中 chainWebpack 的常用操作

原文: vuecli 中 chainWebpack 的常用操作

1、webpack 配置很多,这里我们探讨比较经常需要修改的:

  • 不复杂,可以在 configWebpack 中操作:
    • mode
    • devtool

  • 配置复杂,可以在 chainWebpack 中操作:
    • module.rules
    • plugins
    • optimization

2、使用 vue inspect 可以查看当前 webpack 配置

vue inspect > output.js

配置无非增删改查四个操作,接下来一一列举

一、增

  • 增加规则
// loader 默认是从下往上处理

// enforce: 决定现有规则调用顺序
// - pre 优先处理
// - normal 正常处理(默认)
// - inline 其次处理
// - post 最后处理
module.exports = {
    chainWebpack: config => {
        config.module
            .rule('lint') // 定义一个名叫 lint 的规则
                .test(/.js$/) // 设置 lint 的匹配正则
                .pre()  // 指定当前规则的调用优先级
                .include // 设置当前规则的作用目录,只在当前目录下才执行当前规则
                    .add('src')
                    .end()
                .use('eslint') // 指定一个名叫 eslint 的 loader 配置
                    .loader('eslint-loader') // 该配置使用 eslint-loader 作为处理 loader
                    .options({ // 该 eslint-loader 的配置
                        rules: {
                            semi: 'off'
                        }
                    })
                    .end()
                .use('zidingyi') // 指定一个名叫 zidingyi 的 loader 配置
                    .loader('zidingyi-loader') // 该配置使用 zidingyi-loader 作为处理 loader
                    .options({ // 该 zidingyi-loader 的配置
                        rules: {
                            semi: 'off'
                        }
                    })
        config.module
            .rule('compile')
                .test(/.js$/)
                .include
                    .add('src')
                    .add('test')
                    .end()
                .use('babel')
                    .loader('babel-loader')
                    .options({
                        presets: [
                            ['@babel/preset-env', { modules: false }]
                        ]
                    })
    }
}

最后将解析为如下配置:

{
    module: {
        rules: [
            /* config.module.rule('lint') */
            {
                test: /.js$/,
                enforce: 'pre',
                include: ['src'],
                use: [
                    /* config.module.rule('lint').use('eslint') */
                    {
                        loader: 'eslint-loader',
                        options: {
                            rules: {
                                semi: 'off'
                            }
                        }
                    },
                    /* config.module.rule('lint').use('zidingyi') */
                    {
                        loader: 'zidingyi-loader',
                        options: {
                            rules: {
                                semi: 'off'
                            }
                        }
                    }
                ]
            },
            /* config.module.rule('compile') */
            {
                test: /.js$/,
                include: ['src', 'test'],
                use: [
                    /* config.module.rule('compile').use('babel') */
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                ['@babel/preset-env', { modules: false }]
                            ]
                        }
                    }
                ]
            }
        ]
    }
}
  • 增加插件
module.exports = {
    chainWebpack: config => {
        // 用法:
        // config
        //     .plugin(name)
        //         .use(WebpackPlugin, args)
        
        // 示例:
        config
            .plugin('clean') // 创建一个名称为 clean 的插件
                .use(CleanPlugin, [['dist'], { root: '/dir' }]) // 不要用 new 去创建插件,因为已经为你做好了
    }
}
  • 增加 optimization.minimizers
// 用法(v5版本可用):
config.optimization
  .minimizer(name)
  .use(WebpackPlugin, args)

// 示例:
config.optimization
  .minimizer('css')
  .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true } }])

二、删

  • 删除单个规则中的全部 loader
// vue.config.js
module.exports = {
  chainWebpack: config => {
    const svgRule = config.module.rule('svg')

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

    // 添加要替换的 loader
    svgRule
      .use('vue-svg-loader')
        .loader('vue-svg-loader')
  }
}
  • 删除单个规则中的一个loader
// 删除前:
{
    test: /.m?jsx?$/,
    exclude: [
        function () { /* omitted long function */ }
    ],
    use: [
        /* config.module.rule('js').use('cache-loader') */
        {
            loader: 'cache-loader',
            options: {
                cacheDirectory: 'D:\webproject\webapp-jy\node_modules\.cache\babel-loader',
                cacheIdentifier: '519fc596'
            }
        },
        /* config.module.rule('js').use('babel-loader') */
        {
            loader: 'babel-loader'
        }
    ]
}


// 删除后:
const jsRule = config.module.rule('js')
// 删除 cache-loader
jsRule.uses.delete('cache-loader')
{
    test: /.m?jsx?$/,
    exclude: [
        function () { /* omitted long function */ }
    ],
    use: [
        /* config.module.rule('js').use('babel-loader') */
        {
            loader: 'babel-loader'
        }
    ]
}
  • 删除单个规则
const moduleRule = config.module
// 删除命名为  js 的规则
moduleRule.rules.delete('js')
  • 删除插件
config.plugins.delete(name)
  • 删除 optimization.minimizers
config.optimization.minimizers.delete(name)

三、改

  • 修改单个 loader 的配置
// 两种写法都可修改
config.module
  .rule('compile')
    .use('babel')
      .tap(options => merge(options, {
        plugins: ['@babel/plugin-proposal-class-properties']
      }))

config.module
  .rule('compile')
    .use('babel')
    .loader('babel-loader')
      .tap(options => merge(options, {
        plugins: ['@babel/plugin-proposal-class-properties']
      }))
  • 在多个 loader 中进行添加或者删除
config.module.rule('js').toConfig():
// {
//   test: /.m?jsx?$/,
//   exclude: [ [Function] ],
//   use: [
//     { loader: 'cache-loader', options: [Object] },
//     { loader: 'babel-loader' }
//   ]
// }

// 这里以添加一个新的 loader 为例
// 1、拿到原来的 loader 
let originUse = config.module.rule('js').toConfig().use
// 2、添加 loader
let newLoader = { loader: 'eslint-loader' }
originUse.splice(1, 0, newLoader)
// 3、清空原来的 loader
config.module.rule('js').uses.clear()
// 4、重新设置新的 loader
config.module.rule('js').merge({ use: originUse})

// {
//   test: /.m?jsx?$/,
//   exclude: [ [Function] ],
//   use: [
//     { loader: 'cache-loader', options: [Object] },
//     { loader: 'eslint-loader' },
//     { loader: 'babel-loader' }
//   ]
// }
  • 修改插件参数
// 用法:
config.plugin(name)
  .tap(args => newArgs)
// 示例:
config.plugin('env')
  .tap(args => [...args, 'SECRET_KEY'])

// 修改前:
/* config.plugin('optimize-css') */
new OptimizeCssnanoPlugin(
    {
        sourceMap: false,
        cssnanoOptions: {
            preset: [
                'default',
                {
                    mergeLonghand: false,
                    cssDeclarationSorter: false
                }
            ]
        },
    }
)
// 修改后:
config.plugin('optimize-css')
  .tap(args => {
      args[0].yy = 1
      return args
  })
/* config.plugin('optimize-css') */
new OptimizeCssnanoPlugin(
    {
        sourceMap: false,
        cssnanoOptions: {
            preset: [
                'default',
                {
                    mergeLonghand: false,
                    cssDeclarationSorter: false
                }
            ]
        },
        yy: 2
    }
)
config.plugin('optimize-css')
  .tap(args => {
      return [...args, { x: 1 }]
  })
/* config.plugin('optimize-css') */
new OptimizeCssnanoPlugin(
    {
        sourceMap: false,
        cssnanoOptions: {
            preset: [
                'default',
                {
                    mergeLonghand: false,
                    cssDeclarationSorter: false
                }
            ]
        }
    },
    {
        x: 1
    }
)
  • 修改插件实例
config.plugin(name)
  .init((Plugin, args) => new Plugin(...args))
  • 修改插件调用顺序
    • 指定当前插件上下文应该在另一个指定插件之前/之后执行,你不能在同一个插件上同时使用 .before() 和 .after()

// 用法:
// 在 otherName 之前调用
config
  .plugin(name)
    .before(otherName)

// 在 otherName 之后调用
config
  .plugin(name)
    .after(otherName)

// 示例:
// 修改之前:
[
    /* config.plugin('named-chunks') */
    new NamedChunksPlugin(
        function () { /* omitted long function */ }
    ),
    /* config.plugin('copy') */
    new CopyWebpackPlugin(
        []
    )
]
// 修改后:
config.plugin('named-chunks')
  .after('copy')
[
    /* config.plugin('copy') */
    new CopyWebpackPlugin(
        []
    ),
    /* config.plugin('named-chunks') */
    new NamedChunksPlugin(
        function () { /* omitted long function */ }
    )
]

config.plugin('copy')
  .before('named-chunks')
[
    /* config.plugin('copy') */
    new CopyWebpackPlugin(
        []
    ),
    /* config.plugin('named-chunks') */
    new NamedChunksPlugin(
        function () { /* omitted long function */ }
    )
]
  • 修改 optimization
// 用法(v5版本可用):
config.optimization
  .minimizer(name)
  .tap(args => newArgs)

// 示例:
config.optimization
  .minimizer('css')
  .tap(args => [...args, { cssProcessorOptions: { safe: false } }])

四、查

  • 使用 .toConfig() 输出配置
// 示例1:
console.log('js config :>> ', config.module.rule('js').toConfig())
js config :>>  
{
  test: /.m?jsx?$/,
  exclude: [ [Function] ],
  use: [
    { loader: 'cache-loader', options: [Object] },
    { loader: 'babel-loader' }
  ]
}

// ***************************

// 示例2:
console.log('cache-loader config :>> ', config.module.rule('js').use('cache-loader').toConfig())
cache-loader config :>>  
{
  loader: 'cache-loader',
  options: {
    cacheDirectory: 'D:\webproject\myproject\node_modules\.cache\babel-loader',
    cacheIdentifier: '20a97f42'
  }
}

// ***************************

// 示例3:
console.log('plugin config :>> ', config.plugin('optimize-css').toConfig())
plugin config :>>  OptimizeCssnanoPlugin {
  options: { sourceMap: false, cssnanoOptions: { preset: [Array] } }
}

五、操作方法

chainWebpack 中,有两个大的数据分类:ChainedMap 和 ChainedSet

在操作的时候分别有如下方法可以链式调用:

  • ChainedMap:
// 从 Map 移除所有 配置.
clear()

// 通过键值从 Map 移除单个配置.
// key: *
delete(key)

// 获取 Map 中相应键的值
// key: *
// returns: value
get(key)

// 获取 Map 中相应键的值
// 如果键在Map中不存在,则ChainedMap中该键的值会被配置为fn的返回值.
// key: *
// fn: Function () -> value
// returns: value
getOrCompute(key, fn)

// 配置Map中 已存在的键的值
// key: *
// value: *
set(key, value)

// Map中是否存在一个配置值的特定键,返回 真或假
// key: *
// returns: Boolean
has(key)

// 返回 Map中已存储的所有值的数组
// returns: Array
values()

// 返回Map中全部配置的一个对象, 其中 键是这个对象属性,值是相应键的值,
// 如果Map是空,返回 `undefined`
// 使用 `.before() 或 .after()` 的ChainedMap, 则将按照属性名进行排序。
// returns: Object, undefined if empty
entries()

//  提供一个对象,这个对象的属性和值将 映射进 Map。
// 你也可以提供一个数组作为第二个参数以便忽略合并的属性名称。
// obj: Object
// omit: Optional Array
merge(obj, omit)

// 对当前配置上下文执行函数。
// handler: Function -> ChainedMap
  // 一个把ChainedMap实例作为单个参数的函数
batch(handler)

// 条件执行一个函数去继续配置
// condition: Boolean
// whenTruthy: Function -> ChainedMap
  // 当条件为真,调用把ChainedMap实例作为单一参数传入的函数
// whenFalsy: Optional Function -> ChainedMap
  // 当条件为假,调用把ChainedMap实例作为单一参数传入的函数
when(condition, whenTruthy, whenFalsy)
  • ChainedSet:
// 添加/追加 给Set末尾位置一个值.
// value: *
add(value)

// 添加 给Set开始位置一个值.
// value: *
prepend(value)

// 移除Set中全部值.
clear()

// 移除Set中一个指定的值.
// value: *
delete(value)

// 检测Set中是否存在一个值.
// value: *
// returns: Boolean
has(value)

// 返回Set中值的数组.
// returns: Array
values()

// 连接给定的数组到 Set 尾部。
// arr: Array
merge(arr)

// 对当前配置上下文执行函数。
// handler: Function -> ChainedSet
  // 一个把 ChainedSet 实例作为单个参数的函数
batch(handler)

// 条件执行一个函数去继续配置
// condition: Boolean
// whenTruthy: Function -> ChainedSet
  // 当条件为真,调用把 ChainedSet 实例作为单一参数传入的函数
// whenFalsy: Optional Function -> ChainedSet
  // 当条件为假,调用把 ChainedSet 实例作为单一参数传入的函数
when(condition, whenTruthy, whenFalsy)

转载于:https://zhuanlan.zhihu.com/p/555670597 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: vue-cli3 vue.config.js 文件用于配置项目的 webpack 构建环境。可以在该文件进行如下配置: - 修改 webpack 的配置项 - 配置 devServer - 配置代理 - 使用插件 示例: ``` module.exports = { devServer: { port: 8080, proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } } }, configureWebpack: { plugins: [ new MyAwesomeWebpackPlugin() ] } } ``` 其,configureWebpack 配置项可以修改 webpack 的配置项,devServer 配置项可以配置开发服务器的相关选项,proxy 配置项可以配置代理。 注意:vue.config.js 文件不是必须的,如果项目没有该文件,则使用默认配置。 ### 回答2: Vue CLI 3是Vue.js的一个脚手架工具,用于快速构建Vue项目。vue.config.js是一个配置文件,它在项目构建过程被调用,用于配置WebpackVue CLI的一些选项。 vue.config.js配置文件可以设置很多选项,包括开发时代理、打包时的压缩和代码分割等等。下面是一些常用的选项: 1. publicPath publicPath是一个字符串,用于指定打包后的静态资源的路径。可以是相对路径或绝对路径,它的值会被Webpack在生成代码时加入到各个静态资源引用的URL。 2. outputDir outputDir是一个字符串,用于指定打包后的输出目录。默认值是"dist"。 3. devServer devServer是一个对象,用于配置开发服务器。其包括代理、端口号和自动打开浏览器等选项。可以用它来配置前后端联调、Mock服务等。 4. chainWebpack chainWebpack是一个函数,用于修改Webpack的配置。可以在其添加、删除、修改各种Webpack配置项。举个例子,我们可以通过chainWebpack来关闭ESLint验证: ``` chainWebpack: config => { config.module .rule('eslint') .use('eslint-loader') .tap(options => { options.emitWarning = false return options }) } ``` 5. configureWebpack configureWebpack是一个对象或函数,用于向Webpack配置添加内容。其包括Entry和Output等选项。 6. optimization optimization是一个对象,用于配置打包时的优化选项,比如代码压缩等。 7. css css是一个对象,用于配置CSS的选项。其包括分离CSS、压缩CSS、CSS的sourceMap等。 8. pluginOptions pluginOptions是一个对象,用于配置Vue CLI插件的选项。其包括ESLint、Stylelint、PWA等。我们可以通过它来关闭ESLint验证: ``` pluginOptions: { eslint: { enable: false } } ``` 除了上面提到的常用选项,vue.config.js还有很多其他配置项可供选择,具体可参考Vue CLI的官方文档。总的来说,vue.config.js是一个非常强大的工具,可以大大提高开发效率和优化打包结果。 ### 回答3: Vue.js是目前非常流行的前端框架之一,它的灵活性和易用性受到了广大开发者的欢迎。其最新的版本Vue-cli3,提供了更加方便快捷的开发模式,同时其强大的配置功能也是特别值得注意的。Vue-cli3vue.config.js文件包含着许多重要的配置选项,下面我们来逐一介绍一下。 1. publicPath publicPath选项可以指定发布路径,通过配置publicPath选项,可以将Vue应用的资源文件发布到指定的位置,这样就方便我们在多个环境部署Vue应用。例如,如果希望将Vue应用文件发布到“/my-app/”目录下,配置publicPath选项为“/my-app/”即可。 2. outputDir outputDir选项用于指定Vue应用的输出目录,通过配置outputDir选项,可以将Vue应用打包生成的文件输出到指定的目录下面。例如,如果希望将生成的文件输出到“/dist/”目录下,那么可以在vue.config.js文件配置outputDir选项为“dist”。 3. devServer devServer选项用于配置开发服务器,对于Vue应用的开发来说,它非常重要。通过配置devServer选项,可以定制开发服务器的端口、代理等信息,使我们在开发Vue应用时能够更加方便地进行调试和测试。 4. lintOnSave lintOnSave选项用于在保存代码时自动检查语法错误和格式错误,让我们在开发过程能够更加精细地把控代码质量。通过配置该选项,可以将Vue应用的代码自动规范,并保持统一的风格。 5. chainWebpack chainWebpack选项用于定制Webpack的配置,它可以让我们更加灵活地定制Vue应用的构建过程。通过配置该选项,可以添加自定义的Webpack插件,优化打包生成的文件等。 总之,Vue-cli3vue.config.js文件不仅提供了强大的配置功能,而且能够让我们更加方便地开发和部署Vue应用。掌握这些配置选项,能够让我们更加高效地进行Vue应用的开发和维护工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值