Изучение Vite через его исходный код

Изучение Vite через его исходный код Изучение

Как вы, наверное, слышали, у интерфейсной экосистемы появился новый классный ребенок: инструмент сборки под названием Vite. Хотя он был создан Эваном Ю (который также создал Vue. js), он не зависит от фреймворка, поэтому вы можете использовать Vite с Vue. js, React. js, Svelte. js или даже ванильным JavaScript.

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

Теперь, без лишних слов, давайте создадим приложение с Vite.

Создание приложения с Vite

Для целей этой демонстрации мы создадим проект Vue, используя эту команду:

npm init vite@latest

(Наличие @latestwill гарантирует, что вы всегда будете получать последнюю версию, когда будете npm installвнутри этого только что созданного проекта.)

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

Как видите, предупреждение об устаревании предлагает нам использовать

Как видите, предупреждение об устаревании предлагает нам использовать npm init viteвместо этого.

Эта новая команда по сути является сокращением для:

npx create-vite

Это установит и запустит инструмент под названием create-vite, который подсказывает вам, какой проект вы создаете. Вы выберете имя и шаблон.

Выберите для своего проекта название, которое вам нравится.

Выберите для своего проекта название, которое вам нравится

И выберите шаблон для использования.

И выберите шаблон для использования

В целях исследования вы можете использовать либо vanillaили vue.

Далее мы рассмотрим этот create-vite инструмент через его исходный код на GitHub.

Изучение исходного кода Vite

Сначала перейдите на страницу Vite GitHub по адресу github. com/vitejs/vite.

Сначала перейдите на страницу Vite GitHub по адресу github

Затем зайдите в packages папку.

Затем зайдите в packages папку

Здесь вы можете увидеть create-appи create-vite.

create-appотвечал за исходную команду с надписью «устарело». Что нас здесь интересует, так это create-viteпапка. В нем размещены все встроенные шаблоны для создания проектов.

Внутри packagesпапки мы также можем увидеть несколько папок плагинов для нескольких встроенных плагинов.

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

Шаблоны

Шаблон должен быть простой для понимания концепцией: это стартовый код для нового проекта.

Внутри packages/create-viteпапки вы должны увидеть с десяток template-*папок.

📁 /packages/create-vite

Внутри packages create-viteпапки вы должны

Как видите, Vite поддерживает шаблоны для различных фреймворков (и их аналоги на TypeScript).

Вы можете выбрать vanillaиз create-viteподсказки.

Вы можете выбрать vanillaиз create-viteподсказки

Если вы выберете ванильный, он в основном возьмет файлы в packages/template-vanillaпапке и клонирует их как ваш новый проект.

📁 /packages/template-vanilla

Вы также можете выбрать vueиз подсказки

Вы также можете выбрать vueиз подсказки:

Если вы выберете vue, он будет клонировать файлы

 

Если вы выберете vue, он будет клонировать файлы в packages/template-vueпапке как ваш новый проект.

📁 /packages/template-vue

Созданный проект из шаблона vue будет иметь стандартную структуру папок

Созданный проект из шаблона vue будет иметь стандартную структуру папок, которую вы ожидаете от проекта Vue.

Итак, это шаблон. Теперь поговорим о плагине.

Плагины

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

По умолчанию Vite предоставляет плагины для Vue, Vue с JSX и React.

Вы можете изучить код каждого встроенного плагина в packagesпапке:

📁 /packages

plugin-legacyпредназначен для устаревших браузеров, которые

Примечание: plugin-legacyпредназначен для устаревших браузеров, которые не поддерживают собственный ESM.

Чаще всего эти плагины используются с помощью соответствующих им шаблонов. Например, шаблон Vue потребует использования плагина Vue, а шаблон React потребует использования плагина React.

Читайте также:  Безопасность Kubernetes для конвейеров DevOps

В качестве простого варианта проект, созданный с использованием стандартного шаблона, не знает, как обслуживать файлы однофайловых компонентов (SFC) Vue. Но проект Vue, созданный с помощью Vite, сможет обрабатывать тип файла SFC. И он также знает, как собрать весь проект Vue для производства.

Если мы сравним соответствующие package. json файлы из шаблона Vue и ванильного шаблона, мы легко поймем, почему это так.

json файлы из шаблона Vue и ванильного шаблона

📁 /packages/template-vanilla/package.json

packages template-vanilla package.json

📁 /packages/template-vue/package.json

template-vueсодержит все, что template-vanillaесть, плюс три дополнительных пакета.

📁 /packages/template-vue/package.json

"dependencies": {
    "vue": "^3.2.6" // 1
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.6.1", // 2
    "@vue/compiler-sfc": "^3.2.6", // 3
    "vite": "^2.5.4"
  }
  • vue это основная библиотека, которая запускается во время выполнения
  • @vitejs/plugin-vue это плагин, который отвечает за обслуживание и объединение проекта Vue
  • @vue/compiler-sfc необходим для компиляции файла SFC

Таким образом, можно с уверенностью сказать, что эти три пакета дают проекту Vite возможность понимать код Vue. @vitejs/plugin-vueПакет является «мостом», соединяющим ядро системы Vite к рамкам Vue. js.

Плагин Vue

Как мы видели в плагине Vue package. json, @vitejs/plugin-vueпакет отвечает за объединение проекта Vue.

Vite делегирует работу по объединению в Rollup, еще один очень популярный инструмент для сборки. Отношения между плагинами основаны на том, что viteядро вызывает pluginкод пакета в определенные моменты времени. Эти специфические точки называются » крючками «. Разработчик плагина должен решить, какой код будет выполняться в каждом хуке.

Например, в исходном коде плагина Vue вы можете увидеть, как реализованы некоторые из этих хуков.

📁 /packages/plugin-vue/src/index.ts


async resolveId(id) {
  // component export helper
  if (id === EXPORT_HELPER_ID) {
    return id
  }
  // serve sub-part requests (*?vue) as virtual modules
  if (parseVueRequest(id).query.vue) {
    return id
  }
},

load(id, ssr = !!options.ssr) {
  if (id === EXPORT_HELPER_ID) {
    return helperCode
  }

  const { filename, query } = parseVueRequest(id)
  // select corresponding block for sub-part virtual modules
  if (query.vue) {
    if (query.src) {
      return fs.readFileSync(filename, 'utf-8')
    }
    const descriptor = getDescriptor(filename, options)!
    let block: SFCBlock | null | undefined
    if (query.type === 'script') {
      // handle <scrip> + <script setup> merge via compileScript()
      block = getResolvedScript(descriptor, ssr)
    } else if (query.type === 'template') {
      block = descriptor.template!
    } else if (query.type === 'style') {
      block = descriptor.styles[query.index!]
    } else if (query.index != null) {
      block = descriptor.customBlocks[query.index]
    }
    if (block) {
      return {
        code: block.content,
        map: block.map as any
      }
    }
  }
},

transform(code, id, ssr = !!options.ssr) {
  const { filename, query } = parseVueRequest(id)
  if (query.raw) {
    return
  }
  if (!filter(filename) && !query.vue) {
    if (!query.vue && refTransformFilter(filename)) {
      if (!canUseRefTransform) {
        this.warn('refTransform requires @vue/compiler-sfc@^3.2.5.')
      } else if (shouldTransformRef(code)) {
        return transformRef(code, {
          filename,
          sourceMap: true
        })
      }
    }
    return
  }
    if (!query.vue) {
    // main request
    return transformMain(
      code,
      filename,
      options,
      this,
      ssr,
      customElementFilter(filename)
    )
  } else {
    // sub block request
    const descriptor = getDescriptor(filename, options)!
    if (query.type === 'template') {
      return transformTemplateAsModule(code, descriptor, options, this, ssr)
    } else if (query.type === 'style') {
      return transformStyle(
        code,
        descriptor,
        Number(query.index),
        options,
        this
      )
    }
  }
}

А в основном viteпакете Rollup будет использоваться для вызова вышеупомянутых хуков плагина.

📁 /packages/vite/src/node/build.ts

// first, gathers all the plugins used
const plugins = (
  ssr ? config.plugins.map((p) => injectSsrFlagToHooks(p)) : config.plugins
) as Plugin[]

...

// then, put the plugins and everything else in an options object
const rollupOptions: RollupOptions = {
  input,
  preserveEntrySignatures: ssr
    ? 'allow-extension'
    : libOptions
    ? 'strict'
    : false,
  ...options.rollupOptions,
  plugins,
  external,
  onwarn(warning, warn) {
    onRollupWarning(warning, warn, config)
  }
}

...

// lastly, delegate to rollup
const bundle = await rollup.rollup(rollupOptions)

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

Читайте также:  Как измерить и улучшить производительность Node.js

Другими словами, плагин Vite является расширением плагина Rollup.

Команды Vite

Возвращаясь к шаблону Vue, давайте обратим внимание на эту scriptsопцию.

📁 /packages/create-vite/template-vue/package.json

"scripts": {
  "dev": "vite",
  "build": "vite build",
  "serve": "vite preview"
},

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

  • npm run dev для запуска сервера разработки
  • npm run build для создания производственной сборки
  • npm run serve для предварительного просмотра указанной производственной сборки на месте

Вышеуказанные команды сопоставлены со следующими командами:

  • vite
  • vite build
  • vite preview

Как видите, viteвсе начинается с пакета.

Вы можете получить представление о том, какие другие сторонние инструменты задействованы, заглянув в package.jsonфайл viteпакета.

📁 /packages/vite/package.json

"dependencies": {
  "esbuild": "^0.12.17",
  "postcss": "^8.3.6",
  "resolve": "^1.20.0",
  "rollup": "^2.38.5"
},

Как видите, viteна самом деле за сценой используются два разных сборщика: Rollup и esbuild.

Rollup против esbuild

Vite использует оба этих бандлера для разных видов деятельности.

Накопительный пакет используется Vite для основных нужд объединения. А esbuild используется для совместимости и оптимизации модулей. Эти шаги известны как процесс «предварительного объединения зависимостей». Этот процесс считается «тяжелым», потому что он должен выполняться для каждого модуля, а в проекте обычно используется много модулей.

Совместимость модулей означает преобразование различных форматов (модули UMD или CommonJS) в стандартный формат ESM.

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

Rollup будет слишком медленным, чтобы справиться с этими сверхмощными вещами по сравнению с esbuild. Esbuild на самом деле самый быстрый инструмент для сборки. Это быстро, потому что он разработан на Go (языке программирования).

Как видите, esbuild не просто быстрый; это на совершенно другом уровне

Как видите, esbuild не просто быстрый; это на совершенно другом уровне. И поэтому Vite работает молниеносно. ⚡

Заключение

В этой статье мы просмотрели источник и узнали, что:

  • npm init viteкоманда использует create-viteинструмент
  • create-viteпакет содержит все встроенные шаблоны
  • специфичный для фреймворка шаблон зависит от соответствующего ему специфичного для фреймворка плагина
  • плагины реализованы в архитектуре на основе хуков
  • Vite за кулисами использует как Rollup, так и esbuild

Теперь у вас должно быть твердое представление о системе Vite. Но на практике вам понадобятся другие общие функции, которые мы здесь не рассмотрели. Наиболее распространенными из них являются поддержка препроцессора TypeScript и CSS.

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