Esbuild — это новое поколение фронтенд-конструкторов, которые все еще могут так играть!
Всем привет, сегодня я представляю вам введение и практику, связанную с Esbuild, надеюсь, она вас вдохновит.
Что такое Эсбилд?
Esbuild — это инструмент для создания пакетов, разработанный техническим директором Figma «Эваном Уоллесом» на основе Golang.По сравнению с традиционными инструментами для создания пакетов он фокусируется на преимуществах в производительности и может создавать в 10–100 раз быстрее.
Архитектурное преимущество
1. Разработка Голанга
Разработанный на языке Go, по сравнению с однопоточными языками + JIT-интерпретируемыми языками, преимущества использования Go заключаются в следующем:
- С одной стороны, вы можете в полной мере использовать многопоточную упаковку и обмениваться контентом между потоками, а JS должен иметь накладные расходы на обмен потоками (postMessage), если вы используете многопоточность;
- С другой стороны, он напрямую компилируется в машинный код, вместо того, чтобы анализировать JS-код в байт-код и затем преобразовывать его в машинный код, такой как Node, что значительно экономит время работы программы.
2. Многоядерный параллелизм
Алгоритм внутренней упаковки полностью использует преимущества многоядерных процессоров. Внутренний алгоритм ESBUILD разработан таким образом, чтобы максимально использовать преимущества всех ядер ЦП. Все шаги максимально параллельны, чему также способствуют преимущества многопоточного совместного использования памяти при GO, а все шаги в JS можно только сериализовать. Данные для перетаскивания
3. Создайте колесо с нуля
Создавайте колеса с нуля, без какой-либо логики черного ящика сторонних библиотек, чтобы обеспечить максимальную производительность кода.
4. Эффективное использование памяти
Вообще говоря, данные AST часто анализируются и передаются в традиционных инструментах упаковки, разработанных JS, таких как строка -> TS -> JS -> строка, которая каждый раз включает сложные цепочки инструментов компиляции, такие как webpack -> babel -> terser. открывается новая цепочка инструментов, AST необходимо повторно анализировать, что приводит к большому объему памяти. В Esbuild копия данных узла AST максимально повторно используется от начала до конца, что значительно повышает эффективность использования памяти и повышает производительность компиляции.
Сравните с SWC
скорость
Давайте использовать чистый Esbuild и SWC для компиляции кода, как Transformer для преобразования 800+ файлов tsx, без написания какого-либо связующего кода JS (например, esbuild-register, esbuild-loader, сам swc-loader, чтобы адаптироваться к соответствующим хост-инструменты, напишу кучу связующего кода JS, влияющего на суждение).
| Esbuild | SWC | TSC | |
|---|---|---|---|
| первый раз | 138 ms | 217 ms | 8640 ms |
| второй раз | 154 ms | 206 ms | 8400 ms |
| в третий раз | 142 ms | 258 ms | 8480 ms |
| средний | 144.7 ms | 227 ms | 8507 ms |
| скорость, отнимающая много времени | x1 | x 1.58 | x 58.8 |
Из этого примера видно, что Esbuild и SWC находятся на одном порядке по производительности.Пример через склад здесь немного быстрее, чем Esbuild, но нельзя исключать, что SWC немного быстрее, чем Esbuild в других примерах .
совместимость
Ограничения самого Esbuild включают следующее:
- Нет проверки типа TS
- Невозможно манипулировать AST
- Синтаксис декоратора не поддерживается
- Продуктовую цель нельзя понизить до ES5 и ниже.
Это означает, что сценарии, требующие артефактов ES5, не могут быть реализованы только с помощью Esbuild.
Напротив, SWC имеет лучшую совместимость:
- Продукт поддерживает формат ES5
- Поддержка синтаксиса декоратора
- AST можно манипулировать, написав плагины JS.
Сценарии применения
Что касается Esbuild и SWC, мы много раз сравниваем их производительность и игнорируем сценарии приложений. Для фронтальных строительных инструментов существует несколько вертикальных функций:
- Bundler
- Transformer
- Minimizer
Из приведенного выше сравнения скорости и совместимости видно, что Esbuild и SWC имеют такую же производительность, как и трансформаторы, но совместимость с Esbuild намного меньше, чем у SWC. Поэтому SWC лучше в качестве трансформера.
Но, как Bundler и Minimizer, SWC кажется слишком тонким.Во-первых, официальный swcpack в настоящее время практически недоступен, а Minimizer также очень незрелый, и легко столкнуться с проблемами совместимости.
В качестве Bundler Esbuild был использован Vite в качестве предварительно упакованного инструмента на этапе разработки в этапе разработки, а также широко используется в качестве онлайн-сервиса ESM CDN, например,esm.shИ так далее; как минимизатор, Esbuild также достаточно зрел, чтобы его можно было использовать в производстве Vite в качестве инструмента сжатия для кода JS и CSS.
В целом отношения между SWC и Esbuild аналогичны нынешним Babel и Webpack, первый больше подходит для兼容性а также自定义Трансформеры с высокими требованиями (например, мобильные бизнес-сценарии), которые подходят для Bundler и Minimizer, и兼容性а также自定义Трансформатор с низкими требованиями.
Механизм плагина
esbuildПлагин — это объект, который содержитnameа такжеsetupдва свойства,nameэто название плагина,setup— это функция, входной параметр — это объект сборки, и к этому объекту монтируются некоторые хуки, чтобы мы могли настроить некоторую логику построения. Ниже приведен простойesbuildПример плагина:
let envPlugin = {
name: 'env',
setup(build) {
// 文件解析时触发
// 将插件作用域限定于env文件,并为其标识命名空间"env-ns"
build.onResolve({ filter: /^env$/ }, args => ({
path: args.path,
namespace: 'env-ns',
}))
// 加载文件时触发
// 只有命名空间为"env-ns"的文件才会被处理
// 将process.env对象反序列化为字符串并交由json-loader处理
build.onLoad({ filter: /.*/, namespace: 'env-ns' }, () => ({
contents: JSON.stringify(process.env),
loader: 'json',
}))
},
}
require('esbuild').build({
entryPoints: ['app.js'],
bundle: true,
outfile: 'out.js',
// 应用插件
plugins: [envPlugin],
}).catch(() => process.exit(1))
Используйте следующим образом:
*// 应用了env插件后,构建时将会被替换成process.env对象*
import { PATH } from 'env'
console.log(`PATH is ${PATH}`)
Тем не менее, при написании плагинов следует помнить о нескольких вещах:
-
Механизм плагина Esbuild работает только на
buildAPI, не дляtransformAPI, что означает, что загрузчик esbuild в веб-пакете, который использует только функцию преобразования Esbuild, не может использовать преимущества механизма подключаемого модуля Esbuild. -
в плагине
filterРегуляризация реализована с помощью встроенной в go регуляризации для фильтрации файлов, чтобы не сильно снижать производительность, правила должны быть максимально строгими. В то же время он также отличается от обычных JS, таких как просмотр вперед (? -
Фактические плагины должны учитывать индивидуальное кэширование (уменьшает накладные расходы на дублирование нагрузки), слияние исходной карты (источники отображаются правильно) и обработку ошибок. может относиться кSvelte plugin.
Поддержка виртуальных модулей
По сравнению с накопительным пакетом
Упаковщику обычно требуются две формы модулей: один существует в файловой системе реального диска, а другой находится не на диске, а в памяти, то есть виртуальный модуль. Сам Rollup, естественно, поддерживает виртуальные модули.Основываясь на своем механизме подключаемых модулей, Vite также активно использует функцию виртуальных модулей.В качестве примера возьмем обработку файлов wasm:
const wasmHelperId = '/__vite-wasm-helper'
// helper 函数实现
const wasmHelper = async (opts = {}, url: string) => {
// 省略具体实现
}
export const wasmPlugin = (config: ResolvedConfig): Plugin => {
return {
name: 'vite:wasm',
resolveId(id) {
if (id === wasmHelperId) {
return id
}
},
async load(id) {
if (id === wasmHelperId) {
return `export default ${wasmHelperCode}`
}
if (!id.endsWith('.wasm')) {
return
}
const url = await fileToUrl(id, config, this)
// 虚拟模块
return `
import initWasm from "${wasmHelperId}"
export default opts => initWasm(opts, ${JSON.stringify(url)})
`
}
}
}
Но виртуальные модули Rollup также имеют некоторые ограничения: чтобы отличить их от реальных модулей, по соглашению по умолчанию перед путем пишется '\0'. Это сделает путь в определенной степени навязчивым, а импорт напрямую в браузер вызовет проблемы (Vite также\0заменить__xxэту форму, чтобы не приводить непосредственно\0Путь ставится в импорт браузера):
Поддержка виртуальных модулей в Esbuild более дружелюбная, прямо различая реальные модули и виртуальные модули через пространство имён, так что не будет\0Это хакерская операция.
Возможность компиляции
Используя виртуальный модуль Esbuild, вы можете выполнить множество функций.В дополнение к вычислению значения env в памяти как содержимого модуля в приведенном выше экземпляре плагина вы также можете использовать имя модуля в качестве функции для компиляции, и вы может даже реализовать рекурсию функций на этапе компиляции. Например, этот плагин Esbuild:
{
name: 'fibo',
setup(build) {
build.onResolve({ filter: /^fib\(\d+\)/ }, args => {
return { path: args.path, namespace: 'fib' }
})
build.onLoad({ filter: /^fib\(\d+\)/, namespace: 'fib' }, args => {
const match = /^fib\((\d+)\)/.exec(args.path);
n = Number(match[1]);
console.log(n);
let contents = n < 2 ? `export default ${n+1}` : `
import n1 from 'fib(${n - 1})'
import n2 from 'fib(${n - 2})'
export default n1 + n2`
return { contents }
})
}
}
С помощью этого плагина можно анализировать следующие операторы импорта:
import fib5 from 'fib(5)'
console.log(fib5)
// 13
Все модули являются виртуальными модулями и не существуют в реальной файловой системе.
Кроме того, импорт URL также может быть выполнен с помощью виртуальных модулей, и поддерживаются следующие коды импорта:
import React from 'https://esm.sh/react@17'
Это также может быть реализовано в плагинах, см.Пример.
сцена приземления
1. Инструмент сжатия кода
Функция сжатия кода Esbuild очень хороша, и она может сократить разрыв в производительности более чем на порядок по сравнению с традиционными инструментами сжатия. Vite также официально объявил в версии 2.6, что может напрямую использовать Esbuild для сжатия кода JS и CSS в производственной среде.
2. Вместо ц-узла
У сообщества уже есть соответствующий план esno:github.com/antfu/esno
ts-node index.ts
// 替换为
esno hello.ts
3. Вместо ц-шутки
использоватьesbuild-jestзаменятьts-jest, попробуйте использовать esbuild-jest как трансформер в крупномасштабном проекте.По сравнению с ts-jest общая эффективность теста улучшена примерно в 3 раза.Таймозатратное сравнение до и после выглядит следующим образом:
Адрес на гитхабе:GitHub.com/Ааа Праджня/ESB…
4. Сборщик сторонних библиотек
В Vite Esbuild используется для предварительной упаковки зависимостей на этапе разработки, а все используемые сторонние зависимости преобразуются в продукты Bundle формата ESM, и в будущемПланирование использования в производственной среде.
В то же время в отрасли также есть несколько платформ, которые предоставляют онлайн-сервисы cjs -> esm CDN на основе чистого Esbuild, такие какesm.sh а такжеskypack:
5. Упаковка библиотеки узла
Почему вы хотите упаковать библиотеку Node:
- Сократите код node_modules, избегайте установки большого количества кода node_modules в бизнесе и уменьшите объем установки.
- Увеличьте скорость запуска, все коды записываются в один файл, что сокращает количество операций файлового ввода-вывода.
- безопаснее. Вся упаковка кода также является способом блокировки версии зависимостей, что позволяет избежать проблемы зависания крупномасштабной CI, вызванной предыдущим пакетом coa.эта статья.
В этом отношении роль Esbuild аналогична текущему ncc, созданному командой vercel, но есть некоторые ограничения на написание кода, и он не может анализировать динамическое требование или оператор импорта, содержащий переменные:
6. Компиляция небольшой программы
Для сценариев с небольшими программами вместо Webpack также можно использовать Esbuild, что значительно повышает скорость компиляции.Для преобразования AST подключаемый модуль Esbuild встроен в SWC для обеспечения быстрой компиляции. Подробности см. в разделе 132.производство на esbuild.
7. Веб-строительство
Веб-сцена более сложная, а требования к совместимости и экологии окружающих инструментов относительно высоки, например, низкое понижение синтаксиса браузера, прекомпилятор CSS, HMR и т. д. Если вы хотите использовать для этого чистый Esbuild, вам нужно добавить много возможностей.
Ранее студенты Sanyuan внедрили набор каркасов веб-разработки на основе Esbuild.ewas, был открыт поставлен на Github, и успешно приземлился на мой предыдущийБрошюра проектаСреди них по сравнению сcreate-react-appБолее чем в 100 раз более быстрый запуск (30s -> 0.3s). Адрес склада:GitHub.com/ternary0704…
сейчасRemix 1.0Официально выпущенный нижний слой построен с помощью Esbuild, который обеспечивает максимальную производительность и становится сильным конкурентом Next.js.
Но в целом у Esbuild по-прежнему много возможностей для реальных веб-сценариев, и есть еще некоторые недостатки, в том числе синтаксис, который не поддерживает даунгрейд до ES5, негибкая распаковка и отсутствие поддержки HMR.Впереди еще долгий путь. с точки зрения инструментов.
использованная литература
[1] Svelte plugin: *ES build.GitHub.IO/plugins/#SV…
[2] Пример плагина: *ES build.GitHub.IO/plugins/#contracts…
[3] GitHub.com/Вите есть/Вите…
[4] sm.sh : *esm.sh/
[5] kypack: *www.skypack.dev/
[6] Производство на esbuild: *zhuanlan.zhihu.com/p/408379997
[7] ewas: GitHub.com/ternary0704…
[8] Пункты буклета:GitHub.com/ternary0704…
[9] Remix 1.0: remix.run/