webpack-chain

7 4月

webpack-chain提供链式API用于创建和修改webpack配置。

  • ChainedMap,ChainedSet
  • config
  • entry
  • output
  • resolve
  • optimization
  • plugin
  • devServer
  • module
  • node,performance
  • merge
  • 反射 toString

ChainedMap,ChainedSet

核心就是ChainedMap,ChainedSet,类似JS里的map,set,提供了很多便利的API,看名字就知道是干啥的。其中when用于条件设置

// ChainedMap的API
has(key)
get(key)
getOrCompute(key, fn)    // 如果key没找到,就用fn的返回值 fn: () => value
set(key, value)
delete(key)
clear()
values()
entries()
merge(obj, omit)
batch(handler)
when(condition, whenTruthy, whenFalsy)  // whenTruthy和whenFalsy的参数是当前config实例对象

// ChainedSet的API
has(value)
add(value)        // 加在末尾
prepend(value)    // 加在开头
delete(value)
clear()
values()
merge(arr)
batch(handler)
when(condition, whenTruthy, whenFalsy)  // whenTruthy和whenFalsy的参数是当前config实例对象

// when 例子
config
  .when(process.env.NODE_ENV === 'production', config => {
    config
      .plugin('minify')
      .use(BabiliWebpackPlugin);
  });

config
  .when(process.env.NODE_ENV === 'production',
    config => config.plugin('minify').use(BabiliWebpackPlugin),
    config => config.devtool('source-map')
  );

config

操作webpack-chain需要一个config,提供了很多和webpack相关的API。

const Config = require('webpack-chain');

const config = new Config();

config
  .amd(amd)
  .bail(bail)
  .cache(cache)
  .devtool(devtool)
  .context(context)
  .externals(externals)
  .loader(loader)
  .name(name)
  .mode(mode)
  .parallelism(parallelism)
  .profile(profile)
  .recordsPath(recordsPath)
  .recordsInputPath(recordsInputPath)
  .recordsOutputPath(recordsOutputPath)
  .stats(stats)
  .target(target)
  .watch(watch)
  .watchOptions(watchOptions)

entry

config.entry(name)是个ChainedSet:

config
  .entry(name)
    .add(value)
    .add(value)

config
  .entry(name)
    .clear()

output

config.output是个ChainedMap:

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)

resolve

config.resolve和config.resolve.alias是个ChainedMap。其他都是ChainedSet:modules,aliasFields,descriptionFields,extensions,mainFields,mainFiles

config.resolve
  .cachePredicate(cachePredicate)
  .cacheWithContext(cacheWithContext)
  .enforceExtension(enforceExtension)
  .enforceModuleExtension(enforceModuleExtension)
  .unsafeCache(unsafeCache)
  .symlinks(symlinks)

config.resolve.alias
  .set(key, value)
  .set(key, value)
  .delete(key)
  .clear()

config.resolve.modules
  .add(value)
  .prepend(value)
  .clear()

config.resolve.aliasFields
  .add(value)
  .prepend(value)
  .clear()

config.resolve.descriptionFields
  .add(value)
  .prepend(value)
  .clear()

config.resolve.extensions
  .add(value)
  .prepend(value)
  .clear()

config.resolve.mainFields
  .add(value)
  .prepend(value)
  .clear()

config.resolve.mainFiles
  .add(value)
  .prepend(value)
  .clear()

config.resolveLoader是在config.resolve基础上增加了:moduleExtensions,packageMains

config.resolveLoader.moduleExtensions
  .add(value)
  .prepend(value)
  .clear()

config.resolveLoader.packageMains
  .add(value)
  .prepend(value)
  .clear()

optimization

config.optimization是个ChainedMap:

config.optimization
  .concatenateModules(concatenateModules)
  .flagIncludedChunks(flagIncludedChunks)
  .mergeDuplicateChunks(mergeDuplicateChunks)
  .minimize(minimize)
  .namedChunks(namedChunks)
  .namedModules(namedModules)
  .nodeEnv(nodeEnv)
  .noEmitOnErrors(noEmitOnErrors)
  .occurrenceOrder(occurrenceOrder)
  .portableRecords(portableRecords)
  .providedExports(providedExports)
  .removeAvailableModules(removeAvailableModules)
  .removeEmptyChunks(removeEmptyChunks)
  .runtimeChunk(runtimeChunk)
  .sideEffects(sideEffects)
  .splitChunks(splitChunks)
  .usedExports(usedExports)

config.optimization
  .minimizer(name)
  .use(WebpackPlugin, args)

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

config.optimization
  .minimizer('css')
  .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safe: true } }])

config.optimization
  .minimizer(name)
  .tap(args => newArgs)

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

config.optimization
  .minimizer(name)
  .init((Plugin, args) => new Plugin(...args));

config.optimization.minimizers.delete(name)

plugin

config.plugin是个ChainedMap。可以用.before() 和 .after()进行排序:

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

// 例子
config
  .plugin('hot')
  .use(webpack.HotModuleReplacementPlugin);

config
  .plugin('env')
  .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);

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

// 例子
config
  .plugin('env')
  .tap(args => [...args, 'SECRET_KEY']);

config
  .plugin(name)
  .init((Plugin, args) => new Plugin(...args));

config.plugins.delete(name)

config
  .plugin(name)
    .before(otherName)

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

config
  .plugin(name)
    .after(otherName)

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

devServer

config.devServer是个ChainedMap:

config.devServer.allowedHosts
  .add(value)
  .prepend(value)
  .clear()

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)

module

config.module是个ChainedMap:

config.module
  .noParse(noParse)

config.module
  .rule(name)
    .test(test)
    .pre()
    .post()
    .enforce(preOrPost)

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

// 例子
config.module
  .rule('compile')
    .use('babel')
      .loader('babel-loader')
      .options({ presets: ['@babel/preset-env'] });

config.module
  .rule(name)
    .use(name)
      .tap(options => newOptions)

// 例子
config.module
  .rule('compile')
    .use('babel')
      .tap(options => merge(options, {
        plugins: ['@babel/plugin-proposal-class-properties']
      }));

config.module
  .rule(name)
    .oneOf(name)

// 例子
config.module
  .rule('css')
    .oneOf('inline')
      .resourceQuery(/inline/)
      .use('url')
        .loader('url-loader')
        .end()
      .end()
    .oneOf('external')
      .resourceQuery(/external/)
      .use('file')
        .loader('file-loader')

config.module
  .rule(name)
    .oneOf(name)
      .before()

// 例子
config.module
  .rule('scss')
    .test(/\.scss$/)
    .oneOf('normal')
      .use('sass')
        .loader('sass-loader')
        .end()
      .end()
    .oneOf('sass-vars')
      .before('normal')
      .resourceQuery(/\?sassvars/)
      .use('sass-vars')
        .loader('sass-vars-to-js-loader')

config.module
  .rule(name)
    .oneOf(name)
      .after()

// 例子
config.module
  .rule('scss')
    .test(/\.scss$/)
    .oneOf('vue')
      .resourceQuery(/\?vue/)
      .use('vue-style')
        .loader('vue-style-loader')
        .end()
      .end()
    .oneOf('normal')
      .use('sass')
        .loader('sass-loader')
        .end()
      .end()
    .oneOf('sass-vars')
      .after('vue')
      .resourceQuery(/\?sassvars/)
      .use('sass-vars')
        .loader('sass-vars-to-js-loader')

node,performance

config.node / performance是个ChainedMap:

config.node
  .set('__dirname', 'mock')
  .set('__filename', 'mock');

config.performance
  .hints(hints)
  .maxEntrypointSize(maxEntrypointSize)
  .maxAssetSize(maxAssetSize)
  .assetFilter(assetFilter)

merge

config.merge允许你将一个对象,直接merge进webpack配置中

config.merge({ devtool: 'source-map' });
config.get('devtool')     // "source-map"

反射 toString

将config解析成一个真实的webpack配置对象:

config.toString();

发表评论

电子邮件地址不会被公开。 必填项已用*标注