Резюме вопросов интервью для веб-пакета

Webpack


Зачем обобщать вопросы интервью, связанные с webpack

С ростом сложности и масштаба современной фронтенд-разработки уже невозможно вести самостоятельную разработку без инжиниринга.Например, код jsx реакции должен быть скомпилирован до того, как его можно будет использовать в браузере;другим примером является браузер кода sass и меньше тоже не поддерживается. И если отказаться от этих фреймворков разработки, то эффективность разработки упадет в разы. Среди многих интерфейсных инженерных инструментов,webpackВыделитесь сегодня как самый популярный инструмент для сборки интерфейса. Однако большинство пользователей просто使用, не зная его основных принципов. Я надеюсь, что следующее краткое изложение вопросов для интервью поможет вам проанализировать прошлое и узнать что-то новое, проверить и заполнить пробелы и понять, почему.


Список вопросов

  1. Чем webpack отличается от grunt и gulp?
  2. Какие еще инструменты похожи на webpack? Расскажите, почему вы решили (или отказались) использовать веб-пакет?
  3. Каковы общие загрузчики? Какую проблему они решают?
  4. Каковы общие плагины? Какую проблему они решают?
  5. В чем разница между загрузчиком и плагином?
  6. Каков процесс создания веб-пакета?Процесс от чтения конфигурации до выходного файла максимально завершен.
  7. Вы написали загрузчик и плагин? Опишите идею написания загрузчика или плагина?
  8. Как выполняется горячее обновление веб-пакета? Объясните его принцип?
  9. Как использовать веб-пакет для оптимизации производительности интерфейса? (улучшает производительность и опыт)
  10. Как улучшить скорость сборки webpack?
  11. Как настроить одностраничное приложение? Как настроить многостраничные приложения?
  12. На что следует обратить внимание при упаковке с помощью npm? Как использовать webpack для лучшей сборки?
  13. Как реализовать загрузку по требованию в проекте vue?

1. В чем разница между webpack, grunt и gulp?

Все три являются интерфейсными инструментами для построения интерфейса. Grunt и gulp были популярны в первые дни. Теперь webpack является относительно мейнстримным. Однако некоторые легкие задачи по-прежнему выполняются с помощью gulp, например, отдельная упаковка CSS-файлов.

gruntа такжеgulpОн основан на задачах и потоках (Task, Stream). Подобно jQuery, найдите файл (или класс файлов), выполните над ним серию цепочек операций и обновите данные в потоке Вся цепочка операций представляет собой задачу, а несколько задач составляют весь процесс построения сети.

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

Итак, подведем итог:

  • С точки зрения строительства
gulp和grunt需要开发者将整个前端构建过程拆分成多个`Task`,并合理控制所有`Task`的调用关系
webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工
  • Для фона знаний
    Gulp больше похож на мышление бэкенд-разработчиков, и ему нужно хорошо знать весь процесс, тогда как Webpack больше склонен к мышлению фронтенд-разработчиков.

2. Какие еще инструменты похожи на webpack? Расскажите, почему вы решили (или отказались) использовать веб-пакет?

Существуют также следующие основные инструменты упаковки, основанные на входе:

С точки зрения сценария приложения:

  • webpack подходит для создания больших и сложных интерфейсных сайтов.
  • роллап подходит для упаковки базовых библиотек, таких как vue, react
  • посылка подходит для простых экспериментальных проектов, она может соответствовать низкому порогу и быстро увидеть эффект
Поскольку отладочная информация, предоставляемая посылкой в ​​процессе упаковки, очень ограничена, ее трудно отладить после возникновения ошибки упаковки, поэтому не рекомендуется использовать посылку для сложных проектов.

3. Каковы общие загрузчики? Какую проблему они решают?

  • загрузчик файлов: вывод файла в папку и обращение к выходному файлу через относительный URL-адрес в коде
  • url-loader: аналогичен файловому загрузчику, но может вставлять содержимое файла в код в режиме base64, когда файл небольшой.
  • source-map-loader: загружает дополнительные файлы исходной карты для облегчения отладки точки останова.
  • image-loader: загружать и сжимать файлы изображений
  • babel-loader: конвертировать ES6 в ES5
  • css-loader: загружает CSS, поддерживает модульность, сжатие, импорт файлов и другие функции.
  • style-loader: вставка кода CSS в JavaScript и загрузка CSS с помощью манипуляций с DOM.
  • eslint-loader: проверка кода JavaScript с помощью ESLint

4. Каковы общие плагины? Какую проблему они решают?

  • определить-плагин: определить переменные среды
  • commons-chunk-plugin: извлечь общий код
  • uglifyjs-webpack-плагин: пройтиUglifyESкомпрессияES6код

5. В чем разница между загрузчиком и плагином?

другая роль

  • LoaderДословно переводится как «загрузчик». Webpack рассматривает все файлы как модули, но изначально Webpack может анализировать только файлы js.Если вы хотите упаковать другие файлы, вы будете использовать его.loader. Таким образом, роль Loader состоит в том, чтобы позволить веб-пакету загружать и анализироватьФайлы без JavaScriptСпособность.
  • PluginДословно переводится как «плагин». Плагин может расширить функциональность веб-пакета, придав веб-пакету большую гибкость. В течение жизненного цикла работы Webpack многие события транслируются, и плагин может прослушивать эти события и изменять выходные результаты через API, предоставляемый Webpack, в соответствующее время.

различное использование

  • Loaderсуществуетmodule.rulesВ конфигурации, то есть, он существует как правило разбора модуля. Тип — массив, каждый элемент — этоObject, который описывает, для какого типа файла (test), с помощью чего загрузить (loader) и используемые параметры (options)
  • Pluginсуществуетpluginsнастраивается отдельно. Тип — массив, каждый элемент — этоpluginЭкземпляр , параметры передаются через конструктор.

6. Что такое процесс сборки вебпака?Процесс от чтения конфигурации до выходного файла должен быть максимально полным

Работающий процесс Webpack является последовательным процессом, и следующие процессы выполняются последовательно от начала до конца:

  1. Параметры инициализации: чтение и объединение параметров из файлов конфигурации и операторов оболочки для получения окончательных параметров;
  2. Начать компиляцию: Инициализируйте объект Compiler с параметрами, полученными на предыдущем шаге, загрузите все настроенные плагины и выполните метод запуска объекта, чтобы начать компиляцию;
  3. Определить запись: найти все файлы записи в соответствии с записью в конфигурации;
  4. Скомпилируйте модуль: начиная с файла записи, вызовите все настроенные загрузчики для преобразования модуля, затем найдите модули, от которых зависит модуль, а затем повторите этот шаг, пока все файлы, зависящие от записи, не будут обработаны на этом шаге;
  5. Завершение компиляции модуля: После перевода всех модулей с помощью Loader на шаге 4 получается финальное содержимое каждого модуля после перевода и зависимости между ними;
  6. Выходные ресурсы: в соответствии с зависимостями между записями и модулями соберите фрагменты, содержащие несколько модулей, один за другим, а затем преобразуйте каждый фрагмент в отдельный файл и добавьте его в список выходных данных.Этот шаг — последний шанс изменить выходное содержимое. ;
  7. Вывод завершен: после определения содержимого вывода определите путь вывода и имя файла в соответствии с конфигурацией и запишите содержимое файла в файловую систему.

В приведенном выше процессе Webpack будет транслировать определенное событие в определенный момент времени, подключаемый модуль будет выполнять определенную логику после прослушивания интересующего события, а подключаемый модуль может вызывать API, предоставленный Webpack, для изменения текущего результат вебпака.

7. Вы написали загрузчик и плагин? Опишите идею написания загрузчика или плагина?

Загрузчик подобен «переводчику», чтобы преобразовать содержимое прочитанного исходного файла в новое содержимое файла, и каждый загрузчик шаг за шагом переводит исходный файл в желаемый вид через цепочку операций.

При написании загрузчиков следуйте единому принципу, и каждый загрузчик выполняет только один вид "экранирования". Каждый загрузчик получает содержимое исходного файла (source), вы можете вывести обработанный контент, вернув значение, или вы можете вызватьthis.callback()способ вернуть содержимое в webpack. также черезthis.async()генерироватьcallbackфункцию, а затем используйте этот обратный вызов для вывода обработанного содержимого. такжеwebpackТакже подготовлен для разработчиков, чтобы разработать набор функций инструмента загрузчика -loader-utils.

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

8. Как происходит горячее обновление вебпака? Объясните его принцип?

Горячее обновление webpack также называется горячей заменой (Hot Module Replacement), сокращенно HMR. Этот механизм позволяет заменять старые модули новыми модулями без обновления браузера.

принцип:

Изображение взято из передней части колонки голодных @zhihu.

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

  1. Первый шаг, в режиме просмотра веб-пакета, когда файл в файловой системе изменяется, веб-пакет отслеживает изменение файла, перекомпилирует и упаковывает модуль в соответствии с файлом конфигурации и сохраняет упакованный код в памяти через простой объект JavaScript. .
  2. Вторым шагом является интерфейсное взаимодействие между webpack-dev-server и webpack, и на этом этапе, в основном взаимодействие между промежуточным ПО dev-server webpack-dev-middleware и webpack, webpack-dev-middleware вызывает webpack для раскрытия кода. изменяется и указывает webpack упаковать код в память.
  3. Третий шаг — это мониторинг изменений файлов с помощью webpack-dev-server, этот шаг отличается от первого тем, что он не отслеживает изменения кода и не перепаковывает их. Когда мы настраиваем devServer.watchContentBase в файле конфигурации как true, сервер будет отслеживать изменения статических файлов в этих папках конфигурации и уведомит браузер о необходимости перезагрузки приложения после изменения. Обратите внимание, что здесь обновление браузера и HMR — это два разных понятия.
  4. Четвертый шаг также является работой кода webpack-dev-server.Этот шаг в основном заключается в установлении длинного соединения websocket между браузером и сервером через sockjs (зависимость от webpack-dev-server), а также компиляции и упаковки каждого этапа. of webpack Информация о состоянии сервера уведомляет сторону браузера, а также включает в себя информацию о том, что сервер отслеживает изменения статических файлов на третьем шаге. Сторона браузера выполняет различные операции на основе этих сообщений сокета. Разумеется, самой важной информацией, передаваемой сервером, является хеш-значение нового модуля, и последующие шаги будут выполнять горячую замену модуля на основе этого хэш-значения.
  5. Сторона webpack-dev-server/client не может запрашивать обновленный код, выполнять операции с горячими модулями и передавать эти задачи webpack.Работа webpack/hot/dev-server основана на webpack-dev. -server/client и конфигурация dev-server определяют, следует ли обновлять браузер или выполнять горячее обновление модуля. Конечно, если вы просто обновите браузер, дальнейших шагов не будет.
  6. HotModuleReplacement.runtime является хабом HMR клиента, получает хеш-значение нового модуля, переданного ему на предыдущем шаге, отправляет Ajax-запрос на сервер через JsonpMainTemplate.runtime, и сервер возвращает json, содержащий все информация, подлежащая обновлению.После получения обновленного списка хеш-значений модуля модуль снова запрашивает последний код модуля через jsonp. Это шаги 7, 8 и 9 на изображении выше.
  7. 10-й шаг является ключевым шагом для определения успеха HMR.На этом этапе HotModulePlugin сравнит старый и новый модули, чтобы решить, следует ли обновлять модуль.Приняв решение об обновлении модуля, проверьте зависимости между модулями и обновите module Также обновите зависимости между модулями.
  8. На последнем шаге, когда HMR дает сбой, вернитесь к операции перезагрузки в реальном времени, которая заключается в обновлении браузера для получения последнего упакованного кода.

9. Как использовать веб-пакет для оптимизации производительности интерфейса? (улучшает производительность и опыт)

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

  • Сжатый код. Удалите лишний код, комментарии, упростите написание кода и т. д. Вы можете использовать веб-пакетUglifyJsPluginа такжеParallelUglifyPluginЧтобы сжать файлы JS, используйтеcssnano(css-loader? свернуть) для сжатия css
  • Ускорьтесь с CDN. В процессе сборки измените указанный путь к статическому ресурсу на соответствующий путь в CDN. Вы можете использовать веб-пакет дляoutputпараметры и каждый загрузчикpublicPathпараметры для изменения пути к ресурсу
  • Удаление мертвого кода (Tree Shaking). Удалите фрагменты в коде, которые никогда не идут. Это можно сделать, добавив параметры при запуске веб-пакета.--optimize-minimizeреализовать
  • Извлечь общедоступный код.

10. Как улучшить скорость сборки webpack?

  1. В случае нескольких записей используйтеCommonsChunkPluginизвлечь публичный код
  2. пройти черезexternalsНастроить, чтобы извлечь общие библиотеки
  3. использоватьDllPluginа такжеDllReferencePluginПредварительно скомпилированные модули ресурсов черезDllPluginЧтобы предварительно скомпилировать те пакеты npm, на которые мы ссылаемся, но никогда не будем их изменять, а затем передатьDllReferencePluginЗагрузите предварительно скомпилированный модуль.
  4. использоватьHappypackРеализовать многопоточную ускоренную компиляцию
  5. использоватьwebpack-uglify-parallelулучшитьuglifyPluginскорость сжатия. В общемwebpack-uglify-parallelМногоядерное параллельное сжатие используется для повышения скорости сжатия.
  6. использоватьTree-shakingа такжеScope Hoistingдля устранения избыточного кода

11. Как настроить одностраничное приложение? Как настроить многостраничные приложения?

Одностраничные приложения можно понимать как стандартный режим вебпака, прямо вentryВы можете указать запись одностраничного приложения в

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

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

12. На что следует обратить внимание при упаковке npm? Как использовать webpack для лучшей сборки?

NpmJavaScript — самый большой складской модуль, разработчики со всего мира загружают повторно используемые модули. Вы можете просто использовать пользовательский модуль JS, но в некоторых случаях вы также можете загрузить собственную разработку модуля. О методе Модули NPM можно загружать наОфициальный сайтИзучите вышеизложенное, здесь только объясните, как использовать webpack для сборки.

Модули NPM должны обратить внимание на следующие вопросы:

  1. Для поддержки модульной спецификации CommonJS конечный результат после упаковки должен соответствовать этому правилу.
  2. Среда пользователей модуля Npm неопределенна, и весьма вероятно, что ES6 не поддерживается, поэтому окончательный результат упаковки следует писать на ES5. И если ES5 конвертируется, пожалуйста, загрузите его вместе с SourceMap.
  3. Размер пакета Npm должен быть как можно меньше (некоторые репозитории ограничивают размер пакета)
  4. Опубликованные модули не могут быть упакованы с зависимыми модулями, и пользователям должно быть разрешено выборочно устанавливать их самостоятельно. Это может избежать ситуации, когда базовый модуль повторно упаковывается, когда пользователь модуля упаковывает его снова.
  5. Модули классов компонентов пользовательского интерфейса должны зависеть от других файлов ресурсов, таких как.cssФайлы также должны быть включены в опубликованный модуль.


Основываясь на вышеуказанных проблемах, требующих внимания, мы можем сделать следующие расширения и оптимизации для конфигурации веб-пакета:

  1. Решение модульной спецификации CommonJS: setoutput.libraryTarget='commonjs2'Сделайте выходной код соответствующим модульной спецификации CommonJS2 для импорта и использования других модулей.
  2. Решение для вывода кода ES5: используйтеbabel-loaderПреобразование кода ES6 в код ES5. затем включитеdevtool: 'source-map'Вывод SourceMap для отладки выпуска.
  3. Решение для наименьшего размера пакета Npm: Babel внедряет некоторые вспомогательные функции при преобразовании кода ES6 в код ES5, что в конечном итоге приводит к тому, что каждый выходной файл содержит код этой вспомогательной функции, что приводит к избыточности кода. Решение состоит в том, чтобы изменить.babelrcфайл для добавленияtransform-runtimeплагин
  4. Решение для невозможности упаковать зависимые модули в модули npm: используйтеexternalsЭлементы конфигурации, чтобы указать веб-пакету, какие модули не нужно упаковывать.
  5. Для решений, упакованных зависимыми файлами ресурсов: черезcss-loaderа такжеextract-text-webpack-pluginДля достижения конфигурация выглядит следующим образом:
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  module: {
    rules: [
      {
        // 增加对 CSS 文件的支持
        test: /\.css/,
        // 提取出 Chunk 中的 CSS 代码到单独的文件中
        use: ExtractTextPlugin.extract({
          use: ['css-loader']
        }),
      },
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      // 输出的 CSS 文件名称
      filename: 'index.css',
    }),
  ],
};

13. Как реализовать загрузку по требованию в проекте vue?

Загрузка по запросу библиотеки компонентов Vue UIДля быстрой разработки фронтенд-проектов часто вводятся готовые библиотеки UI-компонентов, такие как ElementUI, iView и т. д., но их объем столь же огромен, как и функции, которые они предоставляют. Обычно нам нужно только небольшое количество компонентов, но мы упаковываем огромную библиотеку компонентов в наш исходный код, вызывая ненужные накладные расходы.

Однако многие библиотеки компонентов уже предоставляют готовые решения, такие как Element'sbabel-plugin-componentи МуравейДизайнbabel-plugin-importПосле установки вышеуказанных плагинов в.babelrcнастройка илиbabel-loaderЗадав его в параметрах, компонент можно будет подгружать по требованию.

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

Загрузка по требованию для одностраничных приложенийВ настоящее время многие интерфейсные проекты разрабатываются с помощью одностраничных приложений, но по мере расширения бизнеса он столкнется с серьезной проблемой — объем кода, загружаемого в первый раз, увеличится, что повлияет на пользовательский опыт.

пройти черезimport(*)заявление для управления временем загрузки, webpack имеет встроенный дляimport(*)анализ, будетimport(*)Модуль, представленный в качестве новой записи, генерирует чанк. Когда код выполняется дляimport(*)При выполнении оператора будет загружен файл, соответствующий чанку.import()Возвращает объект Promise, поэтому для того, чтобы браузер поддерживал его, его необходимо внедрить заранее.Promise polyfill

Справочная статья

Ran Sixi: Анализ принципа работы Webpack HMR