Skip to content

Возможности ​

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

Разрешение зависимостей NPM и предварительное объединение ​

Импорты нативных ES-модулей не поддерживают прямые ссылки на модули, например:

js
import { someMethod } from 'my-dep'

Вышеуказанный импорт вызовет ошибку в браузере. Vite обнаружит такие «голые» импорты модулей во всех обслуживаемых исходных файлах и выполнит следующее:

  1. Предварительное объединение зависимостей для улучшения скорости загрузки страниц и преобразования модулей CommonJS / UMD в ESM. Этап предварительного объединения выполняется с помощью Rolldown и делает время холодного старта Vite значительно быстрее, чем у любого сборщика на основе JavaScript.

  2. Замена импортов корректными URL-адресами, например /node_modules/.vite/deps/my-dep.js?v=f3sf2ebd, чтобы браузер мог правильно их импортировать.

Зависимости сильно кэшируются

Vite кэширует запросы к зависимостям через HTTP-заголовки, поэтому если вы хотите локально отредактировать/отладить зависимость, выполните указанные шаги.

Горячая замена модулей ​

Vite предоставляет HMR API поверх родного ESM. Фреймворки с возможностями HMR могут использовать API для предоставления мгновенных и точных обновлений без перезагрузки страницы или удаления состояния приложения. Vite предоставляет сторонние интеграции HMR для однофайловых компонентов Vue и React Fast Refresh. Есть также официальная интеграция для Preact через @prefresh/vite.

Обратите внимание, что вам не нужно настраивать их вручную — когда вы создаете приложение с помощью create-vite, выбранные шаблоны уже будут настроены для вас.

TypeScript ​

Vite поддерживает импорт файлов .ts из коробки.

Только транспиляция ​

Обратите внимание, что Vite выполняет транспиляцию только для файлов .ts и НЕ выполняет проверку типов. Предполагается, что о проверке типов позаботится ваша IDE и процесс сборки.

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

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

  • Для продакшен-сборок вы можете выполнить команду tsc --noEmit в дополнение к команде сборки Vite.

  • Во время разработки, если вам нужно больше, чем подсказки IDE, мы рекомендуем запускать tsc --noEmit --watch в отдельном процессе, или использовать vite-plugin-checker, если вы предпочитаете, чтобы ошибки типов отображались непосредственно в браузере.

Vite использует Oxc Transformer для транспиляции TypeScript в JavaScript, что быстрее стандартного tsc, а HMR-обновления отображаются в браузере менее чем за 50 мс.

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

ts
import type { T } from 'only/types'
export type { T }

Параметры компилятора TypeScript ​

Vite учитывает некоторые параметры из tsconfig.json и задаёт соответствующие параметры Oxc Transformer. По умолчанию Vite использует ближайший родительский tsconfig.json, соответствующий каждому файлу. Если в поле references этого конфига указана другая конфигурация и она соответствует файлу, используется именно она. Vite считает конфигурацию соответствующей файлу, если файл удовлетворяет полям files, include и exclude этой конфигурации.

Когда одна и та же опция задана и в конфигурации Vite, и в tsconfig.json, приоритет имеет значение из конфигурации Vite.

Некоторые поля конфигурации в секции compilerOptions в tsconfig.json требуют особого внимания.

isolatedModules ​

Должно быть установлено значение true.

Это связано с тем, что Oxc Transformer выполняет только транспиляцию без информации о типах, и не поддерживает определённые функции, такие как const enum и неявные импорты только для типов.

Вы должны установить "isolatedModules": true в вашем tsconfig.json в секции compilerOptions, чтобы TS предупреждал вас о функциях, которые не работают с изолированной транспиляцией.

Если зависимость не работает с "isolatedModules": true, можно использовать "skipLibCheck": true для временного подавления ошибок до тех пор, пока они не будут исправлены.

useDefineForClassFields ​

Значение по умолчанию будет true, если целевая версия TypeScript — ES2022 или новее, включая ESNext. Это соответствует поведению TypeScript 4.3.2+. Для других целевых версий TypeScript значение по умолчанию будет false.

true является стандартным поведением среды выполнения ECMAScript.

Если вы используете библиотеку, которая сильно зависит от полей класса, пожалуйста, будьте осторожны с предполагаемым использованием этой библиотеки. Хотя большинство библиотек ожидают, что "useDefineForClassFields": true, вы можете явно установить useDefineForClassFields в false, если ваша библиотека не поддерживает эту опцию.

target ​

Vite по умолчанию не транспилирует TypeScript с заданным значением target, следуя тому же поведению, что и esbuild.

Для указания целевой версии (target) в режиме разработки можно использовать опцию oxc.target, которая по умолчанию имеет значение esnext для обеспечения минимальной транспиляции. При сборке опция build.target имеет более высокий приоритет перед oxc.target и также может быть настроена при необходимости.

emitDecoratorMetadata ​

Эта опция поддерживается лишь частично. Полная поддержка требует вывода типов компилятором TypeScript, что не поддерживается. Подробности см. в документации Oxc Transformer.

paths ​

Можно указать resolve.tsconfigPaths: true, чтобы Vite использовал опцию paths из tsconfig.json для разрешения импортов.

Обратите внимание: эта возможность имеет накладные расходы по производительности и не рекомендуется командой TypeScript для изменения поведения внешних инструментов.

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

skipLibCheck

В стартовых шаблонах Vite есть "skipLibCheck": true по умолчанию, чтобы избежать проверки типов зависимостей, поскольку они могут поддерживать только определённые версии и конфигурации TypeScript. Более подробную информацию вы можете найти на сайте vuejs/vue-cli#5688.

Клиентские типы ​

Типы по умолчанию в Vite предназначены для его API Node.js. Чтобы настроить среду для клиентского кода в приложении Vite, добавьте vite/client в compilerOptions.types внутри tsconfig.json:

tsconfig.json
json
{
  "compilerOptions": {
    "types": ["vite/client", "some-other-global-lib"]
  }
}

Обратите внимание, что если указаны compilerOptions.types, в глобальную область видимости будут включены только эти пакеты (вместо всех доступных пакетов «@types»). Это рекомендуется начиная с TS 5.9.

Использование директивы с тройной косой чертой

В качестве альтернативы вы можете добавить файл объявления d.ts:

vite-env.d.ts
typescript
/// <reference types="vite/client" />

vite/client предоставляет следующие типовые шимы:

  • Импорт ресурсов (например, импорт файла .svg)
  • Типы для внедряемых Vite констант в import.meta.hot
  • Типы для HMR API в import.meta.hot

СОВЕТ

Чтобы переопределить стандартные типы, добавьте файл определения, который содержит ваши типы. Затем добавьте ссылку на типы перед vite/client.

Например, чтобы сделать стандартный импорт *.svg компонентом React:

  • vite-env-override.d.ts (файл, содержащий ваши наборы):
    ts
    declare module '*.svg' {
      const content: React.FC<React.SVGProps<SVGElement>>
      export default content
    }
  • Если вы используете compilerOptions.types, убедитесь, что файл включен в tsconfig.json:
    tsconfig.json
    json
    {
      "include": ["src", "./vite-env-override.d.ts"]
    }
  • Если вы используете директивы с тройной косой чертой, обновите файл, содержащий ссылку на vite/client (обычно vite-env.d.ts):
    ts
    /// <reference types="./vite-env-override.d.ts" />
    /// <reference types="vite/client" />

HTML ​

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

Любые HTML-файлы в корне вашего проекта могут быть напрямую доступны по соответствующему пути к директории:

  • <root>/index.html -> http://localhost:5173/
  • <root>/about.html -> http://localhost:5173/about.html
  • <root>/blog/index.html -> http://localhost:5173/blog/index.html

Ресурсы, на которые ссылаются HTML-элементы, такие как <script type="module" src> и <link href>, обрабатываются и упаковываются как часть приложения. Полный список поддерживаемых элементов приведен ниже:

  • <audio src>
  • <embed src>
  • <img src> и <img srcset>
  • <image href> и <image xlink:href>
  • <input src>
  • <link href> и <link imagesrcset>
  • <object data>
  • <script type="module" src>
  • <source src> и <source srcset>
  • <track src>
  • <use href> и <use xlink:href>
  • <video src> и <video poster>
  • <meta content>
    • Только если атрибут name соответствует msapplication-tileimage, msapplication-square70x70logo, msapplication-square150x150logo, msapplication-wide310x150logo, msapplication-square310x310logo, msapplication-config или twitter:image
    • Или только если атрибут property соответствует og:image, og:image:url, og:image:secure_url, og:audio, og:audio:secure_url, og:video или og:video:secure_url
html
<!DOCTYPE html>
<html>
  <head>
    <link rel="icon" href="/favicon.ico" />
    <link rel="stylesheet" href="/src/styles.css" />
  </head>
  <body>
    <img src="/src/images/logo.svg" alt="logo" />
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

Чтобы отказаться от обработки HTML для определённых элементов, вы можете добавить атрибут vite-ignore к элементу, что может быть полезно при ссылке на внешние ресурсы или CDN.

Фреймворки ​

Все современные фреймворки поддерживают интеграцию с Vite. Большинство плагинов для фреймворков поддерживаются командами каждого фреймворка, за исключением официальных плагинов Vite для Vue и React, которые поддерживаются в организации vite:

Посмотрите Руководство по плагинам для получения дополнительной информации.

JSX ​

Файлы .jsx и .tsx также поддерживаются из коробки. Транспиляция JSX также осуществляется с помощью Oxc Transformer.

Ваш выбранный фреймворк уже настроит поддержку JSX по умолчанию (например, пользователи Vue должны использовать официальный плагин @vitejs/plugin-vue-jsx, который предоставляет специфические для Vue 3 функции, включая HMR, глобальное разрешение компонентов, директивы и слоты).

Если вы используете JSX с вашим собственным фреймворком, вы можете настроить пользовательские jsxFactory и jsxFragment, используя опцию oxc. Например, плагин Preact будет использовать:

vite.config.js
js
import { 
defineConfig
} from 'vite'
export default
defineConfig
({
oxc
: {
jsx
: {
importSource
: 'preact',
}, } })

Подробности в документации Oxc Transformer.

Вы можете инжектировать хелперы JSX с помощью jsxInject (эта опция доступна только для Vite), чтобы избежать ручного импорта:

vite.config.js
js
import { 
defineConfig
} from 'vite'
export default
defineConfig
({
oxc
: {
jsxInject
: `import React from 'react'`
} })

CSS ​

Импорт файлов .css будет инжектировать их содержимое на страницу через тег <style> с поддержкой HMR.

Встраивание и перебазирование @import ​

Vite предварительно настроен для поддержки встраивания CSS @import через postcss-import. Также учитываются алиасы Vite для CSS @import. Кроме того, все ссылки CSS url(), даже если импортируемые файлы находятся в разных директориях, всегда автоматически перерабатываются для обеспечения корректности.

Алиасы @import и обработка URL также поддерживаются для файлов Sass и Less (см. Препроцессоры CSS).

PostCSS ​

Если проект содержит корректный конфиг PostCSS (любой формат, поддерживаемый postcss-load-config, например, postcss.config.js), он будет автоматически применён ко всем импортированным CSS.

Обратите внимание, что минификация CSS будет выполняться после PostCSS и будет использовать опцию build.cssTarget.

CSS-модули ​

Любой CSS-файл, заканчивающийся на .module.css, считается CSS-модулем. Импорт такого файла вернет соответствующий объект модуля:

example.module.css
css
.red {
  color: red;
}
js
import 
classes
from './example.module.css'
document
.
getElementById
('foo').
className
=
classes
.
red

Поведение CSS-модулей можно настроить с помощью опции css.modules.

Если css.modules.localsConvention установлен для включения локалей в верблюжьем регистре (например, localsConvention: 'camelCaseOnly'), вы также можете использовать именованный импорт:

js
// .apply-color -> applyColor
import { 
applyColor
} from './example.module.css'
document
.
getElementById
('foo').
className
=
applyColor

Препроцессоры CSS ​

Поскольку Vite ориентирован только на современные браузеры, рекомендуется использовать собственные переменные CSS с плагинами PostCSS, которые реализуют проекты CSSWG (например, postcss-nesting) и авторский простой CSS, соответствующий будущим стандартам.

Тем не менее, Vite обеспечивает встроенную поддержку файлов .scss, .sass, .less, .styl и .stylus. Для них не нужно устанавливать специфические для Vite плагины, но сам соответствующий препроцессор должен быть установлен:

bash
# .scss и .sass
npm add -D sass

# .less
npm add -D less

# .styl и .stylus
npm add -D stylus

Если вы используете компоненты Vue в одном файле, это также автоматически включает <style lang="sass"> и другие.

Vite улучшает разрешение @import для Sass и Less, так что алиасы Vite также учитываются. Кроме того, относительные ссылки url() внутри импортированных файлов Sass/Less, которые находятся в других директориях по сравнению с корневым файлом, также автоматически пересчитываются для обеспечения корректности. Перебазирование ссылок url(), начинающихся с переменной или интерполяции, не поддерживается из-за ограничений API.

Алиасы @import и пересчёт URL не поддерживаются для Stylus из-за ограничений его API.

Вы также можете использовать CSS-модули в сочетании с препроцессорами, добавляя .module к расширению файла, например, style.module.scss.

Отключение внедрения CSS на странице ​

Автоматическое внедрение содержимого CSS можно отключить с помощью параметра запроса ?inline. В этом случае обработанная CSS-строка возвращается как экспорт модуля по умолчанию, как обычно, но стили не внедряются на страницу.

js
import 
styles
from './foo.css' // стили будут вставлены в страницу
import
otherStyles
from './bar.css?inline' // стили не будут вставлены в страницу

ПРИМЕЧАНИЕ

Импорт по умолчанию и именованный импорт из CSS-файлов (например, import style from './foo.css') удален из Vite 5. Вместо этого используйте запрос ?inline.

Lightning CSS ​

Vite по умолчанию использует Lightning CSS для минификации CSS в продакшен-сборках. Однако PostCSS по-прежнему применяется для остальной обработки CSS.

Существует экспериментальная поддержка полного использования Lightning CSS для обработки CSS. Вы можете включить её, добавив css.transformer: 'lightningcss'.

Для настройки можно передавать опции Lightning CSS через параметр конфигурации css.lightningcss. Для настройки CSS Modules следует использовать css.lightningcss.cssModules вместо css.modules (который настраивает обработку CSS Modules через PostCSS).

Статические ресурсы ​

Импорт статического ресурса вернёт разрешённый публичный URL при его обслуживании:

js
import 
imgUrl
from './img.png'
document
.
getElementById
('hero-img').src =
imgUrl

Специальные запросы могут изменять способ загрузки ресурсов:

js
// Явная загрузка ресурсов в виде URL (автоматически встраивается в зависимости от размера файла)
import 
assetAsURL
from './asset.js?url'
js
// Загружаем ресурсы в виде строк
import 
assetAsString
from './shader.glsl?raw'
js
// Загружаем веб-воркеров
import 
Worker
from './worker.js?worker'
js
// Веб-воркеры встраиваются в строки base64 во время сборки
import 
InlineWorker
from './worker.js?worker&inline'

Подробнее в главе Обработка статических ресурсов.

JSON ​

Файлы JSON можно импортировать напрямую — также поддерживается именованный импорт:

js
// импортируем весь объект
import 
json
from './example.json'
// импорт корневого поля в виде именованных экспортов - помогает при встряхивании деревьев! import {
field
} from './example.json'

Глобальный импорт ​

Vite поддерживает импорт нескольких модулей из файловой системы с помощью специальной функции import.meta.glob:

js
const 
modules
= import.meta.
glob
('./dir/*.js')

Вышеизложенное преобразуется в следующее:

js
// код, созданный Vite
const modules = {
  './dir/bar.js': () => import('./dir/bar.js'),
  './dir/foo.js': () => import('./dir/foo.js'),
}

Затем вы можете перебирать ключи объекта modules, чтобы получить доступ к соответствующим модулям:

js
for (const path in modules) {
  modules[path]().then((mod) => {
    console.log(path, mod)
  })
}

По умолчанию совпадающие файлы лениво загружаются через динамический импорт и будут разделены на отдельные части во время сборки. Если вы предпочитаете импортировать все модули напрямую (например, полагаясь на то, что побочные эффекты в этих модулях будут применены первыми), вы можете передать { eager: true } в качестве второго аргумента:

js
const 
modules
= import.meta.
glob
('./dir/*.js', {
eager
: true })

Вышеизложенное преобразуется в следующее:

js
// код, созданный Vite
import * as __vite_glob_0_0 from './dir/bar.js'
import * as __vite_glob_0_1 from './dir/foo.js'
const modules = {
  './dir/bar.js': __vite_glob_0_0,
  './dir/foo.js': __vite_glob_0_1,
}

Несколько шаблонов ​

Первым аргументом может быть массив глобалов, например:

js
const 
modules
= import.meta.
glob
(['./dir/*.js', './another/*.js'])

Шаблоны исключений ​

Также поддерживаются шаблоны с префиксом !. Чтобы исключить некоторые файлы из результата, вы можете добавить шаблоны исключений в первый аргумент:

js
const 
modules
= import.meta.
glob
(['./dir/*.js', '!**/bar.js'])
js
// код, созданный Vite
const modules = {
  './dir/foo.js': () => import('./dir/foo.js')
}

Именованные импорты ​

С помощью опций import можно импортировать только части модулей:

ts
const 
modules
= import.meta.
glob
('./dir/*.js', {
import
: 'setup' })
ts
// код, созданный Vite
const modules = {
  './dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
  './dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
}

В сочетании с опцией eager даже возможно включить «tree-shaking» («встряхивание дерева») для этих модулей:

ts
const 
modules
= import.meta.
glob
('./dir/*.js', {
import
: 'setup',
eager
: true
})
ts
// код, созданный Vite:
import { setup as __vite_glob_0_0 } from './dir/bar.js'
import { setup as __vite_glob_0_1 } from './dir/foo.js'
const modules = {
  './dir/bar.js': __vite_glob_0_0,
  './dir/foo.js': __vite_glob_0_1,
}

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

ts
const 
modules
= import.meta.
glob
('./dir/*.js', {
import
: 'default',
eager
: true
})
ts
// код, созданный Vite:
import __vite_glob_0_0 from './dir/bar.js'
import __vite_glob_0_1 from './dir/foo.js'
const modules = {
  './dir/bar.js': __vite_glob_0_0,
  './dir/foo.js': __vite_glob_0_1,
}

Пользовательские запросы ​

Можно также использовать опцию query, чтобы задать запросы к импорту, например, импортировать ресурсы как строку или как url:

ts
const 
moduleStrings
= import.meta.
glob
('./dir/*.svg', {
query
: '?raw',
import
: 'default'
}) const
moduleUrls
= import.meta.
glob
('./dir/*.svg', {
query
: '?url',
import
: 'default'
})
ts
// код, созданный Vite:
const moduleStrings = {
  './dir/bar.svg': () => import('./dir/bar.svg?raw').then((m) => m['default']),
  './dir/foo.svg': () => import('./dir/foo.svg?raw').then((m) => m['default']),
}
const moduleUrls = {
  './dir/bar.svg': () => import('./dir/bar.svg?url').then((m) => m['default']),
  './dir/foo.svg': () => import('./dir/foo.svg?url').then((m) => m['default']),
}

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

ts
const 
modules
= import.meta.
glob
('./dir/*.js', {
query
: {
foo
: 'bar',
bar
: true }
})

Базовый путь ​

Вы также можете использовать опцию base для указания базового пути для импортов:

ts
const 
modulesWithBase
= import.meta.
glob
('./**/*.js', {
base
: './base',
})
ts
// код, созданный Vite:
const modulesWithBase = {
  './dir/foo.js': () => import('./base/dir/foo.js'),
  './dir/bar.js': () => import('./base/dir/bar.js'),
}

Опция base может быть только путём к директории, относительным к файлу-импортёру или абсолютным относительно корня проекта. Алиасы и виртуальные модули не поддерживаются.

Только шаблоны, которые являются относительными путями, интерпретируются как относительные к разрешённому базовому пути.

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

Сопоставление с учётом регистра ​

По умолчанию сопоставление глобальных шаблонов выполняется с учётом регистра. Для изменения этого поведения можно использовать параметр caseSensitive:

js
const 
modules
= import.meta.
glob
('./dir/module*.js', {
caseSensitive
: false,
})

При значении caseSensitive: false глобальный шаблон будет сопоставляться с файлами независимо от регистра (например, Module.js, module.js и MODULE.js будут соответствовать шаблону module*.js).

Предостережения по поводу глобального импорта ​

Обратите внимание, что:

  • Это функция, специфичная для Vite, и не является стандартом веба или ES.
  • Глобальные шаблоны обрабатываются как спецификаторы импорта: они должны быть либо относительными (начинаться с ./), либо абсолютными (начинаться с /, разрешаемыми относительно корня проекта), либо путями алиасов (см. опцию resolve.alias).
  • Глобальное сопоставление выполняется с помощью tinyglobby — ознакомьтесь с его документацией для поддерживаемых глобальных шаблонов.
  • Также следует учитывать, что все аргументы в import.meta.glob должны быть переданы как литералы. Вы не можете использовать переменные или выражения в них.

Динамический импорт ​

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

ts
const module = await import(`./dir/${file}.js`)

Обратите внимание, что переменные представляют имена файлов только на одном уровне. Если file имеет значение 'foo/bar', импорт будет неудачным. Для более продвинутого использования можно воспользоваться функцией глобального импорта.

Также обратите внимание, что динамический импорт должен соответствовать следующим правилам, чтобы быть собранным:

  • Импорты должны начинаться с ./, ../ или #: import(`./dir/${foo}.js`) допустим, но import(`${foo}.js`) недопустим.
  • Импорты должны заканчиваться расширением файла: import(`./dir/${foo}.js`) допустим, но import(`./dir/${foo}`) недопустим.
  • Импорты в собственную директорию должны указывать шаблон имени файла: import(`./prefix-${foo}.js`) допустим, но import(`./${foo}.js`) недопустим.

Эти правила введены для предотвращения случайного импорта файлов, которые не предназначены для сборки. Например, без этих правил import(foo) собрал бы все файлы из файловой системы.

WebAssembly ​

Vite поддерживает импорт предварительно скомпилированных файлов .wasm двумя способами: напрямую как ES-модуль, если нужны только экспорты модуля, или через ?init, если требуется явный контроль над созданием экземпляра.

Интеграция с ES-модулями ​

Файл .wasm можно импортировать напрямую. Vite считывает импорты и экспорты модуля из бинарного файла, создаёт экземпляр модуля и повторно экспортирует его значения как именованные экспорты ES-модуля:

js
import { add } from './add.wasm'

console.log(add(1, 2)) // 3

Если модуль WebAssembly сам объявляет импорты, Vite разрешает их из JavaScript-модулей. Имя каждого импортируемого модуля рассматривается как спецификатор импорта (разрешаемый относительно файла .wasm), а запрошенные сущности автоматически подключаются к экземпляру модуля.

Это соответствует предложению по интеграции WebAssembly и ES-модулей. Поскольку экземпляр модуля WebAssembly создаётся асинхронно, напрямую импортированный файл .wasm ведёт себя как асинхронный модуль и требует поддержки await верхнего уровня.

Поддержка TypeScript

Поскольку типы файлов .wasm неизвестны, TypeScript будет сообщать об ошибках вида Module '"*.wasm"' has no exported member 'add'. Чтобы исправить это, включите allowArbitraryExtensions в своём tsconfig.json и создайте файл объявления рядом с вашим .wasm-файлом. При включённой опции allowArbitraryExtensions TypeScript будет искать файл объявления с именем {имя_файла}.d.wasm.ts при разрешении импорта .wasm. Например, для add.wasm создайте файл add.d.wasm.ts:

add.d.wasm.ts
ts
export function add(a: number, b: number): number

Ручная инициализация ​

Если вам нужен контроль над тем, когда и каким образом создаётся экземпляр модуля, импортируйте его с суффиксом ?init. Экспорт по умолчанию будет функцией инициализации, возвращающей Promise с объектом WebAssembly.Instance:

js
import 
init
from './example.wasm?init'
init
().
then
((
instance
) => {
instance
.
exports
.
test
()
})

Функция init также может принимать в качестве второго аргумента importObject, который передается в WebAssembly.instantiate:

js
init
({
imports
: {
someFunc
: () => {
/* ... */ } } }).
then
(() => {
/* ... */ })

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

Для сборки под SSR поддерживаются только рантаймы, совместимые с Node.js

Из-за отсутствия универсального способа загрузки файлов внутренняя реализация как прямого импорта .wasm, так и импорта .wasm?init использует модуль node:fs. Это означает, что данные возможности будут работать в SSR-сборках только в средах выполнения, совместимых с Node.js.

Доступ к модулю WebAssembly ​

Если вам нужен доступ к объекту Module, например, чтобы инстанцировать его несколько раз, используйте явный импорт URL для разрешения ресурса, а затем выполните инстанцирование:

js
import 
wasmUrl
from 'foo.wasm?url'
const
main
= async () => {
const
responsePromise
=
fetch
(
wasmUrl
)
const {
module
,
instance
} =
await WebAssembly.
instantiateStreaming
(
responsePromise
)
/* ... */ }
main
()

Веб-воркеры ​

Импорт с конструкторами ​

Скрипт веб-воркера можно импортировать с помощью new Worker() и new SharedWorker(). По сравнению с суффиксами воркеров, этот синтаксис ближе к стандартам и является рекомендуемым способом создания воркеров.

ts
const worker = new Worker(new URL('./worker.js', import.meta.url))

Конструктор воркера также принимает опции, которые могут быть использованы для создания «модульных» воркеров:

ts
const worker = new Worker(new URL('./worker.js', import.meta.url), {
  type: 'module'
})

Обнаружение воркера будет работать только в том случае, если конструктор new URL() используется непосредственно внутри объявления new Worker(). В противном случае он будет обработан как URL статического ресурса. Кроме того, все параметры опций должны быть статическими значениями (т. е. строковыми литералами).

Импорт с суффиксами запросов ​

Скрипт веб-воркера можно импортировать напрямую, добавив к запросу на импорт ?worker или ?sharedworker. По умолчанию экспортируется пользовательский конструктор воркера:

js
import 
MyWorker
from './worker?worker'
const
worker
= new
MyWorker
()

Скрипт воркера также может использовать ESM-операторы import вместо импортаScripts(). Примечание: во время разработки это зависит от нативной поддержки браузера, но для промышленной сборки это откомпилировано.

По умолчанию скрипт воркера будет выдан в виде отдельного блока в продакшен-сборке. Если вы хотите вставить воркера в виде строк base64, добавьте запрос inline:

js
import 
MyWorker
from './worker?worker&inline'

Если вы хотите получить воркера в виде URL, добавьте запрос url:

js
import 
MyWorker
from './worker?worker&url'

Подробности о настройке объединения всех воркеров см. в главе Параметры воркера.

Политика безопасности контента (CSP) ​

Для развёртывания CSP необходимо установить определённые директивы или конфигурации, обусловленные внутренним устройством Vite.

'nonce-{RANDOM}' ​

Когда html.cspNonce установлен, Vite добавляет атрибут nonce с указанным значением к любым тегам <script> и <style>, а также к тегам <link> для таблиц стилей и предварительной загрузки модулей. Кроме того, когда эта опция установлена, Vite будет инжектировать мета-тег (<meta property="csp-nonce" nonce="PLACEHOLDER" />).

Значение мета-тега nonce с property="csp-nonce" будет использоваться Vite всякий раз, когда это необходимо, как в процессе разработки, так и после сборки.

ПРЕДУПРЕЖДЕНИЕ

Убедитесь, что вы заменяете placeholder уникальным значением для каждого запроса. Это важно для предотвращения обхода политики ресурса, что в противном случае можно легко сделать.

data: ​

По умолчанию, во время сборки Vite встраивает небольшие ресурсы в виде data URI. Необходимо разрешить data: для связанных директив (например, img-src, font-src) или отключить это, установив build.assetsInlineLimit: 0.

ПРЕДУПРЕЖДЕНИЕ

Не разрешайте data: для script-src. Это позволит внедрить произвольные скрипты.

Лицензия ​

Vite может сгенерировать файл со всеми лицензиями зависимостей, использованных в сборке, с помощью опции build.license. Его можно разместить для отображения и подтверждения зависимостей, используемых приложением.

vite.config.js
js
import { 
defineConfig
} from 'vite'
export default
defineConfig
({
build
: {
license
: true,
}, })

Это сгенерирует файл .vite/license.md с выводом, который может выглядеть так:

md
# Licenses

The app bundles dependencies which contain the following licenses:

## dep-1 - 1.2.3 (CC0-1.0)

CC0 1.0 Universal

...

## dep-2 - 4.5.6 (MIT)

MIT License

...

Чтобы обслуживать файл по другому пути, вы можете передать, например, { fileName: 'license.md' }, чтобы он обслуживался по адресу https://example.com/license.md. Подробнее см. в документации по build.license.

Оптимизация сборки ​

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

Разделение кода CSS ​

Vite автоматически извлекает CSS, используемый модулями в асинхронном чанке, и генерирует для него отдельный файл. CSS-файл автоматически загружается через тег <link> при загрузке связанного асинхронного чанка, и гарантируется, что асинхронный чанк будет оценён только после загрузки CSS, чтобы избежать FOUC.

Если вы предпочитаете, чтобы весь CSS был извлечен в один файл, вы можете отключить разделение кода CSS, установив build.cssCodeSplit в false.

Генерация директив предварительной загрузки ​

Vite автоматически генерирует директивы <link rel="modulepreload"> для входных фрагментов и их прямого импорта в собранном HTML.

Оптимизация асинхронной загрузки чанков ​

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

Вход асинхронный чанк A общий чанк C асинхронный чанк B динамический импорт прямой импорт

В неоптимизированных сценариях, когда импортируется асинхронный чанк A, браузеру необходимо запросить и разобрать A, прежде чем он сможет понять, что ему также нужен общий чанк C. Это приводит к дополнительной сетевой задержке:

Вход ---> A ---> C

Vite автоматически переписывает вызовы динамического импорта с разделением кода, добавляя шаг предварительной загрузки, так что когда A запрашивается, C загружается параллельно:

Вход ---> (A + C)

Возможно, что у C есть дальнейшие импорты, что приведёт к ещё большему количеству задержек в неоптимизированном сценарии. Оптимизация Vite отслеживает все прямые импорты, чтобы полностью устранить задержки независимо от глубины импорта.

Оптимизация карты импорта чанков ​

Чтобы улучшить коэффициент попадания в кэш чанков, Vite может создавать карту импорта для чанков. Это предотвращает проблему каскадной инвалидации кэша, которая характерна для ES-модулей.

Например, рассмотрим следующий сценарий:

Вход --> A ---> C

Если C обновляется, то по сути только чанк C должен быть инвалидирован. Однако, если A ссылается на C через обычный URL в статическом импорте (т. е. хэш C включён в URL), содержимое A изменяется, и поэтому A также нужно будет инвалидировать. То же самое касается Вход.

Используя функцию карты импортов, этой проблемы можно избежать. Когда эта оптимизация включена, Vite создаёт карту импорта, которая сопоставляет ID каждого чанка с его URL, и использует ID чанка в операторах import вместо URL. Таким образом, при обновлении чанка инвалидируется только обновлённый чанк, а чанки, которые на него ссылаются, останутся валидными.

Обратите внимание, что эта оптимизация в настоящее время не применяется к CSS и ресурсам. Если вы обновите ресурс, чанки, которые на него ссылаются, будут инвалидированы. Тем не менее, инвалидация не будет каскадной, и чанк, импортирующий инвалидированный чанк, не будет инвалидирован.

Чтобы включить эту функцию, установите build.chunkImportMap в true.