Читайте Vuepress (II): WebPack-цепь, используя конфигурацию цепи, созданный веб-запас

внешний интерфейс Vue.js CSS Webpack

предисловие

Vuepress имеет три набора конфигурации веб-пакета: базовая конфигурация, конфигурация разработки, конфигурация сборки, которая, кажется, ничем не отличается от обычного внешнего проекта, но использует цепочку веб-пакетов для генерации конфигурации вместо традиционной жестко запрограммированной конфигурации.

См. связанный исходный кодcreateBaseConfig.js,createClientConfig,createServerConfig.

Введение в цепочку webpack

обертка цепи

После введения webpack-chain вся наша конфигурация webpack может быть сгенерирована через обёртку цепочки:

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

Прежде чем представить подробные примеры, давайте представим две структуры данных, встроенные в цепочку webpack: ChainMap и ChainSet.

ChainedSet

Коллекция со связанными методами.

Очевидно, это то же самое, что и ES6.SetТочно так же у обоих есть пары ключ-значение, но стоит упомянуть, что он работает через цепные методы.

В цепочке webpack принадлежащие ChainedSet:config.entry(name),config.resolve.modulesЖдать.

Если нам нужно указать вход в конфигурацию веб-пакета, нам просто нужно сделать это:

config
  .entry('app')
    .add('src/index.js')

Это эквивалентно этой части объекта конфигурации webpack:

entry: {
  app: './src/index.js'
}

Конечно, реальная сила ChainedSet, которую я хочу подчеркнуть, заключается во встроенных методах, предоставляемых ChainedSet: add(value), delete(value), has(value) и т. д.

Это может помочь нам CRUD проверить любую часть всей конфигурации веб-пакета.

ChainedMap

Хеш-таблица со связанными методами.

То же самое, это то же самое, что и ES6.MapТочно так же он также работает с помощью цепных методов.

В цепочке webpack принадлежащие ChainedMap:config,config.resolveЖдать.

Читатели, которые хотят узнать больше об использовании API, могут перейти наДокументация.

Знакомство с принципом работы webpack-chain

Открываем исходный каталог:

webpack-chain 源码目录

Есть три типа: Chainable, ChainedSet или ChainedMap, другие.

цепной вызов

Chainable реализует функцию вызова цепочки, и ее код очень лаконичен:

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

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

  end() {
    return this.parent;
  }
};

Отсюда происходит наиболее часто вызываемый конечный метод, который возвращает объект на переднем конце цепочки вызовов.

Например, у нас есть этот фрагмент кода в 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 или плагин Проблема корректировки порядка. Заинтересованные читатели могут прочитать самостоятельноисходный код~

Приложение в 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 для определенного языка стилей в следующем порядке: загрузчик -> postcss-загрузчик -> css-загрузчик -> 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))

Уменьшает ли это объем написания конфигурации? Он также гибко поддерживает определяемые пользователем параметры и более поздние изменения кода.

Эпилог

Когда следует использовать webpack-chain? Ведь его внедрение удорожает проект, мой ответ таков:

  1. Когда конфигурацию веб-пакета проекта необходимо сгенерировать в соответствии с некоторой логикой, рекомендуется ввести webpack-chain для декларативного написания конфигурации веб-пакета.
  2. Если конфигурация веб-пакета проста или вы просто пишете объект напрямую, не рекомендуется вводить цепочку веб-пакетов, Если есть несколько конфигураций, которые необходимо объединить, вы можете ввести веб-слияние.