前端工程化:webpack-chain

webpack-chain是什麼?經過鏈式的方式修改webpack的配置css

列出一些本人經常使用的使用webpack-chain的方式修改webpack配置. 整個文件爲:html

//vue.config.js
module.exports={
  chainWebpack:(webpackConfig)=>{

  }
}
複製代碼

一、修改entry和output

chainWebpack: config => {
  config.entryPoints.clear() // 會把默認的入口清空
  config.entry('main').add('./src/main.js')//新增入口
  config.entry('routes').add('./src/app-routes.js')//新增入口


   config.output
        .path("dist")
        .filename("[name].[chunkhash].js")
        .chunkFilename("chunks/[name].[chunkhash].js")
        .libraryTarget("umd")
        .library();
}

// 其他的output配置
config.output
  .auxiliaryComment(auxiliaryComment)
  .chunkFilename(chunkFilename)
  .chunkLoadTimeout(chunkLoadTimeout)
  .crossOriginLoading(crossOriginLoading)
  .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate)
  .devtoolLineToLine(devtoolLineToLine)
  .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate)
  .filename(filename)
  .hashFunction(hashFunction)
  .hashDigest(hashDigest)
  .hashDigestLength(hashDigestLength)
  .hashSalt(hashSalt)
  .hotUpdateChunkFilename(hotUpdateChunkFilename)
  .hotUpdateFunction(hotUpdateFunction)
  .hotUpdateMainFilename(hotUpdateMainFilename)
  .jsonpFunction(jsonpFunction)
  .library(library)
  .libraryExport(libraryExport)
  .libraryTarget(libraryTarget)
  .path(path)
  .pathinfo(pathinfo)
  .publicPath(publicPath)
  .sourceMapFilename(sourceMapFilename)
  .sourcePrefix(sourcePrefix)
  .strictModuleExceptionHandling(strictModuleExceptionHandling)
  .umdNamedDefine(umdNamedDefine)

複製代碼

二、設置別名alias

const path = require('path');
function resolve (dir{
    return path.join(__dirname, dir)
}
module.exports = {
    lintOnSavetrue,
    chainWebpack(config)=>{
        config.resolve.alias
            .set('@$', resolve('src'))
            .set('assets',resolve('src/assets'))
            .set('components',resolve('src/components'))
            .set('layout',resolve('src/layout'))
            .set('base',resolve('src/base'))
            .set('static',resolve('src/static'))
            .delete('base'// 刪掉指定的別名
            // .clear()  會把全部別名都刪掉
    }
}

複製代碼

三、修改代理proxy

devServe的配置,請見這裏前端

  chainWebpack: config => {
    config.devServer.port(8888)
      .open(true)
      .proxy({'/dev': {
                 target'http://123.57.153.106:8080/',
                 changeOrigintrue,
                 pathRewrite: {
                   '^/dev'''
                 }
               }
           })
  }
// chain其餘隊proxy的配置
config.devServer
  .bonjour(bonjour)
  .clientLogLevel(clientLogLevel)
  .color(color)
  .compress(compress)
  .contentBase(contentBase)
  .disableHostCheck(disableHostCheck)
  .filename(filename)
  .headers(headers)
  .historyApiFallback(historyApiFallback)
  .host(host)
  .hot(hot)
  .hotOnly(hotOnly)
  .https(https)
  .inline(inline)
  .info(info)
  .lazy(lazy)
  .noInfo(noInfo)
  .open(open)
  .openPage(openPage)
  .overlay(overlay)
  .pfx(pfx)
  .pfxPassphrase(pfxPassphrase)
  .port(port)
  .progress(progress)
  .proxy(proxy)
  .public(public)
  .publicPath(publicPath)
  .quiet(quiet)
  .setup(setup)
  .socket(socket)
  .staticOptions(staticOptions)
  .stats(stats)
  .stdin(stdin)
  .useLocalIp(useLocalIp)
  .watchContentBase(watchContentBase)
  .watchOptions(watchOptions)

複製代碼

四、添加插件及修改插件參數

插件相關配置請見這裏vue

添加插件node

// 添加API
config
  .plugin(name)
  .use(WebpackPlugin, args)

// 一個例子
const fileManager = require("filemanager-webpack-plugin");
...
//注意:use部分,不能使用new的方式建立插件實例
webpackConfig.plugin("zip").use(fileManager, [
    {
      onEnd: {
        archive: [
          {
            source"dist",
            destination: zipName
          }
        ]
      }
    }
  ]);

複製代碼

修改插件參數react

// 可使用tap方式,修改插件參數
config
  .plugin(name)
  .tap(args => newArgs)

// 一個例子
config
  .plugin('env')
  //使用tag修改參數
  .tap(args => [...args, 'SECRET_KEY']);
複製代碼

五、修改插件初始化及移除插件

修改插件初始化webpack

config
  .plugin(name)
  .init((Plugin, args) => new Plugin(...args));
複製代碼

移除插件git

 chainWebpack: config => {
  config.plugins.delete('prefetch')
  // 移除 preload 插件
  config.plugins.delete('preload');
 }
複製代碼

六、在xx插件前調用/在xx插件以後調用

有時候須要xx插件在aa插件以前調用。github

config
  .plugin(name)
    .before(otherName)

// 一個例子:ScriptExtWebpackPlugin插件在HtmlWebpackTemplate插件前調用

config
  .plugin('html-template')
    .use(HtmlWebpackTemplate)
    .end()
  .plugin('script-ext')
    .use(ScriptExtWebpackPlugin)
    .before('html-template');

複製代碼

有時候須要xx插件在aa插件以後調用。web

config
  .plugin(name)
    .after(otherName)

// 一個例子html-template在script-ext以後調用

config
  .plugin('html-template')
    .after('script-ext')
    .use(HtmlWebpackTemplate)
    .end()
  .plugin('script-ext')
    .use(ScriptExtWebpackPlugin);

複製代碼

七、performance 性能

配置請見webpack參數:performance

config.performance
  .hints(hints)//false | "error" | "warning"。打開/關閉提示
  .maxEntrypointSize(maxEntrypointSize)//入口起點表示針對指定的入口,對於全部資源,要充分利用初始加載時(initial load time)期間。此選項根據入口起點的最大致積,控制 webpack 什麼時候生成性能提示。默認值是:250000
  .maxAssetSize(maxAssetSize)//資源(asset)是從 webpack 生成的任何文件。此選項根據單個資源體積,控制 webpack 什麼時候生成性能提示。默認值是:250000
  .assetFilter(assetFilter)//此屬性容許 webpack 控制用於計算性能提示的文件

複製代碼

八、代碼分割及性能優化 optimizations

config.optimization
  .concatenateModules(concatenateModules)
  .flagIncludedChunks(flagIncludedChunks)
  .mergeDuplicateChunks(mergeDuplicateChunks)
  .minimize(minimize) //boolean,默認爲true,是否開啓壓縮
  .namedChunks(namedChunks)
  .namedModules(namedModules)
  .nodeEnv(nodeEnv)
  .noEmitOnErrors(noEmitOnErrors)
  .occurrenceOrder(occurrenceOrder)
  .portableRecords(portableRecords)
  .providedExports(providedExports)
  .removeAvailableModules(removeAvailableModules)
  .removeEmptyChunks(removeEmptyChunks)
  .runtimeChunk(runtimeChunk)
  .sideEffects(sideEffects)
  .splitChunks(splitChunks)//object:代碼分割。默認狀況下,webpack v4 +爲動態導入的模塊提供了開箱即用的新通用塊策略。
  .usedExports(usedExports)

//舉個例子

config.optimization.splitChunks({
     chunks"async"// 必須三選一: "initial" | "all"(推薦) | "async" (默認就是async)
     minSize: 30000// 最小尺寸,30000
     minChunks: 1// 最小 chunk ,默認1
     maxAsyncRequests: 5// 最大異步請求數, 默認5
     maxInitialRequests : 3// 最大初始化請求書,默認3
     automaticNameDelimiter: '~',// 打包分隔符
     name: function(){}, // 打包後的名稱,此選項可接收 function
     cacheGroups:{ // 這裏開始設置緩存的 chunks
         priority: 0// 緩存組優先級
         vendor: { // key 爲entry中定義的 入口名稱
             chunks: "initial"// 必須三選一: "initial" | "all" | "async"(默認就是async) 
             test: /react|lodash/// 正則規則驗證,若是符合就提取 chunk
             name: "vendor"// 要緩存的 分隔出來的 chunk 名稱 
             minSize: 30000,
             minChunks1,
             enforcetrue,
             maxAsyncRequests5// 最大異步請求數, 默認1
             maxInitialRequests : 3// 最大初始化請求書,默認1
             reuseExistingChunk: true // 可設置是否重用該chunk
         }
     }
});


複製代碼

九、自定義代碼壓縮工具

webpack4.x默認使用的TerserPlugin作代碼壓縮。

//使用
config.optimization.minimizer.use(WebpackPlugin,args);
//刪除
config.optimization.minimizers.delete(name)



// 一個例子

config.optimization
  .minimizer('css')
  .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safetrue } }])

// Minimizer plugins can also be specified by their path, allowing the expensive require()s to be
// skipped in cases where the plugin or webpack configuration won't end up being used.
config.optimization
  .minimizer('css')
  .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safetrue } }])

//是要tap修改插件參數
config.optimization
  .minimizer('css')
  .tap(args => [...args, { cssProcessorOptions: { safefalse } }])
複製代碼

十、添加一個新的 Loader

首先請先了解一下webpack如何配置loader. 官網連接

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

// 一個例子

 config.module
      .rule('graphql')
      .test(/\.graphql$/)
      .use('graphql-tag/loader')
        .loader('graphql-tag/loader')
        .end()
// 若是是非webpack-chain的話
module:{
  rules:[
    {
      test:/\.graphql$/,
      use::[
        {
          loader:"graphql-tag/loader"
        }
      ]
    }
  ]
}
複製代碼

十一、 修改Loader

// vue.config.js
module.exports = {
  chainWebpackconfig => {
    config.module
      .rule('vue')
      .use('vue-loader')
        .loader('vue-loader')
        .tap(options => {
          // 修改它的選項...
          return options
        })
  }
}
複製代碼

注意 對於 CSS 相關 loader 來講,咱們推薦使用 css.loaderOptions 而不是直接鏈式指定 loader。這是由於每種 CSS 文件類型都有多個規則,而 css.loaderOptions 能夠確保你經過一個地方影響全部的規則。

十二、 替換一個規則裏的 Loader

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

    // 清除已有的全部 loader。
    // 若是你不這樣作,接下來的 loader 會附加在該規則現有的 loader 以後。
    svgRule.uses.clear()

    // 添加要替換的 loader
    svgRule
      .use('vue-svg-loader')
        .loader('vue-svg-loader')
  }
}
複製代碼

1三、使用when作條件配置

consif.when(condition,truthyFunc,falsyFunc)

// 一個例子,當構建生產包時添加minify插件,不然設置構建類型爲source-map
// devtool請見:https://www.webpackjs.com/configuration/devtool/
config
  .when(process.env.NODE_ENV === 'production',
    config => config.plugin('minify').use(BabiliWebpackPlugin),
    config => config.devtool('source-map')
  );

複製代碼

1四、使用toString()查看chain對應的webpack配置

注意 使用toString()生成的數據,不能直接在webpack上使用。

config
  .module
    .rule('compile')
      .test(/\.js$/)
      .use('babel')
        .loader('babel-loader');

config.toString();

/*
{
  module: {
    rules: [
      /* config.module.rule('compile') */

      {
        test/\.js$/,
        use: [
          /* config.module.rule('compile').use('babel') */
          {
            loader'babel-loader'
          }
        ]
      }
    ]
  }
}
*/
複製代碼

參考

歡迎關注個人公衆號,天天定時推送前端相關知識

相關文章
相關標籤/搜索