Отказ от ответственности: если вы здесь только для руководства и части кода, прокрутите до «разработка» и пропустите вступление, это круто, без обид, я тоже был там.

Пролог

По-видимому, статические веб-сайты сейчас в моде.

Я не был удивлен, прочитав твиты или сообщения в блогах о том, как технологическая компания ‹randomcoolcompanyname› использовала Gatzby.js поверх GraphQL для отображения целевой страницы, которая отображалась как 30 слов (которые НИКОГДА не меняются), взятых из CMS Wordpress, обернутых вокруг. Laravel и так далее.
Я к этому привыкаю, многие люди любят вызовы, и когда их нет, они создают их сами, из ниоткуда.

Чего я совсем не ожидал, так это найти в LinkedIn описание работы для компании здесь, в Италии, где JAMstack был указан как требование, «хорошо бы иметь» знания.
Я спросил. сам «что такое JAMstack? Является ли новый стек MEAN? Это значит как Java… Angular… Ммммм… Mongo?».

Нет, совсем нет, цитата с их веб-сайта JAMstack гласит: Современная архитектура — создавайте быстрые и безопасные сайты и динамические приложения с помощью JavaScript, API и предварительно обработанной разметки, обслуживаемые без веб-серверов.
Это… создание статических веб-сайтов.

В тот момент я был как

Почему мы создаем статические веб-сайты в первую очередь? Мы снова возвращаемся? Вы помните, как мы «вернулись» от одностраничного приложения к рендерингу на стороне сервера, потому что фактический HTML-рендеринг на сервере (как это было раньше) был отчасти полезен?

В любом случае, несмотря на первоначальный шок, эта новая тенденция действительно удовлетворила мое любопытство, и я спросил себя: «Как бы я создал статический веб-сайт в конце 2019 года?»

Ответ очень прост: мне просто нужен HTML и один файл CSS, я даже добавлю файл JS, чтобы создать переключаемое меню без использования некоторых хаков с флажками. .
Это все, что мне нужно, теперь я могу начать добавлять некоторые усложнения, которые мне бы хотелось иметь.

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

Та же концепция может быть применена при создании статического веб-сайта (ну, на самом деле ее можно применить ко всей индустрии разработки программного обеспечения, но давайте придерживаться этого случая): ваше движение представлено тремя файлами, перечисленными выше (html, js и css), вам нужно получить содержимое из отдельного файла? Это осложнение. Вам нужно использовать пре- или постпроцессоры для CSS? Еще одно осложнение. Вам нужно использовать babel для переноса краевого javascript? Вы угадали, тоже осложнение.

Итак, возвращаясь к моему первоначальному вопросу, первое, что нужно сделать, это перечислить особенности (сложности), которые должен иметь процесс сборки, которые, я думаю, того стоят:

  • Я хотел бы сохранить содержимое веб-сайта в отдельном файле от фактического HTML, чтобы в будущем это содержимое можно было легко изменить или, например, получить из API;
  • Я хочу, чтобы мой CSS подвергался предварительной и последующей обработке, чтобы я мог писать SASS и мне не нужно было запоминать все префиксы CSS3 для некоторых правил;
  • Я хочу использовать ESM в своих файлах javascript;
  • Я хочу, чтобы весь мой код был минимизирован перед его отправкой в ​​производство.

Следующим шагом является поиск способа реализации этих функций наилучшим образом.

Что лучше?
Что ж, для меня "лучше" это когда код чистый, не хакерский, он использует библиотеки и модули так, как они должны.
Это когда через 6 месяцев я снова открою проект, чтобы внести изменения, и это не сведет меня с ума.
Это когда коллега может взять код и сразу приступить к работе, потому что движение, которое я сделал (придерживаясь аналогии), простое, понятное, интуитивно понятное и не требует двухчасового объяснения, наполненного сожалениями, слезами. и обвинять.

Единственный необходимый здесь инструмент называется Laravel Mix, я использовал его в паре проектов, и он меня очень впечатлил, так что давайте посмотрим на него вместе.

Разработка

Laravel Mix, цитируя их веб-сайт, является «элегантной оболочкой Webpack для 80% случаев использования».

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

Во-вторых, это слой, который устраняет единственную плохую вещь в веб-пакете ИМХО: собирает вместе все необходимые части, чтобы заставить его работать правильно с различными типами файлов и задачами, как в этом случае.

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

Это структура проекта:

/* PROJECT STRUCTURE */
dist/  #static build folder, the one that goes to the server
  assets/ #assets
    index.css #main .css
    index.js #main .js
    index.js.gz
    index.css.gz
  index.html
  about.html
  contacts.html

src/ #source files folder
  data/ #contents folder
    homepage.json #homepage contents
    about.json #about page contents
    contacts.json #contacts page contents
  scripts/ #javascript sources here
    index.js
  styles/ #scss sources here
    index.scss
  views/ #template engine sources
    partials/
      _header.ejs
      _footer.ejs
    index.ejs
    contacts.ejs
    about.ejs

package.json
package-lock.json
webpack.mix.js // main config file

Как видите, я выбрал EJS в качестве шаблонизатора по нескольким причинам:

  • он поддерживается в Laravel Mix «из коробки» с помощью приятного и удобного плагина;
  • он чертовски прост в использовании, так что мне не нужно тратить много времени на изучение того, как он работает, или быть особенно осторожным с синтаксисом (кому-нибудь pug/jade?).

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

Как вы, возможно, заметили, на самом деле существует два конвейера, один для разработки и один для производства, потому что каждая среда имеет разные потребности. Вы можете проверить, находитесь ли вы в производственном режиме с помощью mix.inProduction().

  • .setPublicPath('dist/') используется для создания манифеста, который может быть полезен для кеша ресурсов с SPA или Laravel, он в основном отслеживает, какой отпечаток имеет ваш index.css (или как вы его называете) в текущем построить, чтобы вы могли синхронизировать его в html. По правде говоря, я им не пользуюсь, я сделал отпечаток с отметкой времени и отправил его в контекст шаблонизатора. Причина, по которой я все равно оставил эту функцию, заключается в том, что в противном случае файл манифеста создается в корне проекта, и мне это не нравится. Проверьте https://laravel-mix.com/docs/5.0/versioning для получения дополнительной информации.
  • .js('src/scripts/index.js', 'dist/assets') Это объединяет весь ваш javascript в один файл, применяя встряхивание деревьев и, при запуске в рабочем режиме, минимизацию вывода.
  • .sass('src/styles/index.scss', 'dist/assets') Предварительно обрабатывает весь код SASS и компилирует его в CSS, а также добавляет для вас все префиксы CSS3 и, если выполняется в рабочем режиме, минимизирует код тоже.
  • .ejs('src/views', 'dist', contents, { rmWhitespace: true, partials: 'src/views/partials' }) Компилирует шаблоны EJS в фактический HTML, вам просто нужно указать исходную папку, выходную папку, контекст и параметры ejs. Здесь я указал игнорировать папку partials, так как я не хочу, чтобы она компилировалась вместе с фактическими страницами и удаляла пробелы.
  • .browserSync({ server: 'dist', proxy: null }) Мне это нужно только в процессе разработки, оно создает фактический веб-сервер, который обслуживает указанную папку, а также обновляет ваш браузер при изменении любого из исходных файлов. Да, я имею в виду, это синхронизация браузера, вы, наверное, уже это знаете...
  • .webpackConfig({ plugins: [ new CleanWebpackPlugin(), new CompressionPlugin() ] }) Этот шаг полезен для производственного режима, он удаляет папку dist/, чтобы убедиться, что все чисто и свежо, и создает gzip версия ваших активов, поэтому вашему nginx не нужно будет делать это на лету.

Ну вот и все, если вы следили за страницей установки на веб-сайте Laravel Mix, вы уже знаете, как ее запустить или сделать производственную сборку, но в любом случае просто скопируйте это в свой package.json.

"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}

watch — для разработки, prod — для производства (ни хрена, Шерлок).

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

Если вам понравился пост, подпишитесь и оставьте лайк… нет, подождите, здесь мы этого не делаем.

О счастливого Хэллоуина!