Output management
Содержание:
Создаём html-файлы при помощи html-webpack-plugin
Для создания html-файлов и работы с шаблонами мы будем использовать плагин html-webpack-plugin.
Установим плагин при помощи Yarn. Не забудем флаг -D, чтобы зависимость была сохранена в devDependencies файла-манифеста. Туда же, где сохранён вебпак.
PHP
yarn add html-webpack-plugin -D
1 | yarn add html-webpack-plugin-D |
В webpack.config.js мы поместим следующий код. Я сэкономлю ваше время, сейчас и далее я не буду тратить время на тайпинг. Вместо этого постараюсь объяснить уже набранный код.
PHP
const path = require(‘path’);
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
const PATHS = {
source: path.join(__dirname, ‘source’),
build: path.join(__dirname, ‘build’)
};
module.exports = {
entry: PATHS.source + ‘/index.js’,
output: {
path: PATHS.build,
filename: ‘.js’
},
plugins:
};
1 |
constpath=require(‘path’); constHtmlWebpackPlugin=require(‘html-webpack-plugin’); constPATHS={ sourcepath.join(__dirname,’source’), buildpath.join(__dirname,’build’) }; module.exports={ entryPATHS.source+’/index.js’, output{ pathPATHS.build, filename’.js’ }, plugins newHtmlWebpackPlugin({ title’Webpack app’ }) }; |
Пояснения:
— “сonst” — это ES6-альтернатива для “var”, указывающая, что переменная не должна быть изменена. Node.js полностью поддерживает эту часть ES6, т.е. в данном случае я также могу обойтись без babel.
— “path” — это базовый модуль node.js, который поможет нашему приложению работать корректно (одинаково) на разных платформах (например, windows или linux), т.к. они по разному определяют пути к файлам.
— “PATH” — объект, в который мы поместили 2 свойства: “source” — исходники приложения и “build” — папка, в которую будут помещаться результаты работы Webpack.
— “module.exports” — экспорт модуля в node.js. Внутри него мы пишем такие настройки Webpack, как entry, output, plugins и пр.
— “entry” — точка входа нашего приложения. Для многостраничного сайта можно сделать отдельные точки входа для каждой страницы. Запомните, что точками входа могут являться только те модули, которые не используются другими модулями вашего приложения. Так, например, наш модуль index.js использует другой модуль — menu.js. Но сам index.js не используется больше никаким модулем.
— “output” — описывает имена файлов и директорию — результат работы Webpack.
— “” — это плейсхолдер, в него автоматически будут подставляться имена точек входа “entry” нашего приложения. А у нас их будет несколько. Но об этом позже.
— “plugins” — в этом разделе перечисляются плагины, которые кастомизируют процесс сборки Webpack. В нашем случае, это всего один плагин, который создает HTML-файл с заданным тайтлом.
source
Plugins affecting the source code of modules.
APIPlugin
Make webpack_public_path, webpack_require, webpack_modules and webpack_chunk_load accessible. Ensures that and are not processed by other plugins.
ConstPlugin
Tries to evaluate expressions in statements and ternaries to replace them with / for further possible dead branch elimination using hooks fired by the parser.
There are multiple optimizations in production mode regarding dead branches:
- The ones performed by Terser
- The ones performed by webpack
webpack will try to evaluate conditional statements. If it succeeds then the dead branch is removed. webpack can’t do constant folding unless the compiler knows it. For example:
In the above example, webpack is unable to prune the branch, but Terser does. However, if is defined using DefinePlugin, webpack will succeed.
It is important to mention that will also get pruned because call was in the dead branch and got eliminated.
NodeStuffPlugin
Provide stuff that is normally available in Node.js modules.
It also ensures that is filled with some Node.js stuff if you use it.
Provide stuff that is normally available in require.js.
is removed. is . is mapped to .
NodeSourcePlugin
This module adds stuff from Node.js that is not available in non Node.js environments.
It adds polyfills for , , and if used. It also binds the built in Node.js replacement modules.
NodeTargetPlugin
The plugins should be used if you run the bundle in a Node.js environment.
If ensures that native modules are loaded correctly even if bundled.
RequireContextPlugin
Provides . The parameter and are used to find alternative requests for files. It’s useful to provide the same arrays as you provide to the resolver.
Webpack 2.2.1
Мы будем рассматривать Webpack версии 2.2.1. В новой версии появился ряд важных нововведений, связанных не только с новым функционалом, но и с некоторыми изменениями в синтаксисе.
Будьте осторожны при просмотре видеоуроков и прочтении статей, посвященных первой версии Webpack. Техники, описанные в них, могут быть не только устаревшими, но и ошибочными (применительно ко второй версии Webpack).
Несовместимость
Некоторые плагины Webpack могут быть полностью или частично несовместимы с Webpack 2. Некоторые — с node.js_7. Внимательно читайте документацию!
ES6-модули в Webpack 2
В Webpack 2 встроена поддержка ES6-модулей. Поэтому если мы используем babel, нужно его предупредить, что ES6-модули Webpack не нужно переделывать в CommonJS.
PHP
{
presets:
]
}
1 |
{ presets «es2015»,{«modules»false} } |
На этом первый видеоурок курса по изучению Webpack 2 завершится.
Приятного всем просмотра! Учитесь с удовольствием!
ツПолезные ссылки к видеоуроку:
Исходники на GitHub
Видеоурок по Yarn
Получить профессию «Веб-разработчик»
Прокачаться на «Продвинутом курсе по веб-разработке»
Подписывайтесь на канал, новые видео выходят каждую неделю.
Loading CSS
In order to a CSS file from within a JavaScript module, you need to install and add the style-loader and css-loader to your configuration:
webpack.config.js
Module loaders can be chained. Each loader in the chain applies transformations to the processed resource. A chain is executed in reverse order. The first loader passes its result (resource with applied transformations) to the next one, and so forth. Finally, webpack expects JavaScript to be returned by the last loader in the chain.
The above order of loaders should be maintained: comes first and followed by . If this convention is not followed, webpack is likely to throw errors.
This enables you to into the file that depends on that styling. Now, when that module is run, a tag with the stringified css will be inserted into the of your html file.
Let’s try it out by adding a new file to our project and import it in our :
project
src/style.css
src/index.js
Now run your build command:
Open up in your browser again and you should see that is now styled in red. To see what webpack did, inspect the page (don’t view the page source, as it won’t show you the result, because the tag is dynamically created by JavaScript) and look at the page’s head tags. It should contain the style block that we imported in .
Note that you can, and in most cases should, for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of – postcss, sass, and less to name a few.
Маппинг исходных файлов тестового кода
Тестовая сборка готова, но есть один нюанс, касающийся тестирования кода. Если запустить Mocha для файла и один из этих тестов не пройдёт, как это будет выглядеть? Давайте сделаем тест формулы расстояния в ошибочным:
Выполните и вот что получится:
Тест провален, но нельзя узнать, в какой строке исходного кода находится ошибка. Если таких тестов для веб-приложения у вас много, то поиски строки с ошибкой затянутся надолго.
Код с ошибкой находится в строке 8 в файле , но Mocha запускается для файла , поэтому, с точки зрения Mocha, ошибка находится в строке 116. К счастью, Webpack поддерживает source maps, которые покажут, какая строка кода соответствует ошибке. Source maps (или карты кода) — это файлы исходного кода, которые показывают точное соответствие элементов готового рабочего кода проекта и вашего кода разработки. Выполняется своего рода проход декодером по пакетному файлу , чтобы получить исходные строки кода, которые соответствуют связному коду. Давайте обновим оператор в файле :
Затем в объект добавим строку:
Теперь в тестировочных сборках каталог будет содержать файл типа source maps. Выполните и каталог будет содержать файл в дополнение к пакету .
Чтобы Mocha мог использовать эту source map при запуске тестов, необходимо установить ещё один пакет:
Теперь, чтобы его использовать, нужно обновить скрипт Mocha в разделе файла :
Флаг требует пакет , это означает, что Mocha будет использовать source map, если она доступна. Теперь, если вы выполните и получите ошибку, вы увидите, в какой строке она находится, и сможете исправить код (Commit 8).
Итак, теперь у вас есть пример настройки обычных и тестовых сборок с использованием маппинга. Существует также множество других способов, которыми вы можете воспользоваться в своих сборках, например, объединение нескольких загрузчиков JavaScript для обработки вашего кода как на конвейере или же запуск Webpack как отладочного сервера, чтобы моментально видеть, как изменения в коде влияют на окончательную сборку Webpack. Продолжайте пробовать различные пакеты для компоновки файла !
Для более точной настройки Webpack вам может быть полезен следующий материал:
Перевод статьи Webpack: From 0 to automated testing
module.parser
5.12.0+
Similar to the , you can configure all parsers’ options in one place with a .
webpack.config.js
module.parser.javascript
Configure options for JavaScript parser.
It’s allowed to configure those options in as well to target specific modules.
Enable support for CommonJS.
- Type:
- Available: 5.17.0+
- Example:
Note that only comment is supported at the moment:
module.parser.javascript.url
Enable parsing of syntax.
- Type: |
- Example:
The value for is available since webpack 5.23.0. When used, webpack would generate relative URLs for syntax, i.e., there’s no base URL included in the result URL:
- This is useful for SSR (Server side rendering) when base URL is not known by server (and it saves a few bytes). To be identical it must also be used for the client build.
- Also for static site generators, mini-css-plugin and html-plugin, etc. where server side rendering is commonly needed.
Loading Fonts
So what about other assets like fonts? The Asset Modules will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let’s update our to handle font files:
webpack.config.js
Add some font files to your project:
project
With the loader configured and fonts in place, you can incorporate them via an declaration. The local directive will be picked up by webpack just as it was with the image:
src/style.css
Now run a new build and let’s see if webpack handled our fonts:
Open up again and see if our text has changed to the new font. If all is well, you should see the changes.
Разное
Регулярно обновляйте ваше ПО и зависимости. Более свежие версии Node.js, npm / yarn и инструментов для сборки (webpack, Babel и др.) часто содержат улучшения производительности. Разумеется, перед началом эксплуатации новой версии стоит внимательно ознакомиться с changelog, issues, отчётами по безопасности, убедиться в стабильности и провести тестирование.
При использовании PostCSS и postcss-preset-env обратите внимание на настройку stage, которая отвечает за набор поддерживаемых фич. Например, в нашем проекте был установлен stage-3, из которого использовались только Custom Properties, и переключение на stage-4 сократило время сборки на 13%
Если вы используете Sass (node-sass, sass-loader), попробуйте Dart Sass (реализация Sass на Dart, скомпилированная в JS) и fast-sass-loader. Возможно, на вашем проекте они дадут прирост производительности сборки. Но даже если не дадут — dart-sass хотя бы устанавливается быстрее, чем node-sass, потому что является чистым JS, а не биндингом для libsass.
Пример использования Dart Sass можно найти в
Обратите внимание на явное указание конкретной имплементации препроцессора Sass и использование модуля fibers
Если вы используете CSS-модули, попробуйте отключить добавление хешей в сгенерированные имена классов в dev-режиме. Генерирование уникальных идентификаторов занимает какое-то время, которое можно сэкономить, если включения путей к файлам в имена классов достаточно, чтобы избежать коллизий.
Пример:
Выгода, тем не менее, невелика: на нашем проекте это менее полсекунды.
Возможно, вы когда-нибудь встречали в документации webpack таинственный PrefetchPlugin, который вроде бы обещает ускорить сборку, но каким образом — неизвестно. Создатель webpack в кратко рассказал о том, какую проблему решает этот плагин. Однако как же его использовать?
- Выгрузить в файл статистику сборки. Это делается с помощью CLI-опции , подробнее см. в документации. Актуально, скорее всего, только для dev-режима сборки.
- Загрузить полученный файл в специальный онлайн-анализатор и перейти на вкладку Hints.
- Найти секцию, озаглавленную “Long module build chains”. Если её нет, на этом можно закончить — PrefetchPlugin не понадобится.
- Для найденных длинных цепочек использовать PrefetchPlugin. В качестве стартового примера см. топик на StackOverflow.
Итого: слабо документированный способ без гарантии на заметный положительный результат.
Сборка HTML страниц
Перейдем к самому веселому: к сборке HTML страниц, где у меня возникли самые большие трудности.
Для сборки HTML страниц будем использовать плагин , который поддерживает различные виды шаблонизаторов. Также нам потребуются пакет .
В качестве шаблонизатора HTML будем использовать шаблонизатор по умолчанию lodash. Вот так будет выглядеть типичная HTML страница до сборки:
Вначале в переменной прописываем все наши переменные страницы, которые хотим использовать на этой странице. Потом встраиваем шаблоны шапки и футера через .
Важное уточнение. В статьях про сборку HTML страниц через обычно подключают встраиваемые шаблоны просто через команду:. Но при этом в этих встраиваемых шаблонах синтаксис lodash работать не будет (я так и не понял, почему так происходит)
И данные из переменной туда не передадутся. Поэтому принудительно говорим webpack, что мы встраиваем именно шаблон, который надо обработать как lodash шаблон
Но при этом в этих встраиваемых шаблонах синтаксис lodash работать не будет (я так и не понял, почему так происходит). И данные из переменной туда не передадутся. Поэтому принудительно говорим webpack, что мы встраиваем именно шаблон, который надо обработать как lodash шаблон.
Теперь мы можем использовать полноценные lodash синтаксис в встраиваемых шаблонах. В коде файла ниже через печатаем заголовок статьи.
В пакете html-webpack-plugin генерировать несколько HTML страниц:
Но прописывать для каждой страницы создание своего экземпляра плагина точно не есть хорошо. Поэтому автоматизируем этот процесс, найдя все HTML файлы в папке и создадим для них свои версии .
Для этого в файле внесем следующие изменения:
Функция будет осуществлять поиск всех HTML страниц
Обратите внимание, что в коде функции есть настройка , которая говорит Webpack, что не нужно встраивать ссылки на js и css файл в HTML код самостоятельно: мы сделаем всё сами вручную в шаблонах и
Также нужно отметить, что встраиваемые шаблоны обрабатываются плагином (содержимое файла просто загрузить как текст), а не , как чаще всего предлагают. И также, как в случае с CSS, не использую пакеты или .
И остается последний необязательный момент для работы с HTML. JavaScript файл и CSS файл у нас будут минимифицроваться. А вот HTML файлы хочу, наоборот, сделать красивыми и не минифицировать. Поэтому после сборки всех HTML файлов хочется пройтись по ним каким-то beautify плагином. И тут меня ждала подстава: не нашел способа как это сделать в Webpack. Проблема в том, что обработать файлы нужно после того, как будут вставлены встраиваемые шаблоны.
Нашел пакет html-cli, который может это сделать независимо от Webpack. Но у него 38 установок в месяц. То есть это означает два варианта: либо никому не нужно приводить к красивому внешнему виду HTML файлы, либо есть другое популярное решение, о котором я не знаю. А ради только одной этой функции Gulp прикручивать не хочется.
Устанавливаем этот плагин:
И в файле прописываем еще два скрипта, которые после работы Webpack будут приводить к красивому внешнему виду HTML файлы с установкой табуляции в два пробела.
Update 2018.04.11 Обратите внимание на то, что в команду я добавил еще , который очищает папку перед сборкой. Поэтому для итоговой сборки рекомендую использовать не команду *npm run build, а команду npm run build-and-beautify
Поэтому для итоговой сборки рекомендую использовать не команду *npm run build, а команду npm run build-and-beautify.
Что такое Webpack?
Webpack — это инструмент, позволяющий скомпилировать, например, JavaScript модули в единый JS-файл. Webpack также известен как сборщик модулей.
При большом количестве файлов он создает один объемный файл (или несколько файлов) для запуска вашего приложения.
Он также способен выполнять множество иных операций:
- помогает собрать воедино ваши ресурсы
- следит за изменениями и повторно выполняет задачи
- может выполнить транспиляцию JavaScript следующего поколения до более старого стандарта JavaScript (ES5) с помощью Babel, что позволит использовать новейшие функции JavaScript, не беспокоясь о том, поддерживает их браузер или нет
- может выполнить транспиляцию CoffeeScript в JavaScript
- может конвертировать встроенные изображения в data:URI
- позволяет использовать require() для CSS файлов
- может запустить webpack-dev-server (в нём встроен локальный сервер и livereload (“живая перезагрузка браузера”))
- может работать с Hot Module Replacement (замена горячего модуля)
- может разделить выходной файл (output file) на несколько файлов, чтобы избежать медленной загрузки страницы из-за большого размера JS-файла
- может выполнить Tree Shaking
Webpack не ограничивается одним лишь фронтендом, его также успешно применяют в бэкенд разработке на Node.js.
У Webpack есть предшественники, у которых он перенял многие идеи. Основное различие заключается в том, что те инструменты известны как task runners (такс-раннеры), в то время как Webpack ничто иное, как сборщик модулей.
Webpack — это более целенаправленный инструмент. Вам достаточно указать точку входа в ваше приложение (это может быть даже HTML-файл с тегами <script>), а webpack проанализирует файлы и объединит их в один выходной JavaScript-файл, содержащий все необходимое для запуска приложения.
Loading Images
So now we’re pulling in our CSS, but what about our images like backgrounds and icons? As of webpack 5, using the built-in Asset Modules we can easily incorporate those in our system as well:
webpack.config.js
Now, when you , that image will be processed and added to your directory and the variable will contain the final url of that image after processing. When using the css-loader, as shown above, a similar process will occur for within your CSS. The loader will recognize this is a local file, and replace the path with the final path to the image in your directory. The html-loader handles in the same manner.
Let’s add an image to our project and see how this works, you can use any image you like:
project
src/index.js
src/style.css
Let’s create a new build and open up the file again:
If all went well, you should now see your icon as a repeating background, as well as an element beside our text. If you inspect this element, you’ll see that the actual filename has changed to something like . This means webpack found our file in the folder and processed it!
Собираем JavaScript
Так как Webpack создан в первую очередь для сборки js файлов, то эта часть будем самой простой. Чтобы можно было писать javascript в современном виде ES2015, который не поддерживается браузерами, поставим пакеты , , .
После создаем файл настроек с таким содержимым:
В разделе (точки входа) указываем, какой js файл будем собирать, в разделе указываем путь в папке , куда будем помещаться собранный файл
Обратите внимание, что в webpack 4 в пути саму папку указывать не нужно! И да, как же мне не нравится, что в одном файле webpack в одних случаях нужно писать относительный путь, в других случаях относительный путь в специальной папке, в третьих случаях нужен уже абсолютный путь (например, его получаем этой командой )
Также указано значение параметра , равное: , что позволит создавать карты исходников для js и css файлов.
Для обработки конкретных файлов (по расширению, по месторасположению) в webpack создаются правила в разделе . Сейчас у нас там стоит правило, что все js файлы пропускаем через транслятор Babel, который преобразует наш новомодный ES2015 в стандартный javascript вариант, понятный браузерам.
В нашем тестовом примере мы верстаем наши странице на Boostrap 4. Поэтому нам нужно будет установить три пакета: , , . Второй и третий пакет мы устанавливаем по требованию Bootstrap.
Обратите внимание на то, что эти три пакета нам нужны именно для самого сайта, а не для его сборки. Поэтому эти пакеты мы устанавливаем с флагом , а не
Теперь можно приступить к написанию нашего файла:
В качестве примера пользовательского кода js просто перекрасили цвет текста на синий.
Теперь можно перейти к сборке js файла. Для этого в файле в разделе пропишем следующие npm скрипты:
Теперь при запуске в командной строке строчки npm run dev произойдет сборка проекта (css и html файлы потом также будут собираться этой командой), и в папке появятся файлы и .
При запуске команды npm run build также произойдет сборка проекта, но уже итоговая (с оптимизацией, максимальной минимизацией файла), которую можно выкладывать на хостинг.
При запуске npm run watch запускается режим автоматического просмотра изменений файлов проекта с автоматическим допостроением измененных файлов. Да, чтобы в командной строке отключить этот режим (например, чтобы можно было написать другие команды) можно нажать (как минимум в PowerShell).
При запуске npm run start запустится локальный сервер, который запустит html страницу и также будет отслеживать изменения в файлах. Но пока этой командой не пользуемся, так как сборку html страниц не добавили.
Режим построения проекта создает или переписывает файлы в папке . Но во время разработки проекта при разных сборках файлы могут переименовываться, удаляться. И Webpack не будет следить, чтобы уже ненужные файлы, оставшиеся после предыдущих сборок, удалялись из папки . Поэтому добавим еще один пакет , который будет очищать папку перед каждой сборкой проекта.
Update 2018.04.11. Пришлось отказаться от . Почему? Когда запускаешь сервер через команду (), то webpack компилирует файлы автоматом, не сохраняя их в папку . И это нормально. Но при этом папка очищается из-за наличия . В результате в режиме работы локального сервера папка пустует, что негативно сказывается на работе с git (только в случае, если вы в git репозиторий сохраняется сборку проекта, как и я): после каждого запуска сервера появляется куча изменений из-за удаленных файлов. Было бы хорошо, чтобы очистка папки происходила только при полноценной сборке, например, (об этой команде ниже). Плагин настроить нужным способом не смог. Поэтому использую другой плагин , который не связан с webpack и работает отдельно.
Внесем изменения в файл .
Basic Setup
First let’s create a directory, initialize npm, , and install the (the tool used to run webpack on the command line):
Throughout the Guides we will use blocks to show you what changes we’re making to directories, files, and code. For instance:
Now we’ll create the following directory structure, files and their contents:
project
src/index.js
index.html
We also need to adjust our file in order to make sure we mark our package as , as well as removing the entry. This is to prevent an accidental publish of your code.
package.json
In this example, there are implicit dependencies between the tags. Our file depends on being included in the page before it runs. This is because never explicitly declared a need for ; it just assumes that the global variable exists.
There are problems with managing JavaScript projects this way:
- It is not immediately apparent that the script depends on an external library.
- If a dependency is missing, or included in the wrong order, the application will not function properly.
- If a dependency is included but not used, the browser will be forced to download unnecessary code.
Let’s use webpack to manage these scripts instead.