Snowpack: высокопроизводительный инструмент для сборки внешнего интерфейса

Это один из способов, с помощью которого Snowpack делает разработку приятной и быстрой Программирование и разработка

В этой статье мы впервые взглянем на Snowpack, в частности на Snowpack 3, который на момент написания был только что выпущен. Snowpack — это интерфейсный инструмент для сборки, который привлекает много внимания в сообществе за то, что предлагает подход, отличный от таких инструментов, как webpack, и я некоторое время стремился проверить его.

История инструментов сборки

Прежде чем мы перейдём к Snowpack, нам нужно быстро понять, как и почему появились такие бандлеры, как webpack. Отсутствие в JavaScript модульной системы до модулей ES2015 означало, что в браузере мы могли ближе всего к модулям разделить наш код на файлы, которые помещают код в глобальную область видимости, поскольку именно так мы делили его между файлами. Часто можно было увидеть такой код:

window.APP = {}

window.APP.Authentication = {...}
window.APP.ApiLoader = {...}

Когда появился и завоевал популярность Node.js, у него была модульная система в виде CommonJS:

const Authentication = require('./Authentication.js')
const APILoader = require('./APILoader.js')

Как только это стало популярным как часть Node, люди захотели использовать его в браузере. Именно тогда начали появляться инструменты, которые это сделали; они могли взять приложение, использующее модули CommonJS, и связать его в один большой файл JavaScript requireс удалением всех s, который можно было запустить в браузере. Browserify был первым подобным инструментом, который я использовал для этого, и, честно говоря, это было похоже на волшебство! Это было примерно в то время, когда появился веб-пакет, и другие инструменты также поддерживались с использованием CommonJS.

Когда модули ES были впервые представлены (см. » Основные сведения о модулях ES6 ″ для освежения ), люди очень хотели их использовать, но возникли две проблемы:

  1. Пока была сделана спецификация, браузеры не поддерживали модули ES.
  2. Даже если браузер действительно поддерживает модули ES, вы, вероятно, всё равно захотите объединить их в производственную среду, потому что для загрузки всех модулей, если они определены как отдельные файлы, требуется время.
Читайте также:  Как получить длину массива в Java?

Webpack (и другие) обновлены для поддержки модулей ES, но они всегда будут объединять ваш код в один файл как для разработки, так и для производства. Это означало, что типичный рабочий процесс:

  1. Отредактируйте файл в своём приложении.
  2. Webpack проверяет, какой файл был изменён, и выполняет повторное объединение вашего приложения.
  3. Вы можете обновить страницу в браузере и увидеть изменения. Часто это делается за вас с помощью плагина webpack, такого как горячая перезагрузка модуля.

Проблема здесь заключается на втором этапе, когда ваше приложение увеличивается в размере. Работа веб-пакета по обнаружению изменения файла и последующему выяснению того, какие части вашего приложения следует повторно объединить в основной пакет, может занять время, а в больших приложениях это может вызвать серьёзное замедление. Вот где приходит Snowpack…

Подход снежного покрова

Ключевым аргументом в пользу Snowpack для меня является эта строка из их документации:

Snowpack обслуживает ваше приложение отдельно во время разработки. Каждый файл нужно построить только один раз, а затем навсегда кэшировать. Когда файл изменяется, Snowpack восстанавливает этот единственный файл.

Snowpack в полной мере использует преимущества модулей ES, которые поддерживаются всеми основными браузерами, и не объединяет ваше приложение в разработку, а вместо этого обслуживает каждый модуль как отдельный файл, позволяя браузеру импортировать ваше приложение через модули ES. См. » Использование модулей ES в браузере сегодня » для получения более подробной информации о браузерах и их поддержке несвязанных модулей ES.

На этом этапе важно отметить, что вы должны использовать модули ES для использования Snowpack. Вы не можете использовать CommonJS в своём приложении.

Однако возникает вопрос: что, если вы установите зависимость от npm, которая использует CommonJS? Хотя я надеюсь, что в один прекрасный день большинство пакетов npm будет поставляться как модули ES, мы всё ещё довольно далеко от этого, и в действительности даже если вы создаёте приложение исключительно в модулях ES, весьма вероятно, что в какой-то момент вы мне понадобится зависимость, созданная на CommonJS.

К счастью, Snowpack справится и с этим! Когда он видит зависимость (скажем, React) в вашей node_modulesпапке, он может объединить только эту зависимость в свой собственный мини-пакет, который затем можно импортировать с помощью модулей ES.

Надеюсь, вы понимаете, почему Сноупак привлёк моё внимание. Давайте запустим его и посмотрим, каково это использовать в приложении.

Начало

Для начала я создаю новую пустую папку проекта и запускаю её, npm init -yчтобы начать работу. Это создаёт основу, package.jsonкоторую я могу продолжить и отредактировать позже, если захочу. Вы также можете работать npm initбез -y, что заставит npm предложить вам ответить на вопросы, чтобы заполнить данные в вашем package.json. Мне нравится использовать, -yчтобы быстро приступить к работе; Я могу отредактировать package.jsonпозже.

Затем я устанавливаю Snowpack как зависимость разработчика:

npm install --save-dev snowpack

А теперь добавляю в свой два скрипта package.json:

"scripts": {
  "start": "snowpack dev",
  "build": "snowpack build"
},

Это устанавливает нам две npm runкоманды:

  • npm run start запустит Snowpack в режиме разработки.
  • npm run build запустит производственную сборку Snowpack, о которой мы поговорим позже.

Когда мы запускаем наше приложение, Snowpack запускает небольшой сервер разработки, который будет запускать наше приложение локально. Он будет искать index.htmlфайл, поэтому давайте создадим один из них, а также создадим app.js, который пока просто будет регистрироваться hello worldв консоли:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Snowpack testing</title>
</head>
<body>

  <script src="./app.js"></script>
</body>
</html>
console.log('hello world')

Теперь мы можем запускать npm run start(или npm startдля краткости — startэто один из методов жизненного цикла npm, для которого не нужно ставить префиксrun ).

Вы должны увидеть, что вывод вашего терминала выглядит примерно так:

snowpack

  http://localhost:8080 • http://172.18.33.234:8080
  Server started in 80ms.

▼ Console

[snowpack] Hint: run "snowpack init" to create a project config file. Using defaults...
[snowpack] Nothing to install.

Первая часть вывода сообщает нам, что Snowpack работает localhost:8080. Следующая строка предлагает нам создать файл конфигурации Snowpack, что мы и сделаем в ближайшее время, но это последняя строка, которую я хочу выделить:

[snowpack] Nothing to install.

Это Snowpack, говорящий нам, что он проверен на наличие каких-либо модулей npm, с которыми нужно иметь дело, и не нашёл ни одного. Через мгновение мы добавим пакет npm и посмотрим, как с ним справляется Snowpack.

Создание файла конфигурации

Вы можете запустить, npx snowpack initчтобы сгенерировать файл конфигурации, как предлагает вывод командной строки. Нам не нужно будет изменять поведение Snowpack, пока мы не перейдём к комплектации для производственной среды, но если вы это сделаете, вы можете создать этот файл и настроить широкий спектр параметров, чтобы Snowpack работал так, как вы хотите.

Написание в модулях ES

Давайте создадим ещё один файл JavaScript, чтобы увидеть, как Snowpack работает с несколькими файлами. Я создал api.js, который экспортирует функцию, которая принимает имя пользователя и извлекает некоторые из их публичных репозиториев из GitHub:

export function fetchRepositories(user) {
  return fetch(`https://api.github.com/users/${user}/repos`)
    .then(response=> response.json());
}

Затем в app.js, мы можем импортировать и использовать эту функцию. Не стесняйтесь заменить моё имя пользователя GitHub своим собственным!

import {fetchRepositories} from './api.js';
fetchRepositories('jackfranklin').then(data => console.log(data));

Сохраните этот файл и снова запустите Snowpack, если вы не оставляли его запущенным ранее. В консоли браузера вы увидите ошибку:

Uncaught SyntaxError: Cannot use import statement outside a module

Это из-за нашего <script> тега в нашем HTML-файле:

<script src="./app.js"></script>

Поскольку модули ES ведут себя немного иначе, чем код, который не использует модули ES, браузеры не могут просто начать поддерживать модули ES во всех скриптах. Это почти наверняка приведёт к поломке некоторых существующих веб-сайтов, и одна из основных целей JavaScript состоит в том, чтобы любые новые функции были обратно совместимы. В противном случае каждая новая функция JS может сломать тысячи существующих веб-сайтов!

Для того, чтобы использовать ES модули, всё, что нам нужно сделать, это сказать, что браузер, давая scriptтег typeиз module:

<script type="module" src="./app.js"></script>

И когда вы сохраните это, ваш браузер должен автоматически обновиться (ещё одна приятная вещь, которую Snowpack делает из коробки), и вы увидите список репозиториев GitHub, зарегистрированных в консоли.

Установка зависимостей npm

Давайте посмотрим, как Snowpack справляется с установкой пакета из npm. Я собираюсь вывести наш список репозиториев на экран с помощью Preact. Для начала установим:

npm install --save preact

Чтобы проверить, что он работает, я обновлю app.jsрендеринг Hello worldна экране:

import {fetchRepositories} from './api.js';
import {h, render} from 'preact';

fetchRepositories('jackfranklin').then(data => {
  render(h('p', null, 'Hello world'), document.body);
});

Обратите внимание, что я использую hпомощник для создания HTML, а не JSX. Я делаю это из соображений скорости, чтобы запустить пример. Чуть позже в этой статье мы перейдём на JSX и посмотрим, как Snowpack справится с этим, так что держитесь крепче.

Теперь, когда мы запустим npm start, Snowpack выведет это:

[snowpack] ! building dependencies...
[snowpack] ✔ dependencies ready! [0.33s]

Вы можете видеть, что он нашёл Preact и создал комплект модулей ES, готовый для использования. Если вы посмотрите на вкладку «Сеть» инструментов разработчика, вы увидите запрос к app.js, api.jsи preact.js, который является файлом Snowpack, созданным для нас из зависимости Preact. Что хорошо в подходе Snowpack, так это то, что теперь он создаёт этот файл Preact, он кэширует его и меняет его только в случае изменения Preact. Учитывая, что Preact является зависимостью, мы, вероятно, не собираемся менять его регулярно, поэтому ему не придётся делать эту работу часто. Это один из способов, с помощью которого Snowpack делает разработку приятной и быстрой.

Это один из способов, с помощью которого Snowpack делает разработку приятной и быстрой

Поддержка JSX

Snowpack имеет хорошую поддержку ряда синтаксисов и типов файлов из коробки. Он поддерживает JSX, но с одним условием: весь JSX должен быть определён в.jsxфайлах. Вы можете изменить это, если хотите (подробности смотрите в документации), но мне всегда нравилось использовать.jsx. Давайте создадим новый JSX-файл, содержащий наш компонент Preact repo-list.jsx:

import {h} from 'preact';

export function RepoList(props) {
  return <ul>{props.repos.map(repo => {
    return <li><p>{repo.name}</p></li>
  })}</ul>
}

Обратите внимание, что, несмотря на то, что мы не вызываем hпомощника напрямую, нам необходимо импортировать его, чтобы Snowpack не предполагал, что мы используем React.

Теперь app.jsмы можем отрендерить наш компонент:

import {h, render} from 'preact';
import {fetchRepositories} from './api.js';
import {RepoList} from './repo-list.jsx';

fetchRepositories('jackfranklin').then(data => {
  render(h(RepoList, { repos: data }, null), document.body);
});

И у нас есть список репозиториев на экране.

Производственные постройки

На момент написания производственная сборка Snowpack не объединяет и не минимизирует все ваши файлы в один пакет, как вы могли ожидать. Это объясняется далее в руководстве по производственной сборке Snowpack, но особенность Snowpack — быть инструментом многофайловой сборки ES-модулей, а не полным сборщиком пакетов. На момент написания Snowpack работает над предоставлением встроенного пакета через esbuild, но в документации указано, что это всё ещё очень экспериментально и не следует полагаться на большие проекты.

Вместо этого рекомендуется использовать другой пакет, для которого Snowpack предоставляет плагины:

  • Плагин Webpack.
  • Плагин Rollup.

Обратите внимание, что вам не нужно вручную устанавливать другой сборщик. Это плагины Snowpack, которые вы можете настроить в файле конфигурации Snowpack. Затем Snowpack позаботится о вызове webpack / Rollup, чтобы вы связали приложение при запуске snowpack build.

Связка с Webpack

Вскоре мы рассмотрим встроенную поддержку сборщика esbuild в Snowpack, но на данный момент использование одного из этих подключаемых модулей является простым решением, а также рекомендуемым подходом. Давайте настроим плагин Snowpack для веб-пакетов, чтобы минимизировать наш код при сборке для производства. Сначала мы его установим:

npm install --save-dev @snowpack/plugin-webpack

Вам также понадобится файл конфигурации, поэтому запустите npx snowpack init(если вы ещё этого не сделали), чтобы сгенерировать файл конфигурации, в котором мы можем настроить плагин webpack для производственных сборок.

В snowpack.config.jsсделайте так, чтобы pluginsэлемент выглядел так:

plugins: [
  ['@snowpack/plugin-webpack', {}]
],

Пустой объект — это то место, где вы можете разместить любые дополнительные параметры конфигурации, хотя он должен работать нормально из коробки. Теперь, когда мы запустим npm run build, Snowpack распознаёт, что мы добавили плагин веб-пакета и соответствующий пакет, создав оптимизированный миниатюрный пакет, который мы можем отправить.

Одна из приятных вещей, которые предоставляет webpack «из коробки», — это удаление мёртвого кода, также известное в сообществе JavaScript как «встряхивание дерева», чтобы избежать включения кода, который не требуется, в наш окончательный пакет.

Мы можем убедиться в этом сами, если экспортируем и определим функцию, в api.jsкоторой никогда не используем:

export function fetchRepositories(user) {
  return fetch(`https://api.github.com/users/${user}/repos`)
    .then(response=> response.json());
}

export function neverUsed() {
  console.log('NEVER CALLED')
}

Если мы запустим npm run buildеще раз, а затем загрузим наш миниатюрный вывод (он будет в build/jsкаталоге и вызван app.[hash].js), мы увидим, что если мы будем искать файл ’NEVER CALLED’, он не будет включён. Webpack был достаточно умён, чтобы понять, что мы никогда не вызывали эту функцию, поэтому её можно удалить из окончательного вывода.

Сборка с esbuild

Чтобы получить представление о том, как может выглядеть будущее, когда поддержка esbuild в Snowpack будет улучшена, а сама esbuild станет более готовой к производству (см. Документацию по esbuild для более подробной информации об esbuild и её дорожной карте), давайте настроим это. Сначала удалите всю конфигурацию плагина webpack из вашего snowpack.config.jsфайла и вместо этого добавьте optimizeобъект:

plugins: [
],
optimize: {
  bundle: true,
  minify: true,
  target: 'es2018',
  treeshake: true,
},

Теперь, когда вы запустите npm run build, esbuild возьмёт на себя и выполнит последние шаги по оптимизации, создав build/app.jsполностью минифицированную версию. Он также удаляет мёртвый код, как и webpack, поэтому наша neverUsed()функция не попала в финальную сборку.

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

Заключение

Snowpack предложил мне фантастический опыт разработчика, и мне очень захотелось попробовать его ещё раз в другом проекте. Я знаю, что в этой статье мы использовали Preact, но Snowpack поддерживает множество других библиотек, включая React, Svelte и многие другие, которые вы можете найти в документации на веб-сайте.

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

Оцените статью
bestprogrammer.ru
Добавить комментарий