Практическое руководство по веб-пакету SplitChunksPlugin

внешний интерфейс Webpack
Практическое руководство по веб-пакету SplitChunksPlugin

Когда речь заходит об интерфейсных пакетных инструментах, первое, что приходит на ум, — это webpack. Но фронтенд развивается очень быстро, и время от времени появляются новинки, а еще раньше инструмента для упаковки появились посылки и роллапы. Столкновение различных инструментов извлекает преимущества друг из друга и способствует развитию техники.

Функция нулевой конфигурации поддерживается в webpack4, а также оптимизирована блочная упаковка.CommonsChunkPluginбыл удален и теперь используетсяoptimization.splitChunksзаменять.

Давайте начнем знакомить с содержимым splitChunks.

По умолчанию

Во-первых, webpack автоматически разделит блок кода в соответствии со следующими условиями:

  • Новые блоки кода могут быть общими ссылками, или эти модули могут поступать из папки node_modules.
  • Новый блок кода больше 30 КБ (объем до min+gzip)
  • Блоки кода загружаются по запросу, максимальное количество параллельных запросов должно быть меньше или равно 6
  • Первоначально загружаемый блок кода, максимальное количество параллельных запросов должно быть меньше или равно 4

По умолчанию упаковка блоков влияет только на загрузку модулей по запросу, поскольку оптимизация упаковки начального блока повлияет на количество тегов script в HTML, увеличивая количество запросов.

Давайте рассмотрим несколько примеров, чтобы понять упаковку по умолчанию.

Все модули импортируются синхронно

// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
  <div>SplitChunk</div>,
  document.getElementById('root')
)

Значение по умолчанию влияет только на модули, которые загружаются по запросу, поэтому все объединяется вместе.

Имеются динамически импортируемые модули

Здесь сначала используйтеПредложение ECMAScriptСинтаксис импорта()

// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import(/* webpackChunkName: "async-jquery" */ 'jquery').then(component => {
  console.log(component)
})

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
  <div>SplitChunk</div>,
  document.getElementById('root')
)

Здесь jquery использует динамический импорт.В результатах упаковки видно, что jquery упакован отдельно

реагировать на нагрузку по запросу

Точно так же мы пытаемся загрузить реакцию по запросу, используя ту, что предоставляется react-router.План загрузки по запросу

Модуль AsyncModule асинхронно загружает Dashboard по приведенной выше схеме.

import React from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter, Route} from 'react-router-dom'
import AsyncModule from './AsyncModule.jsx'
import _ from 'lodash'
import $ from 'jquery'

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
  <div>
    <BrowserRouter>
      <Route path='/' component={AsyncModule} />
    </BrowserRouter>
  </div>,
  document.getElementById('root')
)

Из результатов упаковки видно, что модули, загружаемые по запросу, упакованы в 0.js.

После разговора об оптимизации блоков упаковки по умолчанию webpack, давайте посмотрим на элемент конфигурации splitChunks.

элемент конфигурации

Связанные элементы конфигурации:

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async', 
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~', 
      name: true,
      cacheGroups: {}
    }
  }
}
  • чанки: указывает, какой код необходимо оптимизировать.Есть три необязательных значения: начальный (начальный блок), асинхронный (загрузка блоков по требованию), все (все блоки), по умолчанию — асинхронный
  • minSize: указывает минимальный размер модуля перед сжатием, по умолчанию 30000.
  • МИНЧУНКИ: Указывает количество цитат, по умолчанию 1
  • maxAsyncRequests: максимальное количество параллельных запросов при загрузке по запросу, по умолчанию 5
  • maxInitialRequests: максимальное количество параллельных запросов для записи, по умолчанию 3
  • AutomaticNameDelimiter: Именованный разделитель
  • name: Имя разделенного блока, которое автоматически генерируется из имени блока и значения хеш-функции по умолчанию.
  • cacheGroups: группы кэширования. Помимо всех вышеперечисленных атрибутов, к атрибутам группы кеша относятся test, priority, reuseExistingChunk
    • test: используется для контроля того, какие модули соответствуют этой группе кеша
    • приоритет: приоритет упаковки группы кеша
    • reuseExistingChunk: если модуль, содержащийся в текущем блоке кода, уже существует, новый блок кода больше не создается.

Элементы конфигурации в основном те же, что и выше, давайте сосредоточимся на чанках и cacheGroups.

chunks

Значения чанков начальные, асинхронные, все. По умолчанию используется асинхронный режим, и его производительность была представлена ​​в первой части этой статьи, поэтому давайте посмотрим на производительность двух других.

initial, allШаблон назначит все модули из node_modules группе кеша с именем vendors; весь код, на который ссылаются хотя бы дважды, будет назначен группе кеша по умолчанию.

// indexA.js
import './Dashboard.jsx'

// indexB.js
import './Dashboard.jsx'

// Dashboard.jsx
import React from 'react'
// webpack.config.js
splitChunks: {
  chunks: 'initial'
}

Упаковка ведет себя так, как описано выше, что приводит к двум поставщикам блоков кода по умолчанию.

Группу кеша по умолчанию можно отключить, настроив для оптимизации.splitChunks.cacheGroups.default: false.

// webpack.config.js
splitChunks: {
  chunks: 'initial',
  cacheGroups: {
    default: false
  }
}

О разнице между all и initial вы можете прочитать в этой статьеWebpack 4 — Таинственный плагин SplitChunks(научный доступ в Интернет)

упоминается вinitialВ этом режиме асинхронные и неасинхронные модули упаковываются отдельно и оптимизируются. а такжеallАсинхронные и неасинхронные будут оптимизированы и упакованы одновременно. То есть модуль A вводится асинхронно в indexA и синхронно вводится в indexB.initialОн появится в модуле две блоки упаковки, а такжеallА появится.

cacheGroups

Блоки упаковки можно настраивать с помощью cacheGroups.

// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import $ from 'jquery'

// indexB.js
import React from 'react'
import ReactDOM from 'react-dom'
import('lodash')
import $ from 'jquery'

// webpack.config.js
optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2
        }
      }
    }
  }

В соответствии с условиями сегментации webapck, введенными в начале, некоторые общие модули упаковываются в общие, а приоритет пользовательских блоков упаковки равен 0, поэтому теперь общедоступные модули будут упаковываться в общие пакеты вместо упомянутых выше поставщиков блоков упаковки по умолчанию (приоритет является бременем).

Но почему lodash здесь не упакован? Вы можете просмотреть разницу между initial и all. Далее поэкспериментируйте с эффектом всего.

// indexA, indexB同上
// webpack.config.js
optimization: {
    splitChunks: {
        cacheGroups: {
            commons: {
                name: 'commons',
                chunks: 'all',
                minChunks: 2
            }
        }
    }
}

Как и ожидалось, lodash упакован вместе.

Извлечь сторонние библиотеки

Наконец, давайте взглянем на часто используемые отдельные сторонние библиотечные функции CommonsChunkPlugin. Здесь можно подумать, как это сделать.

Настройки были указаны вышеchunks: initial || allСторонние библиотеки могут быть извлечены. Но он извлекает все третьи библиотеки, поэтому нам нужно настроить cacheGroup, когда мы извлекаем только react и react-dom.

// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import $ from 'jquery'

// webpack.config.js
entry: {
    indexA: path.join(__dirname, 'src/indexA.js')
},
optimization: {
    splitChunks: {
        chunks: 'all',
        cacheGroups: {
            vendors: {
                test: /react/,
                name: 'vendors'
            }
        }
    }
}

Мы переписали блок упаковки поставщика и упаковали только те модули, которые соответствовали реакции, поэтому функция предыдущего CommonsChunkPlugin была достигнута.

или

// index.jsx
import React from 'react'
import ReactDOM from 'react-dom'

// webpack.config.js
entry: {
    indexA: path.join(__dirname, 'src/indexA.js'),
    vendor: ["react", "react-dom"]
},
optimization: {
    splitChunks: {
        cacheGroups: {
            vendor: {
                name: "vendor",
                chunks: "initial"
            }
        }
    }
}

Добавьте запись поставщика в запись упаковки веб-пакета, которая включает все библиотеки, которые необходимо упаковать отдельно, а затем установите этот блок упаковки в cacheGroups.chunks: initial || all, также может извлекать дубликаты библиотек в indexA и поставщика в блок упаковки поставщика.

optimization.runtimeChunk

Наконец, упомяните runtimeChunk черезoptimization.runtimeChunk: trueопция, webpack добавит к каждой записи дополнительный блок кода, который содержит только время выполнения (runtime). (Аннотация: это необходимо использовать в зависимости от сцены, что заставит каждую запись загружать дополнительный код времени выполнения)

Суммировать

Функция splitChunks в webpack4 относительно мощная, но рекомендуется использовать режим по умолчанию или извлечь стороннюю библиотеку.

использованная литература