Webpack сейчас в моде. Он имеет более 30 000 звезд на GitHub и был принят некоторыми крупными орудиями в мире JavaScript, такими как React и Angular.
Однако вам не нужно работать над масштабным проектом, чтобы воспользоваться Webpack. Webpack — это, прежде всего, пакет, и в качестве такового вы также можете использовать его для объединения практически любого ресурса или актива, о которых вы хотите подумать.
В этой статье я собираюсь показать вам, как установить и настроить Webpack, а затем использовать его для создания минимизированного пакета для простого статического сайта с несколькими активами.
Но почему вы хотите это сделать?
Хороший вопрос. Рад, что ты спросил!
Одной из основных причин для этого является минимизация количества HTTP-запросов, которые вы делаете на сервер. По мере роста средней веб-страницы вы, вероятно, будете включать jQuery, пару шрифтов, несколько плагинов, а также различные таблицы стилей и немного собственного JavaScript. Если вы делаете сетевой запрос для каждого из этих ресурсов, все скоро складывается, и ваша страница может стать вялой. Однако если вы включите все вышеперечисленное в один пакет, эта проблема исчезнет.
Webpack также позволяет легко минимизировать ваш код, еще больше уменьшая его размер, и позволяет вам писать ваши ресурсы в любом вкусе. Например, в этой статье я покажу, как заставить Webpack переносить ES6 в ES5. Это означает, что вы можете писать JavaScript, используя самый последний, самый современный синтаксис (хотя это может еще не полностью поддерживаться), а затем обслуживать браузеры ES5, которые будут работать практически везде.
И, наконец, это веселое учебное упражнение. Независимо от того, используете ли вы какие-либо из этих методов в своих собственных проектах, зависит от вас, но, следуя инструкциям, вы получите четкое представление о том, что делает Webpack, как он работает и подходит ли он вам.
Встать и бежать
Первое, что вам нужно, это установить Node и npm на ваш компьютер. Если у вас еще нет Node, вы можете загрузить его с веб-сайта Node или загрузить и установить с помощью менеджера версий . Лично я предпочитаю этот второй метод, так как он позволяет переключаться между несколькими версиями Node и сводит на нет кучу ошибок прав доступа, которые в противном случае могли бы привести к установке пакетов Node с правами администратора.
Нам также понадобится каркасный проект для работы. Вот тот, который я сделал ранее . Чтобы запустить его на вашем компьютере, вы должны клонировать проект из GitHub и установить зависимости.
git clone https://github.com/sitepoint-editors/webpack-static-site-example cd webpack-static-site-example npm i
Это установит jQuery , плюс Slick Slider и Lightbox2 — два плагина, которые мы будем использовать на сайте — в папку node_modules
в корне проекта.
После этого вы можете открыть index.html
в вашем браузере и перейти на сайт. Вы должны увидеть что-то вроде этого:
Если вам нужна помощь в выполнении любого из вышеперечисленных шагов, почему бы не заглянуть на наши форумы и оставить вопрос .
Представляем Webpack в проекте
Следующее, что нам нужно сделать, это установить Webpack. Мы можем сделать это с помощью следующей команды:
npm i webpack --save-dev
Это установит Webpack и добавит его как devDependency
в ваш файл package.json
:
"devDependencies": { "webpack": "^3.2.0" }
Далее мы dist
папку dist
которая будет содержать наш встроенный JavaScript.
mkdir dist
Теперь мы можем попробовать запустить Webpack из командной строки, чтобы проверить, правильно ли он настроен.
./node_modules/webpack/bin/webpack.js ./src/js/main.js ./dist/bundle.js
Что я делаю здесь, так это говорю Webpack, чтобы он src/js/main.js
содержимое src/js/main.js
в dist/bundle.js
. Если все установлено правильно, вы должны увидеть что-то вроде этого в командной строке:
Hash: 1856e2c19ecd9b2d9026 Version: webpack 3.2.0 Time: 50ms Asset Size Chunks Chunk Names bundle.js 2.67 kB 0 [emitted] main [0] ./src/js/main.js 192 bytes {0} [built]
А Webpack создаст файл bundle.js
в папке dist
. Если вы посмотрите на этот файл в выбранном вами текстовом редакторе, вы увидите набор шаблонов и содержимое main.js
внизу.
Автоматизация нашей установки
Теперь, если бы нам приходилось вводить все вышеперечисленное в терминал каждый раз, когда мы хотели запустить Webpack, это было бы довольно неприятно. Итак, давайте создадим скрипт npm, который мы сможем запустить.
В package.json
измените свойство scripts
чтобы оно выглядело так:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack ./src/js/main.js ./dist/bundle.js" },
Обратите внимание, как мы можем не указывать полный путь к модулю Webpack, поскольку при запуске из скрипта npm автоматически ищет модуль в папке node_modules
. Теперь, когда вы запускаете npm run build
, должно произойти то же самое, что и раньше Круто, а?
Создайте файл конфигурации Webpack
Заметьте, как мы передаем путь файла к пакету и путь к выходному файлу в качестве аргументов для Webpack? Что ж, мы, вероятно, должны изменить это и указать их в файле конфигурации . Это облегчит нашу жизнь, когда мы позже будем использовать загрузчики.
Создайте файл webpack.config.js
в корне проекта.
touch webpack.config.js
И добавьте следующий код.
module.exports = { entry: './src/js/main.js', output: { path: __dirname + '/dist', filename: 'bundle.js' } }
И измените скрипт npm следующим образом:
"scripts": { ... "build": "webpack" },
В webpack.config.js
мы указываем точку входа и выходное местоположение пакета в качестве свойств объекта конфигурации, который мы затем экспортируем. Запустите все снова и все должно работать как прежде.
Включая комплект
Теперь у нас есть Webpack, генерирующий пакет для нас, следующее, что нам нужно сделать, это включить его куда-нибудь. Но сначала давайте создадим другую точку входа, чтобы мы могли на самом деле требовать main.js
Это будет файл с именем app.js
в app.js
src/js
.
touch src/js/app.js
Добавьте следующее в app.js
:
require('./main.js');
И измените конфигурацию webpack следующим образом:
entry: './src/js/app.js',
Запустите npm run build
снова, чтобы воссоздать пакет. Все должно работать как раньше.
Теперь, если вы посмотрите на index.html
вы заметите, что с JavaScript мало что происходит. В нижней части файла мы main.js
jQuery и файл с именем main.js
, который отвечает за отображение дополнительной информации, когда вы нажимаете ссылку Подробнее ….
Давайте отредактируем index.html, чтобы он включал пакет вместо main.js
Посмотрите на нижнюю часть файла. Тебе следует увидеть:
<script src="./node_modules/jquery/dist/jquery.min.js"></script> <script src="./src/js/main.js"></script> </body> </html>
Измените это на:
<script src="./node_modules/jquery/dist/jquery.min.js"></script> <script src="./dist/bundle.js"></script> </body> </html>
Обновите страницу в браузере и убедитесь, что ссылка Подробнее … все еще работает.
Пакетирование JQuery.
Далее давайте добавим jQuery в комплект. Это уменьшит количество HTTP-запросов, которые делает страница. Для этого мы должны изменить файл app.js
следующим образом:
window.$ = require('jquery'); require('./main.js');
Здесь нам требуется jQuery, но, поскольку мы установили его с помощью npm, нам не нужно указывать полный путь. Мы также добавляем его обычный псевдоним $
к глобальному объекту window
, чтобы он был доступен для других сценариев.
Измените index.html
чтобы удалить тег сценария jQuery:
<script src="./dist/bundle.js"></script> </body> </html>
Запустите npm run build
и еще раз обновите страницу в браузере, чтобы убедиться, что ссылка Подробнее … все еще работает. Оно делает? Хорошо!
Пакетирование CSS
Глядя на index.html
единственное, что мы делаем для сетевого запроса — это CSS. Как вы можете видеть, мы main.css
вверху страницы, и этот файл, в свою очередь, импортирует еще четыре CSS-файла.
Хотя в своей стандартной конфигурации Webpack может работать только с JavaScript, мы можем использовать так называемый загрузчик, чтобы он также связывал наш CSS. Из документов Webpack :
Загрузчики — это преобразования, которые применяются к исходному коду модуля. Они позволяют вам предварительно обрабатывать файлы при их импорте или «загружать» их. Таким образом, загрузчики являются своего рода «задачами» в других инструментах сборки и предоставляют мощный способ обработки шагов сборки переднего плана. Загрузчики могут преобразовывать файлы с другого языка (например, TypeScript) в JavaScript или встроенные изображения в виде URL-адресов данных. Загрузчики даже позволяют вам делать такие вещи, как импорт файлов CSS прямо из ваших модулей JavaScript!
Итак, давайте изменим app.js
:
// CSS require('../css/main.css'); // JavaScript window.jQuery = window.$ = require('jquery'); require('./main.js');
И нам нужно изменить webpack.config.js
чтобы сообщить ему, какой загрузчик запускать, когда он встречает файл, заканчивающийся на .css
:
module.exports = { ... module: { loaders: [ { test: /\.css$/, loaders: [ 'style-loader', 'css-loader' ] } ] } }
Как видите, я указал два загрузчика: css-loader и style-loader . Из них css-loader преобразует CSS в модуль JavaScript, а style-loader внедряет CSS, который экспортируется модулем JavaScript, в тег <style> во время выполнения. Давайте установим оба:
npm i --save-dev css-loader style-loader
Теперь давайте снова запустим Webpack с помощью npm run build
и посмотрим, что произойдет.
Hash: 3699b503299ce447108d Version: webpack 3.2.0 Time: 409ms Asset Size Chunks Chunk Names bundle.js 289 kB 0 [emitted] [big] main [1] ./src/js/app.js 97 bytes {0} [built] [2] ./src/css/main.css 1.01 kB {0} [built] [3] ./node_modules/css-loader!./src/css/main.css 494 bytes {0} [built] [4] ./node_modules/css-loader!./src/css/fonts.css 353 bytes {0} [built] [5] ./src/fonts/open-sans/OpenSans-ExtraBold.ttf 271 bytes {0} [built] [failed] [1 error] [6] ./node_modules/css-loader!./src/css/layout.css 219 bytes {0} [built] [7] ./node_modules/css-loader!./src/css/styles.css 1 kB {0} [built] [8] ./node_modules/css-loader!./src/css/responsive.css 359 bytes {0} [built] [12] ./src/js/main.js 192 bytes {0} [built] + 4 hidden modules ERROR in ./src/fonts/open-sans/OpenSans-ExtraBold.ttf Module parse failed: /home/jim/Desktop/webpack-static-site-example/src/fonts/open-sans/OpenSans-ExtraBold.ttf Unexpected character '' (1:0) You may need an appropriate loader to handle this file type. (Source code omitted for this binary file) @ ./node_modules/css-loader!./src/css/fonts.css 6:131-183 @ ./node_modules/css-loader!./src/css/main.css @ ./src/css/main.css @ ./src/js/app.js
О нет! Что произошло? Изучив вывод, кажется, что в src/css/fonts.css
. Если вы откроете этот файл и посмотрите на строку 5, вы увидите, что мы src/fonts/open-sans/OpenSans-ExtraBold.ttf
пользовательский шрифт ( src/fonts/open-sans/OpenSans-ExtraBold.ttf
), и Webpack не знает, что с ним делать.
Но не волнуйтесь, у нас это есть! Нам просто нужно использовать другой загрузчик. На этот раз url-загрузчик , который может конвертировать ресурсы, такие как шрифты и изображения, в URL-адреса данных , которые затем можно добавить в пакет:
module.exports = { ... module: { loaders: [ { test: /\.css$/, loaders: [ 'style-loader', 'css-loader' ] }, { test: /\.ttf$/, loaders: [ 'url-loader' ] } ] } }
И, конечно же, нам нужно установить его:
npm install url-loader --save-dev
Теперь сборка должна работать. Протестируйте вещи, удалив CSS include, воссоздав комплект и обновив страницу.
Объединение сторонних библиотек
Теперь давайте photos.html
наше внимание на photos.html
. На этой странице происходит нечто большее, поскольку мы используем две библиотеки, Slick Slider и Lightbox2, обе из которых основаны на jQuery. К счастью, мы можем применить методы, которые мы изучили, чтобы включить их в комплект.
Измените app.js
следующим образом:
// CSS require('slick-carousel/slick/slick.css') require('slick-carousel/slick/slick-theme.css') require('lightbox2/dist/css/lightbox.min.css') require('../css/main.css'); // JS window.$ = require('jquery'); window.slick = require('slick-carousel'); window.lightbox = require('lightbox2'); require('./main.js')
Также удалите CSS include из заголовка документа, а скрипт include из нижнего колонтитула. Это должно дать нам:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>I Can Haz Cheeseburger?</title> </head> <body> ... <script src="dist/bundle.js"></script> <script> $('.slick-slider').slick({ dots: true, arrows: false, infinite: true, speed: 500, fade: true, cssEase: 'linear' }); </script> </body> </html>
Хотя ничто не помешает нам включить код инициализации Slick в комплект, я оставлю его на этой странице, так как мы хотим использовать его только здесь.
Теперь давайте запустим Webpack и посмотрим, что произойдет:
ERROR in ./node_modules/slick-carousel/slick/ajax-loader.gif Module parse failed: /home/jim/Desktop/webpack-static-site-example/node_modules/slick-carousel/slick/ajax-loader.gif Unexpected character '' (1:7) You may need an appropriate loader to handle this file type. (Source code omitted for this binary file) @ ./node_modules/css-loader!./node_modules/slick-carousel/slick/slick-theme.css 6:119-147 @ ./node_modules/slick-carousel/slick/slick-theme.css @ ./src/js/app.js ERROR in ./node_modules/slick-carousel/slick/fonts/slick.eot Module parse failed: /home/jim/Desktop/webpack-static-site-example/node_modules/slick-carousel/slick/fonts/slick.eot Unexpected character '' (1:0) You may need an appropriate loader to handle this file type. (Source code omitted for this binary file) @ ./node_modules/css-loader!./node_modules/slick-carousel/slick/slick-theme.css 6:309-337 6:362-390 @ ./node_modules/slick-carousel/slick/slick-theme.css @ ./src/js/app.js
Оу нет, еще одна ошибка! На этот раз, похоже, проблема с файлом slick-theme.css
который ссылается на изображение в формате gif. Webpack не знает, что делать с GIF, поэтому он вскидывает руки и перестает работать. Но мы знаем, что делать, верно?
Добавьте следующее в webpack.config.js
:
{ test: /\.(svg|gif|png|eot|woff|ttf)$/, loaders: [ 'url-loader' ] }
Вы заметите, что я изменил регулярное выражение, чтобы соответствовать нескольким другим типам файлов. Все это требуется Slick или Lightbox2. Запустите Webpack снова и убедитесь, что он завершается без ошибок.
Обновите страницу и убедитесь, что все работает.
Некоторые штрихи.
Мы почти закончили, но есть пара вещей, которые мы можем улучшить.
Обработка флеш-содержимого из стиля
Вы заметили вспышку нестандартного контента при загрузке страницы? Это можно исправить, воспользовавшись блокирующей природой тегов <script> и переместив include в верхнюю часть файла.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>I Can Haz Cheeseburger?</title> <script src="dist/bundle.js"></script> </head> <body> ... </body> </html>
Минимизируйте Пакет
Мы также можем запустить Webpack с флагом p
(сокращенно для производства ) и сделать так, чтобы он все минимизировал для нас.
В package.json
:
"scripts": { ... "build": "webpack -p" },
В webpack.config.js
:
module.exports = { entry: './src/js/app.js', output: { path: __dirname + '/dist', filename: 'bundle.min.js' }, module: { ... } }
И в index.html
и photos.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>I Can Haz Cheeseburger?</title> <script src="./dist/bundle.min.js"></script> </head> <body> ... </body> </html>
Это уменьшает размер пакета до 480 КБ. Это может показаться немного чрезмерным для некоторых CSS, JS и некоторых других ресурсов, но имейте в виду, что 222kb этого шрифта.
Transpile ES6 для ES5
Вы также можете установить babel-загрузчик, и через него Webpack запускает файлы JavaScript, таким образом перенося ES6 в ES5.
npm install babel-core babel-loader babel-preset-es2015 --save-dev
В webpack.config.js
:
{ test: /\.js$/, loader: 'babel-loader?presets[]=es2015' },
Конечно, вы можете заменить ES6 практически любым другим языком компиляции, который вам нравится.
Вывод
Так что у вас есть это. В этой статье я продемонстрировал, как использовать Webpack для объединения простого статического сайта — процесса, который уменьшает количество запросов HTTP, тем самым делая сайт потенциально более быстрым и отзывчивым. Я также продемонстрировал, как заставить Webpack минимизировать полученный пакет, тем самым значительно уменьшая размер файла, а также переносить ES6 с помощью babel-загрузчика.
Даже если эта стратегия не для всех, надеюсь, следуя этой инструкции, вы получите представление о том, что делает Webpack и как он это делает. А для тех, кто хочет изучить Webpack дальше, я рекомендую Руководство для начинающих по Webpack 2 и комплектации модулей , которое немного углубленнее.
Если у вас есть какие-либо вопросы или комментарии, я был бы рад услышать их в обсуждении ниже.