读 VuePress(二):使用 Webpack-chain 链式生成 webpack 配置

栏目: CSS · 发布时间: 5年前

内容简介:vuepress 有三套 webpack 配置:基础配置、dev 配置、build 配置,看似和普通的一个前端项目也没什么差别,但它使用 webpack-chain 生成配置而不是传统的写死配置。相关源码见引入 webpack-chain 后,我们所有的 webpack 配置通过一个链式包装器便可生成了:

vuepress 有三套 webpack 配置:基础配置、dev 配置、build 配置,看似和普通的一个前端项目也没什么差别,但它使用 webpack-chain 生成配置而不是传统的写死配置。

相关源码见 createBaseConfig.jscreateClientConfigcreateServerConfig

webpack-chain 简介

链式包装器

引入 webpack-chain 后,我们所有的 webpack 配置通过一个链式包装器便可生成了:

const Config = require('webpack-chain');
const config = new Config();
// 链式生成配置
...
// 导出 webpack 配置对象
export default config.toConfig();
复制代码

在引入详细的示例之前,先让我们介绍一下 webpack-chain 中内置的两种数据结构:ChainMap、ChainSet。

ChainedSet

带链式方法的集合。

很显然,它和 ES6 的Set 类似,都拥有键值对,但值得一提的是:它通过链式方法来操作。

在 webpack-chain 中,属于 ChainedSet 的有 config.entry(name)config.resolve.modules 等。

假如我们需要指定 webpack 配置的 enrty,我们只需要这样做:

config
  .entry('app')
    .add('src/index.js')
复制代码

它等价于 webpack 配置对象的这部分:

entry: {
  app: './src/index.js'
}
复制代码

当然,我想强调的 ChainedSet 真正强大的地方,在于 ChainedSet 提供的内置方法:add(value)、delete(value)、has(value) 等。

这可以帮助我们增删改查整个 webpack 配置中的任意一个部分。

ChainedMap

带链式方法的哈希表。

同上,它和 ES6 的Map 类似,也通过链式方法来操作。

在 webpack-chain 中,属于 ChainedMap 的有 configconfig.resolve 等。

想了解更多 API 用法的读者可以前往文档。

webpack-chain 原理简介

我们打开源码目录:

读 VuePress(二):使用 Webpack-chain 链式生成 webpack 配置

一共有三种类:Chainable、ChainedSet 或 ChainedMap、其它。

链式调用

Chainable 实现了链式调用的功能,它的代码很简洁:

module.exports = class {
  constructor(parent) {
    this.parent = parent;
  }

  batch(handler) {
    handler(this);
    return this;
  }

  end() {
    return this.parent;
  }
};
复制代码

最常调用的 end 方法便是来源于这了,它会返回调用链中最前端的那个对象。

比如说,我们在 vuepress 中有这样一段代码:

config
    .use('cache-loader')
    .loader('cache-loader')
    .options({
      cacheDirectory,
      cacheIdentifier
    })
    .end()
    .use('babel-loader')
      .loader('babel-loader')
      .options({
        // do not pick local project babel config
        babelrc: false,
        presets: [
          require.resolve('@vue/babel-preset-app')
        ]
      })
复制代码

第八行结尾 end() 处返回的便又是 config 了。

ChainedSet 和 ChainedMap 都继承于 Chainable,其他类大多都继承于 ChainedSet 或 ChainedMap,除了 Use 和 Plugin 类使用 Orderable 这个高阶函数包装了一下(相当于装饰器),目的在于解决在使用 module.use 或 plugin 时调整顺序的问题。有兴趣的读者可以自行翻阅 源码 ~

在 Vuepress 中的应用

分成三个配置我们就不赘述了,毕竟大家平常开发的项目中也可能这样做。在这里我需要特别提一下的地方便是 编写函数生成 webpack 配置

举个例子,在 createBaseConfig 里,有一个这样的函数:

function createCSSRule (lang, test, loader, options) {
  const baseRule = config.module.rule(lang).test(test)
  const modulesRule = baseRule.oneOf('modules').resourceQuery(/module/)
  const normalRule = baseRule.oneOf('normal')

  applyLoaders(modulesRule, true)
  applyLoaders(normalRule, false)

  function applyLoaders (rule, modules) {
    if (!isServer) {
      if (isProd) {
        rule.use('extract-css-loader').loader(CSSExtractPlugin.loader)
      } else {
        rule.use('vue-style-loader').loader('vue-style-loader')
      }
    }

    rule.use('css-loader')
      .loader(isServer ? 'css-loader/locals' : 'css-loader')
      .options({
        modules,
        localIdentName: `[local]_[hash:base64:8]`,
        importLoaders: 1,
        sourceMap: !isProd
      })

    rule.use('postcss-loader').loader('postcss-loader').options(Object.assign({
      plugins: [require('autoprefixer')],
      sourceMap: !isProd
    }, siteConfig.postcss))

    if (loader) {
      rule.use(loader).loader(loader).options(options)
    }
  }
}
复制代码

它做了这样一件事:对特定的一种样式语言进行 css 模块化和非模块化的处理,顺序是 loader -> postcss-loader -> css-loader -> vue-style-loader 或 extract-css-loader。 使用方式是这样的:

createCSSRule('css', /\.css$/)
createCSSRule('postcss', /\.p(ost)?css$/)
createCSSRule('scss', /\.scss$/, 'sass-loader', siteConfig.scss)
createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign({ indentedSyntax: true }, siteConfig.sass))
createCSSRule('less', /\.less$/, 'less-loader', siteConfig.less)
createCSSRule('stylus', /\.styl(us)?$/, 'stylus-loader', Object.assign({
  preferPathResolver: 'webpack'
}, siteConfig.stylus))
复制代码

是不是一下减少了配置的编写量?而且还很灵活的支持用户自定义 options 和后期的代码变更。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Alone Together

Alone Together

Sherry Turkle / Basic Books / 2011-1-11 / USD 28.95

Consider Facebookit’s human contact, only easier to engage with and easier to avoid. Developing technology promises closeness. Sometimes it delivers, but much of our modern life leaves us less connect......一起来看看 《Alone Together》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具