zoukankan      html  css  js  c++  java
  • 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 中,有两个大的数据分类:ChainedMapChainedSet

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

    • 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)
    

    更多配置操作,参考中文文档
    chainWebpack 中文文档

    都读到最后了、留下个建议如何
  • 相关阅读:
    AC自动机 HDOJ 2222 Keywords Search
    AC自动机 HDOJ 5384 Danganronpa
    贪心 HDOJ 5385 The Path
    区间DP UVA 10739 String to Palindrome
    区间DP UVA 10453 Make Palindrome
    素数专题
    判素数+找规律 BestCoder Round #51 (div.2) 1001 Zball in Tina Town
    DP专题
    贪心+模拟 ZOJ 3829 Known Notation
    概率DP ZOJ 3822 Domination
  • 原文地址:https://www.cnblogs.com/linjunfu/p/14520345.html
Copyright © 2011-2022 走看看