Узнайте немного больше о CommonsChunkPlugin для webpack

Webpack

привет~ уважаемые наблюдатели и господа, привет всем~ я недавно изучалwebpackсоответствующие знания. Когда-то я всегда чувствовалwebpackСистема огромна и сложна в освоении, ее избегают и не хотят учиться. Однако великий человек Лу Синь однажды сказал:В мире так много вещей, которые могут сделать вас маниакальным и беспокойным, и лучшее решение — стиснуть зубы и начать это делать!Поэтому из более простогоCommonsChunkPluginНачнем учиться~

Хотя эта статья относительно проста, в ней все же нужно немногоwebpackзнание, если не совсемwebpack, рекомендуется двигаться первымофициальная документацияа такжеWebpack 3, от входа до отказаУзнать оwebpackХорошая основа~

Базовая конфигурация

CommonsChunkPluginПлагин - это дополнительная функция для создания отдельного файла (также называемого кусочками), который содержит общие модули нескольких кусков ввода. Вынимая общие модули, окончательный синтезированный файл может быть загружен один раз в начале, а затем сохраняется в кэше для последующего использования. Это приводит к увеличению скорости, потому что браузер быстро вытаскивает общий код из кэша, вместо того, чтобы загружать больший файл каждый раз, когда доступна новая страница.

Проще говоря, это немного похоже на обертку функции. Отделение инварианта от изменения обеспечивает эффективное повторное использование инварианта и гибкую конфигурацию изменения. Далее будем оптимизировать наш проект по этому принципу.Теперь посмотрим как выглядит виртуальный проект~

создать новыйindex.htmlШаблоны и вводindex.jsфайл, простая конфигурация выглядит следующим образом:

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p>{{ vue_test }}</p>
    </div>
    <div class="jq_test"></div>
</body>
</html>

index.js:

import Vue from 'vue';
import $ from 'jquery';

new Vue({
  el: '#app',
  data: {
    vue_test: 'vue is loaded!'
  }
})

$(function() {
  $('.jq_test').html('jquery is loaded!')
})

Для наглядности код очень простой, думаю объяснять не надо. Далее просто настройтеwebpack.config.js, код показан ниже:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  entry: {
    index: path.join(__dirname, 'index.js')
  },
  output: {
    path: path.join(__dirname, '/dist'),
    filename: 'js/[name].[chunkhash].js'
  },
  resolve: { alias: { 'vue': 'vue/dist/vue.js' } },
  plugins: [
    new CleanWebpackPlugin(['./dist']),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    new BundleAnalyzerPlugin(),
  ]
};

CleanWebpackPluginВ основном используется для очисткиdistФайлы в каталоге, чтобы вам не приходилось вручную очищать их каждый раз при упаковке.HtmlWebpackPluginдляdistновый каталогhtmlшаблон и автоматически вставлять зависимыеjs.BundleAnalyzerPluginВ основном для создания упакованныхjsЗависимости, содержащиеся в файле, при упаковке в это время генерируют:

можно увидеть сгенерированныйindex.jsфайл содержитvueа такжеjquery.

первая оптимизация

Вообще говоря, библиотека классов в нашем проекте меняется меньше, но бизнес-код поддается изменениям. Необходимо найти способ извлечь библиотеку классов и упаковать бизнес-код отдельно. Это вредитhashПосле того, как браузер сможет кэшировать библиотеку классовjsфайлы для оптимизации взаимодействия с пользователем. Наш главный геройCommonsChunkPluginофициально дебютировал. мы вwebpack.config.jsдокументpluginsдобавлено вCommonsChunkPlugin, настроенный следующим образом:

plugins: [
    //...此前的代码
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function(module) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, './node_modules')
          ) === 0
        )
      }
    }),
]

Вышеупомянутая конфигурация выполняетсяCommonsChunkPluginсоздать файл с именемvendorизjsфайл, он извлекает файл записи, которыйindex.jsв источникеnode_modulesсостав зависимостей. В данном случае этоvueа такжеjquery. Стиль упаковки выглядит так:

На данный момент кажется, что наша проблема решена, библиотека зависимых классов извлекается и упаковывается независимо, а кеш может кэшироваться браузером. Однако все не так просто, нет, вы можете изменить вход по своему желанию.index.jsКод, упакованный снова:

Отчаявшись найтиvendor.jsдокументhashизмененный. Проще говоря, это вызвано изменением идентификации модуля, более конкретные причины можно найти вСвязанная китайская документация~ Метод исправления на самом деле довольно прост, просто используйте его сноваCommonsChunkPluginИзвлеките модуль один раз, поместите неизменную библиотеку классов и извлеките измененную. Поэтому добавьте следующий код:

plugins: [
    //...此前的代码
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function(module) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, './node_modules')
          ) === 0
        )
      }
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor', 'index']
    })
]

После упаковки,dist/jsВ каталоге есть дополнительный файл с именемmanifestизjsфайл, и в этот момент вы меняете, несмотря ни на чтоindex.jsкод, упаковкаvendor.jsизhashбольше не изменится.

Но подождите, когда вы захотите хлопнуть в ладоши и покончить с этим, подумайте об этом сценарии: пока проект продолжает итерацию,vendorЗависимости постоянно добавляются и удаляются, что делает егоhashБудут постоянные изменения, которые явно не в наших интересах, так как же именно это можно решить?

оптимизировать снова

теперь, когдаCommonsChunkPluginМожно извлекать модули в соответствии с нашими потребностями, а внешние модули, которые от них зависят, могут постоянно меняться, так почему бы не извлечь основные зависимые модули в виде файла, а другие зависимости, такие как подключаемые модули, в виде отдельного файла?

Проще говоря, как в нашем проектеvueявляется базовой зависимостью и должна использоваться, иjqueryEtc. — это библиотека классов, добавленная позже, которая может быть изменена позже. тогда будетvueУпакуйте файл независимо, что хорошо для кеширования браузера, потому что независимо от того, добавите ли вы больше библиотек классов или удалите их позжеjqueryчас,vueФайловый кеш все еще действует. Итак, мы можем сделать это, сначала создайте новую запись:

entry: {
    index: path.join(__dirname, 'index.js'),
    vendor: ['vue'],
},

В основном это используется для указания того, какие зависимости должны быть упакованы независимо. позжеpluginsВнесите следующие изменения:

plugins: [
    //...此前的代码
    new webpack.HashedModuleIdsPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: Infinity,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common',
      minChunks: function(module) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, './node_modules')
          ) === 0
        )
      },
      chunks: ['index'],
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor', 'common', 'index']
    })
]

плагинHashedModuleIdsPlugin, используется для хранения ссылок на модулиmodule idпостоянный. а такжеCommonsChunkPluginЗатем извлеките зависимости, указанные в записи, и упакуйте независимо друг от друга,minChunks: Infinity,Цель состоит в том, чтобы позволить плагину игнорировать другие вещи, просто извлекая файлы в соответствии с установленным массивом. Затем измените оригиналvendor, переименован вcommon, указав его из записиindex.jsизвлеченный изnode_modulesзависимость. Наконец, извлечениеwebpackФункции времени выполнения и идентификаторы их модулейmanifest. запустить егоwebpack, который строится, как показано на рисунке:

можно увидетьvueа такжеjqueryУпакован отдельно в два файла, попробуем добавить новую зависимостьvuex, результат после упаковки такой:

Таким образом, наша цель оптимизации была достигнута, неизмененные извлекаются, а измененные могут быть динамически настроены ~

резюме

webpackплагинCommonsChunkPluginЭто все, что я представил здесь, но есть еще много оптимизаций, таких как включение сжатия, удаление комментариев и т. д. Когда объем проекта постепенно увеличивается,CommonsChunkPluginЭто не обязательно оптимальное решение для извлечения кода. Сочетание скорости упаковки с детализацией контроля сборкиDLLPluginбудет работать лучше. Комбинируя разные плагины по разным сценариям для достижения нашей цели, изначальноwebpackодин из прелестей.

Спасибо всем официалам за то, что это увидели, это легче сказать, чем сделать, надеюсь эта статья будет вам полезна, все коды будут загружены наgithubвставай, умоляйstar~ Спасибо!