Инструмент упаковки нового поколения esbuild

Vue.js
Инструмент упаковки нового поколения esbuild

предисловие

Студенты, которые обеспокоены базовой реализацией «Vite», я думаю, должно быть ясно, что он использует «esbuild» для достижения.ts,jsx,.jsпреобразование кода. Конечно, более раннее использование «esbuild» до «Vite» было «Snowpack». Однако по сравнению с огромным сообществом, которое есть у «Vite», ясно, что «Snowpack» привлекает меньше внимания.

Ядро «Vite» основано на собственном браузере.ES Module. Однако по сравнению с традиционными инструментами упаковки и инструментами разработки в него внесено множество изменений, использующих «esbuild» для поддержки.ts,jsx,.jsПреобразование кода является одним из них.

Итак, давайте перейдем к сегодняшней теме, Что такое esbuild и как им пользоваться?

1 Что такое esbuild

Официальное введение «esbuild»: это «JavaScript»BundlerИнструмент упаковки и сжатия, который может упаковывать и распространять код «JavaScript» и «TypeScript» для запуска на веб-страницах.

В настоящее время "esbuild" поддерживает функции:

  • Погрузчик
  • компрессия
  • Пакет
  • Tree shaking
  • Генерация исходной карты
  • Перенос JSX и более нового синтаксиса JS на ES6
  • ...

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

Функции, которые в настоящее время не поддерживаются для преобразования синтаксиса "JavaScript":

  • Top-level await
  • async await
  • BigInt
  • Синтаксис хеш-банга

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

2 Сравнение существующих упаковочных инструментов

Автор «esbuild» сравнил текущий этап с аналогичными инструментами"Ориентиры". Окончательный результат:

Для этих тестов esbuild был как минимум в 100 раз быстрее, чем другие протестированные мной сборщики JavaScript.

100 раз можно сказать, что он почти летает... И причина, по которой "esbuild" работает быстро, здесь я объясню на двух уровнях:

2.1 Официальное объяснение

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

2.2 Перевод на языковом уровне

  • Базовая реализация подобных инструментов на этом этапе основана на «JavaScript», который сам по себе ограничен как интерпретируемый язык и не может в полной мере использовать ЦП.
  • Хотя движок «Chrome V8» оптимизировал работу «JavaScript» и представил механизм «JIT», некоторые коды реализуют машинный код, а «esbuild» полностью реализует форму машинного кода, и разрыв в производительности неустраним.

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

3 детали API esbuild

Хотя «esbuild» уже давно открыт и используется, официальная документация лишь кратко описывает, как его использовать, а введение в API отсутствует Читателям рекомендуется самостоятельно прочитать определения в исходном коде.

«esbuild» предоставляет четыре функции:transform,build,buildSync,Service. Далее давайте познакомимся с ними с точки зрения определения исходного кода.

3.1 transform

transformможно использовать для преобразования.js,.tsx,tsи т. д., а затем выводить как старый синтаксис.jsфайл, который предоставляет два параметра:

  • Первый параметр (обязательный, строка) относится к коду (содержимому модуля), который необходимо преобразовать.
  • Второй параметр (необязательный) относится к параметрам, необходимым для преобразования, таким как путь к исходному файлу.sourcefile, нужно загрузитьloaderloaderОпределение:
type Loader = 'js' | 'jsx' | 'ts' | 'tsx' | 'css' | 'json' | 'text' | 'base64' | 'file' | 'dataurl' | 'binary';

transformвернетPromise,соответствующийTransformResultэто объект, который будет содержать преобразованный старыйjsкод,sourceMapКарта, предупреждающее сообщение:

interface TransformResult {
  js: string;
  jsSourceMap: string;
  warnings: Message[];
}

3.2 build

buildДостигнутоtransform, то есть преобразование кода, а также будет сжимать преобразованный код и генерировать.jsфайл в указанныйoutputсодержание.buildПредусмотрен только один параметр (объект) для указания входного файла, выходного файла,loaderДругие варианты:

interface BuildOptions extends CommonOptions {
  bundle?: boolean;
  splitting?: boolean;
  outfile?: string;
  metafile?: string;
  outdir?: string;
  platform?: Platform;
  color?: boolean;
  external?: string[];
  loader?: { [ext: string]: Loader };
  resolveExtensions?: string[];
  mainFields?: string[];
  write?: boolean;
  tsconfig?: string;
  outExtension?: { [ext: string]: string };

  entryPoints?: string[];
  stdin?: StdinOptions;
}

buildВызов функции выведетBuildResult, который содержит сгенерированный файлoutputFilesи оперативная информацияwarnings:

interface BuildResult {
  warnings: Message[];
  outputFiles?: OutputFile[];
}

Однако следует отметить, чтоoutputFilesтолько вwriteдляfalseвывод, только если этоUint8Array.

3.3 buildSync

buidSyncКак следует из названия, по сравнению сbuild, он строится синхронно, т.е. если вы используетеbuildНам нужна помощьasync awaitдля реализации синхронных вызовов при использованииbuildSyncСинхронные вызовы могут быть реализованы напрямую.

3.4 Service

ServiceПоявление призвано решить проблему создания подпроцесса для завершения обращения к вышеуказанному API, при множественных обращениях к API будет потеря производительности, что также поясняется в документации.

Итак, используяServiceДля преобразования кода или упаковки будет создан долгосрочный общий подпроцесс, что позволит избежать потери производительности. И в "Вите" тоже используетсяServiceспособ выполнить.ts,.js,.jsxРабота по перекодировке.

Serviceопределение:

interface Service {
  build(options: BuildOptions): Promise<BuildResult>;
  transform(input: string, options?: TransformOptions): Promise<TransformResult>;
  stop(): void;
}

можно увидеть,ServiceСуть инкапсуляцииbuild,transform,stopфункции, просто отличающиеся от вызова их по отдельности,ServiceОсновная реализация является"долгосрочное присутствие доступно для обмена"дочерний процесс.

Однако в реальном использовании мы не используем напрямуюServiceсоздать экземпляр, ноstartServiceсоздатьServiceПример:

const {
  startService,
  build,
} = require("esbuild")
const service = await startService()

try {
  const res = await service.build({
    entryPoints: ["./src/main.js"],
    write: false
  })
  console.log(res)
} finally {
  service.stop()
}

и, используяstopОбратите внимание, что это завершит дочерний процесс, что также означает, что любойpendingизPromiseтакже будет прекращено.

4 Реализуйте небольшой и красивый пакет Bundler

После просто знания «эсбулда», давайте реализовать небольшую и красивуюBunderПакет:

1. Инициализируйте проект и установите «esbuild»:

mkdir esbuild-bundler; cd esbuild-bundler; npm init -y; npm i esbuild

2. Структура каталогов:

|——— src
     |—— main.js  #项目入口文件
|——— index.js     #bundler实现核心文件

3.index.js:

(async () => {
  const {
    startService,
    build,
  } = require("esbuild")
  const service = await startService()

  try {
    const res = await service.build({
      entryPoints: ["./src/main.js"],
      outfile: './dist/main.js',
      minify: true,
      bundle: true,
    })
  } finally {
    service.stop()
  }
})()

4. Запустите егоnode indexиспытать молниюbundlerПакет!

напиши в конце

После прочтения этой статьи у каждого должно быть базовое представление о «esbuild». Более того, исходный код в этой статье основан только на базовых возможностях реализации «Go», а реальная базовая реализация по-прежнему зависит от того, как реализован «Go». не быть представленным. Итак, в следующей статье я объясню, как использовать его в исходном дизайне «Vite».esbuildреализовать.ts,jsx,.jsРазбор синтаксиса и его настройкаpluginдля реализации некоторых преобразований кода. Наконец, если в статье есть какое-либо неуместное выражение, вы можете отправить вопрос.

Обзор прошлых статей

Углубленная интерпретация исходного кода Vue3 | процесс создания компонента

Углубленная интерпретация исходного кода Vue3 | Какова «предыстория» встроенного телепорта компонента?

Углубленная интерпретация исходного кода Vue3 | процесс исправления комбинации компиляции и среды выполнения

❤️Любовное тройное комбо

Благодаря чтению, если вы чувствуете, что что-то приобрели, вы можете полюбить три комбо! ! !

Спросите у прохожих на переднем крае - Улиу ("Публичный аккаунт WeChat: Code center")