Статьи

Как создать простой статический сайт с помощью Webpack

Webpack сейчас в моде. Он имеет более 30 000 звезд на GitHub и был принят некоторыми крупными орудиями в мире JavaScript, такими как React и Angular.

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

В этой статье я собираюсь показать вам, как установить и настроить Webpack, а затем использовать его для создания минимизированного пакета для простого статического сайта с несколькими активами.

Но почему вы хотите это сделать?

Читать современный JavaScript
Будьте в курсе развивающегося мира JavaScript

Хороший вопрос. Рад, что ты спросил!

Одной из основных причин для этого является минимизация количества 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 и комплектации модулей , которое немного углубленнее.

Если у вас есть какие-либо вопросы или комментарии, я был бы рад услышать их в обсуждении ниже.