bundlejs: Онлайновый бандлер на основе esbuild и проверка размера пакета npm

  • Введение
    • Краткое описание возможностей
  • Пакетирование, создание деревьев и минификация
  • Консоль
  • Вкладки ввода и вывода
  • Конфигурация
    • Хосты CDN
    • Алгоритмы сжатия
    • Проблема Brotli
    • По умолчанию используется Gzip
    • LZ4, нужно быстро
    • Качество сжатия
    • Псевдонимы и внешние файлы
    • Опции конфигурации Esbuild
  • Кнопки редактора + дополнительные возможности…
  • Ручки перетаскивания… Интерактивное развлечение
  • Поддержка JSX
  • Совместное использование сессий пакета
  • Анализ пакета
  • Аналитика
  • Обсуждения и поддержка
  • Безопасность и производительность
  • Советы и рекомендации
  • Внести вклад
  • Заключение

Введение

bundlejs (произносится как bundle js) – это быстрый и простой способ древовидной сортировки, пакетирования, минификации и сжатия (в gzip или brotli) ваших проектов typescript, javascript, jsx и npm, получая при этом общий размер файлов пакета.

Цель bundlejs – генерировать более точные оценки размера пакетов, следуя тому же подходу, который используют пакетники:

  • Выполняя все пакеты локально
  • Вывод кода, собранного в трешакене
  • Получение результирующего размера пакета

Преимущества использования bundlejs следующие:

  1. Легче отлаживать ошибки
  2. Вы можете проверить результирующий пакетный код
  3. Возможность конфигурировать свои пакеты
  4. Возможность объединять пакеты в древовидные структуры
  5. Возможность визуального анализа пучков
  6. Вы можете создавать пакеты в автономном режиме (при условии, что модуль уже использовался ранее).
  7. Поддержка различных типов модулей из различных сетей доставки контента (CDN), например, CDN от модулей deno, модулей npm, случайных скриптов github и т.д….

Эта запись в блоге призвана осветить некоторые из наиболее важных изменений, а также дать некоторое представление о том, как bundlejs работает в фоновом режиме, и выступить в качестве документации по bundlejs.

📒Примечание: будет следующая статья, в которой будет подробно описано, как работает bundlejs и как вы можете использовать то, что я узнал из этого проекта, чтобы создать свой собственный онлайн bundler или es build-wasm backed js repl.

😅 TL;DR: эта статья довольно длинная, поэтому сначала загляните на сайт bundlejs.com, а затем прочтите эту статью, обязательно посмотрите изображения и примеры кода, они помогут сократить путаницу и уменьшить время чтения.

Краткое описание функций

В этом видео рассматриваются все основные возможности bundlejs (есть звук, но у меня нет хорошего микрофона 😅)

Пакетирование, Treeshaking и минификация

  • Пакетирование – это процесс эффективного объединения модулей в один файл, который мы называем пакет.
  • Treeshaking – это процесс, в ходе которого компоновщик обходит модули, подлежащие компоновке, и удаляет неиспользуемый код.
  • Минификация – это процесс сокращения объема кода, необходимого для функциональной программы, например, удаление пустого пространства, сокращение имен переменных и т.д…

bundlejs использует esbuild и его невероятные возможности по пакетированию, преобразованию, транспиляции, минификации, древовидности и траверсированию файлов. Точнее, bundlejs использует esbuild-wasm, который способен получить доступ к подмножеству этих возможностей, с ключевыми ограничениями,

  1. npm работает только на node, поэтому нет package.json или npm install (a-la, шутка об использовании StackBlitz WebContainers для запуска node в браузере)
  2. Браузеры работают не так, как nodejs. У них нет простого способа доступа к файловой системе, поэтому хранение и доступ к файлам непрактичны. То, как esbuild обычно работает при установке на node, приводит к проблемам в интернете
  3. из-за ограничений esbuild-wasm при запуске в браузере (нет npm и node nodejs), единственным вариантом является получение модулей из веб, но esbuild не поддерживает импорт http(s)://... модулей, поэтому требуется другое решение.

Для решения каждой из этих проблем на помощь приходит система плагинов esbuild. Я создал в общей сложности 4 плагина для решения этих ограничений, а именно,

  1. HTTP плагин – собирает и кэширует модули
  2. CDN плагин – перенаправляет импорты пакетов npm (иногда называемые “голыми” импортами) на URL-адреса Content Delivery Network (CDN) для извлечения.
  3. EXTERNALS plugin – Помечает определенные импорты/экспорты как модули для исключения из пакета.
  4. ALIAS плагин – Псевдонимы определенных импортов/экспортов для модулей с другим именем

Сети доставки контента (CDN) – это отличный способ распространять код по всему миру с высокой скоростью. В контексте bundlejs, CDN представляют собой онлайн хранилища кода, из которых bundlejs может получать данные.

Например, unpkg.com – это быстрая глобальная сеть доставки контента для всего, что находится на npm. Она используется для быстрой и простой загрузки любого файла из любого пакета на npm с помощью URL, например: https://unpkg.com/package-name@version/file.js, то же самое можно сделать для skypack.dev, esm.sh и т.д..

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

Посмотрите, как влияет treeshaking на размер пакета.

ℹ️ Информация: Это влияние древовидной сортировки и минификации пакета на размер пакета,

treeshaken

против

non-treeshaken

Консоль

В предыдущих версиях bundlejs.com я предлагал разработчикам использовать консоль devtools для просмотра логов консоли, и некоторое время я считал, что это неплохой опыт, но потом я начал понимать, что это неудобно и не очень удобно для мобильных устройств. Изначально я думал, что создание виртуальной консоли будет большой работой, поэтому я довольно долго откладывал добавление пользовательской консоли. И вот в марте этого года, вдохновившись esbuild-repl от @hyrious, я наконец-то сделал это 👏.

Результаты работы консоли

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

Fetching Packages

По умолчанию консоль отображает прогресс выборки пакетов, это часто лучший способ диагностировать ошибки и проблемы, а также найти точки улучшения.

Для некоторых пакетов (например, @babel/core) существует слишком много подпакетов. Если виртуальная консоль будет обрабатывать такое количество журналов, это съест слишком много памяти и/или замедлит работу менее мощных устройств, поэтому я ограничиваю количество журналов до 250, и когда этот предел будет пройден, bundlejs покажет это дружелюбное сообщение,

📒 Примечание: вы все еще можете получить доступ к полному журналу консоли из консоли devtools, даже если виртуальная консоль делает любое усечение.

Вы можете изменить максимальное количество разрешенных журналов в конфигурации через,

{
    "esbuild": {
        "logLimit": 500
    }
}
Ошибки и предупреждения консоли

Ошибки выглядят следующим образом

Предупреждения выглядят следующим образом

Кнопки консоли

Консоли также были снабжены кнопками, чтобы облегчить навигацию по ним, они находятся вот здесь

  • Это кнопка прокрутки к верху. Когда появляются новые журналы консоли, консоль автоматически опускается в самый низ, некоторые пользователи могут посчитать такое поведение раздражающим, поэтому эта кнопка предлагает быстрый и простой выход из ситуации, перемещая пользователя прямо в верхнюю часть консоли.

  • Это кнопка прокрутки к низу. По сути, это кнопка быстрого перехода к нижней части консоли, предназначенная для быстрого просмотра конечного результата свертки.

  • Это кнопка развернуть/свернуть, она быстро разворачивает/свертывает все ошибки и предупреждения, облегчая навигацию по большому набору ошибок.

  • Это кнопка очистки консоли, она очищает консоль от содержимого, оставляя консоль в таком виде,

Дополнительные возможности консоли

Sticky Console: Привязывает позицию прокрутки консоли к низу, для новых журналов. Если вы прокрутите ~50px от низа, это поведение больше не будет применяться, если вы прокрутите обратно к низу, поведение будет применяться снова.

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

Кликабельные ссылки консоли: Как и звучит, кликабельные ссылки консоли выделяют урлы, начинающиеся с http(s)://.... Они функционируют так же, как vscode и devtools, и служат простым способом доступа к урлам консоли без необходимости копировать и вставлять урлы вручную.

У него есть некоторые ограничения, а именно: иногда он с трудом распознает, какие символы являются ссылками, а какие – нет, например.

Я не смог найти пример во время создания этой записи 🤣, когда/если (надеюсь, что это “если”, а не “когда”) я найду его, я обновлю эту запись.

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

Вкладки ввода и вывода

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

Конфигурация

В v0.2 я добавил поддержку пользовательских конфигураций (configs), она поддерживает большинство опций сборки esbuild, а также некоторые дополнительные опции для изменения CDN по умолчанию и алгоритма сжатия.

Конфиг по умолчанию следующий

{
  "cdn": "https://unpkg.com",
  "compression": "gzip",
  "esbuild": {
      "target": [ "esnext"],
      "format": "esm",
      "bundle": true,
      "minify": true,
      "treeShaking": true,
      "platform": "browser"
  }
}

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

{
  "cdn": "https://unpkg.com",
  "compression": "lz4",
  "esbuild": {
      "target": [ "es2018" ],
      ...
  }
}

Приведенная выше конфигурация приведет к такому URL-адресу bundlejs.com/?q=@okikio/animate&config={“compression”: “lz4”, “esbuild”:{“target”:[“es2018”]}}.

Обратите внимание, что cdn отсутствует в URL ресурса, это потому, что bundlejs разумно решает, какой конфиг отправить как часть URL ресурса, основываясь на том, насколько новый конфиг отличается от конфига по умолчанию.

📒 Примечание: Существует 3 алгоритма сжатия, brotli, gzip и lz4.

Хосты CDN

Сети доставки контента (CDN) – это отличный способ распространять код по всему миру с высокой скоростью. В контексте bundlejs, CDN представляют собой онлайн хранилища кода, из которых bundlejs может получать данные.

Например, unpkg.com – это быстрая глобальная сеть доставки контента для всего, что есть на npm. Она используется для быстрой и простой загрузки любого файла из любого пакета на npm с помощью URL, например: https://unpkg.com/package-name@version/file.js, то же самое можно сделать для skypack.dev, esm.sh и т.д..

По умолчанию bundlejs позволяет вам вводить код следующим образом,

export * from "@okikio/animate";
Войти в полноэкранный режим Выйти из полноэкранного режима

Но за кулисами bundlejs автоматически подбирает этот конкретный пакет из CDN, а именно, unpkg.

В старых версиях bundlejs CDN по умолчанию использовался skypack, но поскольку skypack не имеет легкого доступа к package.json пакетов node, я переключился на использование unpkg в качестве CDN по умолчанию.

В более поздних обновлениях bundlejs получил возможность обновлять cdn по умолчанию в глобальном или локальном масштабе.

Технические детали и дополнительная информация…

Вы можете выбирать CDN путем,

  1. (Глобальная CDN) Устанавливая конфигурацию CDN на другой хост CDN, например.

    {
        "cdn": "https://cdn.esm.sh",
        // OR
        "cdn": "skypack"
    }
    
  2. (Локальная CDN) Используя хост CDN в качестве встроенной url-схемы, например.

    export { animate } from "skypack:@okikio/animate"; 
    //                       ^^^^^^^  https://cdn.skypack.dev/@okikio/animate
    

    Всего существует 8 поддерживаемых схем url хостов CDN:

*   `skypack:react` -> [https://cdn.skypack.dev/react](https://cdn.skypack.dev/react)

*   `unpkg:react` -> [https://unpkg.com/react](https://unpkg.com/react)

*   `esm.sh:react` or `esm:react` -> [https://cdn.esm.sh/react](https://cdn.esm.sh/react)

*   `deno:preact` -> [https://deno.land/x/preact](https://deno.land/x/preact)

*   `esm.run:react` -> [https://esm.run/react](https://esm.run/react)

*   `github:facebook/react/main/packages/react/index.js` -> [https://raw.githubusercontent.com/facebook/react/main/packages/react/index.js](https://raw.githubusercontent.com/facebook/react/main/packages/react/index.js)

*   `jsdelivr:react` -> [https://cdn.jsdelivr.net/npm/react](https://cdn.jsdelivr.net/npm/react)

*   `jsdelivr.gh:facebook/react/packages/react-dom/index.js` -> [https://cdn.jsdelivr.net/gh/facebook/react/packages/react-dom/index.js](https://cdn.jsdelivr.net/gh/facebook/react/packages/react-dom/index.js)
Вход в полноэкранный режим Выход из полноэкранного режима

После определения CDN для использования, следующим шагом будет определение того, поддерживает ли CDN хост модули в стиле npm, примерами которых являются unpkg, skypack, esm.sh и т.д..

Факторы, участвующие в определении того, что CDN-хост поддерживает модули стиля npm, заключаются в том, что CDN-хост поддерживает:

  1. CDN поддерживает версионность пакетов через URL-тег @version (например, react@18).

  2. CDN может загружать пакеты узла, файл package.json.

📒 Примечание: Без package.json вы не сможете загружать импорты подпутей, плюс становится сложнее определить правильные экспортируемые модули для комплектации.

⚠️ Предупреждение: Если выбранная CDN не поддерживает файл package.json и это не CDN-хост в стиле npm, то bundlejs переключится на попытку угадать версии пакетов, что может привести к неточным пакетам с неправильными версиями пакетов.

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

Алгоритмы сжатия

bundlejs предлагает варианты пакетирования с использованием:

  1. brotli – приводит к наименьшему размеру пакета, но является самым медленным.
  2. gzip – приводит ко второму наименьшему размеру пакета, но быстрее, чем brotli (по умолчанию)
  3. lz4 – приводит к самому большому размеру пакета, но это самый быстрый алгоритм пакетной обработки

📒 Примечание: Каждый алгоритм сжатия имеет свою собственную историю.

Проблема Brotli

brotli – это алгоритм сжатия, который действительно хорошо сжимает данные, однако он очень медленный по сравнению с другими альтернативами. Добавление brotli было довольно сложной задачей с множеством взлетов и падений, но благодаря Льюису Лю в Twitter я смог использовать deno-brotli для включения WASM-версии brotli в bundlejs.

Узнайте историю поддержки brotli…

Без тени обиды на оригинальных создателей brotli-wasm и wasm-brotli (разные пакеты, похожее название), но то, как оба пакета обрабатывают WASM, заставляет разработчиков использовать webpack (чего не было, я слишком дорожу своим временем для этого), после многочисленных попыток и 6 месяцев работы я наконец нашел deno-brotli.

Пример использования WASM в обоих пакетах (brotli-wasm и wasm-brotli) выглядит следующим образом,

import WASM from "./bg.wasm";
// ...

Честно говоря, мне несправедливо винить создателей brotli-wasm и wasm-brotli, это не их вина. Вина лежит на экосистеме js, которая еще не нашла интероперабельного решения для работы с WASM. Это одна из ключевых причин, по которой я очень благодарен Льюису Лю, указавшему на deno-brotli.

deno-brotli делает две вещи правильно, а именно,

  1. Он сжимает огромный файл WASM, необходимый для deno-brotli в сжатую строку lz4, которая затем может быть распакована lz4, что позволяет легко хранить WASM в виде js-файла (результат – отличная поддержка инструментов сборки, поскольку WASM – это просто строка внутри JS-файла, плюс это очень хорошо решает проблему экосистемы).

    Для поддержки lz4 bundlejs использует deno-lz4, который также работает через WASM, но способ сжатия deno-lz4 немного отличается от deno-brotli. Я бы настоятельно рекомендовал вам взглянуть на исходный код deno-lz4, он очень информативен.

  2. Имея WASM как js файл, вы можете фактически предварительно загрузить WASM как js модуль 🤯.

Вы можете прочитать этот твиттер, чтобы узнать больше,

Окики Оджо
@okikio_dev
Кто-нибудь знает хорошую библиотеку brotli, желательно скомпилированную под WASM?

Кроме того, я пробовал brotli-wasm и wasm-brotli, но способ импорта wasm (с помощью фактического оператора импорта) вызывает кучу ошибок, поэтому мне нужна хорошая альтернатива, которая делает это так, как это делает esbuild.

05:52 AM – 02 Mar 2022

По умолчанию используется Gzip

bundlejs использует gzip по умолчанию уже довольно давно, раньше bundlejs использовал pako, но благодаря обсуждению с @matthewcp, который справедливо указал на (De)compression Stream API, я начал искать альтернативу pako.

Мэтью Филлипс (Matthew Phillips)
@matthewcp
@okikio_dev @deno_land Ооо, есть вот это, developer.mozilla.org/en-US/docs/Web…, хорошо, я попробую использовать и это.
12:06 PM – 15 Mar 2022
Узнайте историю поддержки gzip…

Благодаря разговору с @matthewcp, я действительно провел дополнительное исследование альтернатив pako, у меня есть 3 возможных альтернативы, это denoflate (который использует WASM), deno-compress (который использует js), и CompressionStream (который встроен в браузеры), ура веселье 🎉😅.

В итоге я решил заменить pako на denoflate в качестве алгоритма сжатия по умолчанию для gzip, он немного быстрее и меньше, чем pako.

LZ4, надо быстро

Чтобы использовать WASM в переносимом виде, deno-brotli сжимал двоичный файл WASM в строку base64, используя lz4 в качестве алгоритма сжатия. Я увидел возможность добавить еще один алгоритм сжатия, поэтому я использовал реализацию lz4 (deno-lz4), используемую для сжатия двоичной строки WASM brotli (см. #the-brotli-problem для получения дополнительной информации), это был самый простой алгоритм сжатия для добавления в bundlejs 🤣.

Качество сжатия

Вы можете установить качество сжатия (по шкале от 1 до 11, где 1 – наименьшее сжатие, а 11 – наибольшее), вы можете установить качество сжатия для любого из алгоритмов сжатия, упомянутых выше, установив опцию compression config,

{
    "compression": {
        "type": "brotli",
        "quality": 11
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы можете посмотреть демонстрацию здесь, bundlejs.com/?config={“compression”:{“type”: “brotli”, “quality”:11}}.

Псевдонимы и внешние элементы

Псевдонимы – это способ перенаправления одних пакетов на другие, например, перенаправление fs на memfs, потому что fs не поддерживается в Интернете, и т.д… Это не было прямым запросом на функцию, но я чувствовал, что это было бы хорошим дополнением.

Экстерналы – это прямой запрос функции issue#13, это заняло некоторое время, но хорошее решение наконец-то стало частью bundlejs, вы используете его так же, как вы используете опцию конфигурации esbuild externals.

Подробнее…

Вы используете aliases следующим образом,

{
    "alias": {
        "@okikio/animate": "@babel/core"
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Вы можете попробовать это ниже, bundlejs.com/?config={“alias”:{“@okikio/animate”:”@babel/core”}}.

Вы используете externals следующим образом,

{
    "esbuild": {
        "external": ["@okikio/animate"]
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Вы можете попробовать это ниже, bundlejs.com/?config={“esbuild”:{“external”:[“@okikio/animate”]}}.

Посмотрите сложный пример использования внешнего конфига bundlejs.com/?q=@babel/core&config={“esbuild”:{“external”:[…]}}.

Никто больше не может понять мою боль… Я добавляю все больше возможностей в bundlejs, пока пишу эту статью, так что она становится все длиннее и длиннее, и т.д….. 😅

Опции конфигурации Esbuild

Опции конфигурации esbuild в точности соответствуют своему звучанию, однако, поскольку esbuild работает в браузере, есть некоторые ограничения на то, что может сделать esbuild, из-за отсутствия доступа к встроенной файловой системе некоторые опции не работают или становятся устаревшими.

Поддерживаемые опции сборки esbuild следующие

Простые опции
  • Собрать в пакет
  • Определить
  • Внешний
  • Форматировать
  • Инжектировать
  • Загрузчик
  • Минифицировать
  • Платформа
  • Sourcemap
  • Разделение
  • Цель
Дополнительные опции
  • Анализировать
  • Названия активов
  • Баннер
  • Charset
  • Имена блоков
  • Цвет
  • Капля
  • Имена записей
  • Нижний колонтитул
  • Глобальное имя
  • Игнорировать аннотации
  • Инкрементный
  • JSX
  • Фабрика JSX
  • Фрагмент JSX
  • Сохранять имена
  • Легальные комментарии
  • Уровень журнала
  • Лимит журнала
  • Реквизиты Mangle
  • Метафайл
  • Расширение Out
  • Outbase
  • Публичный путь
  • Чистый
  • Разрешить расширения
  • Корень источника
  • Исходный файл
  • Содержимое источника
  • Stdin
  • Встряхивание дерева
  • Tsconfig raw

Довольно много для работы, я бы сказал.

Кнопки редактора + дополнительные функции…

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

Текущий список кнопок редактора следующий:

Переключение панели редактора

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

Кнопка “Очистить редактор

Очищает редактор от всего его содержимого.

Кнопка форматирования кода

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

Кнопка сброса кода

Возвращает редактор в исходное состояние.

  • Для входного редактора она сбрасывает его в это состояние,

    // Click Build for the bundled, minified and compressed package size
    export * from "@okikio/animate";
    
  • Для редактора вывода – вот так,

    // Output
    
  • Для редактора конфигурации – вот так,

    {
        "cdn": "https://unpkg.com",
        "compression": "gzip",
        "analysis": false,
        "esbuild": {
            "target": [
                "esnext"
            ],
            "format": "esm",
            "bundle": true,
            "minify": true,
            "treeShaking": true,
            "platform": "browser"
        }
    }
    
Кнопка Копировать код

Копирует код редактора, это именно то, что звучит (а чего вы ожидали? 🤣). Когда вы копируете код из редактора с помощью кнопки копирования, появляется это восхитительное сообщение,

Кнопка обернуть код

Переключает между wrapped и unwrapped кодом. Обернуть код – значит заставить код редактора обернуться вокруг ограничений ограничивающего поля редактора, устраняя необходимость горизонтальной прокрутки для просмотра всего кода.

Вот как выглядит wrapped код,

Вот как выглядит развернутый код,

Бонусные возможности

Бонус: Вы можете получить доступ к встроенной палитре команд Monaco, нажав F1, например.

Дополнительный бонус: Вы можете использовать многие из ярлыков кода vscode, просто щелкнув правой кнопкой мыши, находясь в фокусе редактора monaco-, например.

Ручки перетаскивания… Интерактивное развлечение

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

Дружественность bundlejs к мобильным устройствам не является основным направлением проекта, но это приятно иметь, если вы когда-нибудь столкнетесь с необходимостью работы с bundlejs на мобильном или сенсорном устройстве.

Поддержка JSX

JSX теперь официально поддерживается в bundlejs 🎉.

Не обращайте внимания на красные строки ошибок, по какой-то причине редактор кода monaco не хочет работать с JSX 😅.

Для использования JSX вам необходимо установить опции конфигурации jsxFactory и jsxFragment в соответствии с используемым JSX фреймворком.

Например, для Preact будет использоваться следующая конфигурация:

{
    "esbuild": {
        "jsxFactory": "h",
        "jsxFragment": "Fragment"
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Попробуйте демо-версию Preact

Совместное использование сеансов пакета

Для обмена сессиями bundle* между несколькими пользователями (избегая при этом необходимости в сервере) нам нужен статичный и локальный способ хранения и обмена кодом между пользователями. Для решения этой проблемы я решил закодировать информацию о сессиях пакета* прямо в URL, потому что я хотел, чтобы весь проект работал в автономном режиме, и мне не нужны были большие затраты на обслуживание сервера и базы данных.

*Сессии – это конкретное состояние bundlejs в определенное время, это не вся история сессий bundle, а только код ввода и конфигурация bundle на момент нажатия кнопки share.

Технические детали…

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

Пример URL сессии,

/?q=(import)@okikio/emitter,(import)@okikio/animate,(import)@okikio/animate,(import)@okikio/animate,(import)@okikio/animate,@okikio/animate,@okikio/animate,@okikio/animate,@okikio/animate&treeshake=[T],[{ animate }],[{ animate as B }],[ as TR],[{ type animate }],[],[{ animate as A }],[ as PR],[{ animate }]&text="export  as PR18 from "@okikio/animate";nexport { animate as animate2 } from "@okikio/animate";"&share=MYewdgziA2CmB00QHMAUAiAwiG6CUQA&config={"cdn":"skypack","compression":"brotli","esbuild":{"format":"cjs","minify":false,"treeShaking":false}}&bundle
Войти в полноэкранный режим Выйти из полноэкранного режима

Результирующий входной код этого url сеанса связки выглядит следующим образом,

// Click Build for the Bundled, Minified & Compressed package size
import T from "@okikio/emitter";
import { animate } from "@okikio/animate";
import { animate as B } from "@okikio/animate";
import  as TR from "@okikio/animate";
import { type animate } from "@okikio/animate";
export  from "@okikio/animate";
export { animate as A } from "@okikio/animate";
export  as PR from "@okikio/animate";
export { animate } from "@okikio/animate";
console.log("Cool")
export  as PR18 from "@okikio/animate";
export { animate as animate2 } from "@okikio/animate";
Войти в полноэкранный режим Выйти из полноэкранного режима

с конфигурацией,

{
    "cdn": "skypack",
    "compression": "brotli",
    "esbuild": {
        "target": ["esnext"],
        "format": "cjs",
        "bundle": true,
        "minify": false,
        "treeShaking": false,
        "platform": "browser"
    }
}
Ввести полноэкранный режим Выйти из полноэкранного режима

URL-адрес будет следующим,

/?
q=(import)@okikio/emitter,(import)@okikio/animate,(import)@okikio/animate,(import)@okikio/animate,(import)@okikio/animate,@okikio/animate,@okikio/animate,@okikio/animate,@okikio/animate&
treeshake=[T],[{ animate }],[{ animate as B }],[* as TR],[{ type animate }],[*],[{ animate as A }],[* as PR],[{ animate }]&
text="export * as PR18 from "@okikio/animate";nexport { animate as animate2 } from "@okikio/animate";"&
share=MYewdgziA2CmB00QHMAUAiAwiG6CUQA&
config={"cdn":"skypack","compression":"brotli","esbuild":{"format":"cjs","minify":false,"treeShaking":false}}&
bundle
Войти в полноэкранный режим Выйти из полноэкранного режима
  • q или query представляет модуль, например, react, vue и т.д..

    Вы можете добавить (import) перед определенным модулем, чтобы сделать его импортом вместо экспорта

  • treeshake представляет экспорт/импорт в treeshake.

    Синтаксис treeshake позволяет указывать несколько экспортов для каждого пакета, используя следующий синтаксис

    "[{ x,y,z }],[*],[* as X],[{ type xyz }]" 
    // to
    export { x, y, z } from "...";
    export * from "...";
    export * as X from "...";
    export { type xyz } from "...";
    

    Квадратные скобки представляют отдельные пакеты, а все, что находится внутри квадратных скобок, является экспортируемыми методами, типами и т.д..

  • text представляет входной код в виде строки (используется для короткого входного кода).

  • share представляет сжатую строковую версию входного кода (используется для большого входного кода).

  • config представляет конфигурацию пакета для использования при сборке пакета

  • bundle указывает bundlejs собирать входной код в пакет при запуске. По умолчанию эта функция не включена из соображений безопасности. Я хочу отговорить людей от отправки больших сложных пакетов, которые разрушают браузеры или требуют много времени для загрузки, особенно до того, как входной код будет должным образом проверен на отсутствие вредоносного кода. Поэтому, если вы хотите упаковывать код при запуске, вам придется вручную добавить &bundle в конец url.

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

Анализ пакета

bundlejs может анализировать и визуально представлять пакеты в виде простых в навигации и понятных графиков.

Используя порт esbuild-visualizer и rollup-plugin-visualizer от @bardadymchik я добавил возможность визуализации пучков, эта возможность появилась благодаря просьбе @atomiks в issue#22, вопрос все еще открыт, вы можете вносить предложения по улучшению этой возможности.

Графики анализа пучков отображаются прямо под редактором, как показано ниже,

Отображаемые графики имеют 3 различных вида:

Трехмерная диаграмма

Диаграммы Treemap – это наиболее запоминающаяся форма диаграммы анализа пучков. Вдохновением для создания этой диаграммы послужил webpack-bundle-analyzer. webpack-bundle-analyzer является родоначальником анализаторов пучков и вдохновил bundlejs на создание диаграмм.

Диаграммы в виде карты,

  1. Помогают понять, что на самом деле находится внутри вашего пакета,
  2. Выяснить, какие модули составляют большую часть его размера.
  3. Найти модули, которые попали туда по ошибке
  4. Оптимизируйте его!

Источник: github.com/webpack-contrib/webpack-bundle-analyzer

Источник: github.com/webpack-contrib/webpack-bundle-analyzer

Хотя карта-схема bundlejs менее мощная, чем карта-схема webpack-bundle-analyzer, она проще и быстрее в использовании (bundlejs использует esbuild, а анализ связок легко доступен онлайн).

Сетевая диаграмма

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

Диаграмма солнечных лучей

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

Диаграммы всплеска солнца используют круговые диаграммы для представления размеров пучков, это помогает понять, какую часть от общего размера пучка занимают определенные модули.

Технические детали …

📒 Примечание: Все диаграммы анализа поддерживают размеры пакетов в gzipped и brotli сжатом виде! При анализе пакета он будет выбирать либо gzip, либо brotli, основываясь на типе сжатия.

Например,

{ 
  "compression": "gzip" 
}

будет использовать сжатие gzip для графиков, в результате чего,

Аналитика

Когда я изначально создавал проект, я использовал только простой счетчик просмотров страниц, я хотел посмотреть, насколько популярен проект, не нарушая приватности пользователей, это работало, но я чувствовал, что это может быть лучше, поэтому я решил использовать umami в качестве альтернативы Google Analytics, сохраняющей приватность, без кукинга, с открытым исходным кодом, в которой аналитика является общедоступной для всех желающих.

Дополнительные детали…

Для bundlejs используется самораспространяемая версия umami, чтобы обеспечить конфиденциальность и безопасность пользовательских данных. При попытке настроить self-hosted версию umami мне очень помогла статья Настройка Umami с Vercel и Supabase от Jakob Bouchard.

Аналитика находится в открытом доступе, проверьте ее по адресу analytics.bundlejs.com/share/bPZELB4V/bundle

Или нажмите на счетчик посещений страниц

📒Примечание: bundlejs все еще использует счетчик просмотров страниц, счетчик просмотров работает на countapi (насколько мне известно, countapi сейчас устарел, однако серверы проекта все еще работают, так что я буду продолжать использовать проект, пока не перейду на использование umami для просмотров страниц и общей аналитики).

Настройка Umami с помощью Vercel и Supabase

Jakob Bouchard ・ Feb 2 ’21 ・ 5 min read

#аналитика #firstpost #webdev #учебник

Обсуждения и поддержка

Для поощрения обсуждений, поддержки и получения отзывов я добавил в bundlejs раздел комментариев, для этого я использовал giscus.

Изначально, когда я создал проект bundlejs, я также создал для него обсуждение на GitHub. Я не хотел иметь накладные расходы на управление сервером Discord, поэтому я выбрал GitHub Discussions для чатов о bundlejs. Проблема в том, что никто не использует GitHub Discussions, поэтому я интегрировал его прямо в сам сайт через giscus, чтобы новые пользователи могли легко взаимодействовать с другими, получать от меня поддержку и оставлять отзывы.

Технические детали…

giscus – это система комментариев с открытым исходным кодом на базе GitHub Discussions, она позволяет посетителям оставлять комментарии и отзывы на вашем сайте через GitHub! Она была в значительной степени вдохновлена utterances.

Для bundlejs я использую self-hosted версию giscus, в основном по соображениям безопасности. При попытке настроить giscus для bundlejs, документация по самостоятельному хостингу на репозитории GitHub очень полезна, я настоятельно рекомендую всем, кто думает использовать giscus, прочитать ее, она дает представление о том, как giscus работает на бэкенде.

Вы можете проверить интегрированные комментарии giscus по ссылке bundlejs.com/#discus.

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

Безопасность и производительность

Безопасность и производительность – критические области качества для bundlejs. Для того чтобы связать модули вместе, bundlejs должен получить множество наборов модулей со всего интернета, при этом гарантируя, что в процесс не будут вовлечены злоумышленники, и что esbuild-wasm не будет использован для сбоя других устройств.

Некоторые действительно… действительно большие модули могут занимать до 4+ GB памяти, чтобы быть правильно упакованными esbuild-wasm.

Критерии безопасности, которые я установил для bundlejs, были следующими:

  1. Не сливать личную информацию пользователя.
  2. Не проходить через центральный сервер, например, возможность получать модули узла из различных источников.
  3. Гарантировать, что люди всегда знают, какие пакеты они собирают.
  4. Убедиться, что люди не могут использовать bundlejs для злонамеренного замедления работы браузеров.

Для обеспечения соответствия установленным критериям безопасности,

  1. Я использую строгие политики безопасности содержимого (CSP) для bundlejs, гарантируя, что никакая непреднамеренная третья сторона не может быть вовлечена.

  2. Я самостоятельно размещаю как можно больше сторонних скриптов. Ограждая количество рук, вовлеченных в работу с bundlejs.com, я снижаю вероятность утечки личной информации.

  3. Я использую техники песочницы, например, Web Workers и Shared Workers, чтобы обеспечить работу основного потока на плавной скорости 60fps, избегая при этом доступа к DOM.

    Web Workers и Shared Workers – это скрипты, которые выполняются в отдельном потоке. Используя Workers, я могу изолировать потенциально вредоносный код, гарантируя, что основной поток не пострадает.

    Большинство случаев использования Workers – это Shared Workers. Shared Workers уменьшает влияние на производительность нескольких экземпляров сайта/веб-приложения bundlejs, запущенных на одном устройстве.

  4. Чтобы уменьшить вероятность использования bundlejs для злонамеренного замедления работы браузеров, я гарантирую, что URL общего ресурса легко читается и понимается, и по умолчанию отключаю автоматическое связывание для URL общего ресурса.

Текущая ситуация с поддержкой браузерами Shared Worker в лучшем случае нестабильна.

Таблица поддержки выглядит следующим образом,

Браузер Общие рабочие Рабочие модули
Firefox Да Нет
Chrome Да Да
Safari Да* Да

* Поддержка Safari в настоящее время является экспериментальной, но должна появиться в последующих версиях.

Module Workers – это esmodules, которые запускаются в Workers.

📒 Примечание: Я создал Shared Worker полифилл @okikio/sharedworker. Это небольшой, но простой полифилл, который возвращается к обычному Web Worker, если Shared Worker не поддерживается. Вы можете использовать его в ожидании следующей версии Safari, поддерживающей Shared Workers, или при поддержке старых версий Safari.

⚠️ Предупреждение: Shared Worker polyfill не работает с рабочими модулями, вам все равно придется как-то компилировать ваши модули в не-esm версии для поддержки рабочих модулей в Firefox. Вы можете посмотреть, как bundlejs обрабатывает рабочие модули в исходном коде bundlejs, вы также можете посмотреть исходный код astro-repl, чтобы увидеть, как он обрабатывает рабочие модули.

Большинство других политик безопасности пассивны по своей природе, например.

  • bundlejs выполняет пакетирование только при загрузке страницы, если URL содержит ?bundle.
  • bundlejs принудительно использует https:// для всех запросов, включая iframe и т.д….
  • По умолчанию для bundlejs используются только проверенные CDN-хосты.
  • и т.д.

Советы и рекомендации

Главный совет – следите за мной (@okikio_dev) и bundlejs (@jsbundle) на twitter; бессовестная реклама 🤣.

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

  • При упаковке пакетов, которые также экспортируют CSS и другие внешние файлы, bundlejs.com теперь проверяет размер gzip/brotli этих внешних файлов, однако, он не выводит код внешних файлов, это поведение может измениться в будущем, но пока я придерживаюсь именно такого подхода. Помните, что это не ошибка, однако, если это вызывает путаницу, я готов изменить это поведение.

  • Treeshaking доступен, но не все CDN поддерживают доступ к каждому пакету package.json, поэтому возможны небольшие конфликты версий пакетов. Единственной проверенной CDN с доступом к package.json является https://unpkg.com. Другие CDN, которые используются, либо предварительно упаковывают код для нас (это происходит в зависимости от пакета), либо они не являются полными npm CDN, например, https://deno.land или https://raw.githubusercontent.com.

  • Проверьте полную консоль devtools на наличие сообщений об ошибках и предупреждений, если у вас возникли проблемы с отладкой в bundlejs, а еще лучше включите esbuilds verbose logging при попытке отладить проблемы, например.

    {
        "esbuild": {
            "logLevel": "verbose"
        }
    }
    

    Проверьте демо-версию.

  • Вы можете использовать пользовательские протоколы, чтобы указать, какие конкретные CDN должен использовать модуль импорта/экспорта. Если возникает ошибка, из-за которой вы не можете правильно упаковать пакет, я настоятельно рекомендую сменить CDN либо с помощью пользовательских протоколов, либо изменив параметр конфигурации cdn. Я рекомендую использовать пользовательские протоколы вместо опции конфигурации cdn при попытке отладки проблем с CDN:

    например

    {
        "cdn": "unpkg"
    }
    

    или

    export * from "unpkg:typescript";
    

    Попробуйте использовать пользовательские протоколы для решения этой проблемы на bundlejs.

  • Для некоторых пакетов возникает программная ошибка, когда экспорт по умолчанию исключается из пакета treeshaken, решение для этого – вручную включить экспорт по умолчанию, как показано ниже,

    export * from "skypack:solid-dismiss";
    // and
    export { default } from "skypack:solid-dismiss";
    

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

Вклад

В настоящее время кодовая база довольно дезорганизована, поэтому я бы предложил написать мне в Twitter или начать обсуждение на GitHub, чтобы обсудить способы внесения вклада.

В проекте bundlejs происходит очень много событий, и это может быть очень подавляющим, если вы думаете, что можете внести свой вклад, пожалуйста, сделайте это! Со временем я напишу подробную документацию о том, как вносить вклад и как все работает в бэкенде, с нетерпением жду этого.

Вы можете использовать готовое окружение Gitpod dev для быстрого начала работы с проектом или для внесения быстрых изменений в проект.

Если вам понравится проект, я буду рад, если вы распространите информацию о нем. Моя цель – сделать bundlejs жизнеспособной альтернативой/заменой bundlephobia и даже локальных бандлеров, но сейчас проект настолько мал, что большинство людей, которым он был бы полезен, не знают о нем. Я был бы рад увидеть людей, использующих его.

И последнее замечание: bundlejs сейчас находится на OpenCollective, так что если вы хотите внести финансовый вклад в проект, это будет оценено по достоинству.

Заключение

bundlejs – это быстрый и простой способ древовидной сортировки, пакетирования, минификации и сжатия (в gzip или brotli) ваших проектов typescript, javascript, jsx и npm, получая при этом общий размер файлов пакетирования.

Цель bundlejs – генерировать более точные оценки размера пакетов, следуя тому же подходу, который используют пакетники:

  • Выполняя все пакеты локально
  • Вывод кода, собранного в трешакене
  • Получение результирующего размера пакета

Преимущества использования bundlejs следующие:

  1. Легче отлаживать ошибки
  2. Вы можете проверить результирующий пакетный код
  3. Возможность конфигурировать свои пакеты
  4. Возможность объединять пакеты в дерево
  5. Возможность просматривать визуальный анализ пучков
  6. Вы можете создавать пакеты в автономном режиме (при условии, что модуль уже использовался ранее).
  7. Поддержка различных типов модулей из различных сетей доставки контента (CDN), например, CDN от модулей deno, модулей npm, случайных скриптов github и т.д….

В следующий раз, когда вам понадобится собрать проект в пакет или вам нужно будет узнать размер пакета проекта, попробуйте воспользоваться bundlejs.com.

📒Примечание: В продолжении этой статьи будет описано, как работает bundlejs и как вы можете использовать то, что я узнал из этого проекта, для создания своего собственного онлайн бандлера или esbuild-wasm backed js repl.


Фото Okiki Ojo, изображение можно найти на Dropbox.

Первоначально опубликовано на blog.okikio.dev

Также опубликовано на Hackernoon и dev.to

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