Функции
На самом базовом уровне разработка с использованием Vite не сильно отличается от использования статического файлового сервера. Тем не менее, Vite предоставляет множество улучшений по сравнению с собственным импортом ESM для поддержки различных функций, которые обычно встречаются в установках на основе сборщиков.
Разрешение зависимостей NPM и предварительное связывание
Собственный импорт ES не поддерживает импорт голых модулей, например:
import { someMethod } from 'my-dep'
Приведенное выше вызовет ошибку в браузере. Vite обнаружит такой импорт голых модулей во всех обслуживаемых исходных файлах и выполнит следующее:
Pre-bundle их для повышения скорости загрузки страницы и преобразования модулей CommonJS / UMD в ESM. Этап предварительной сборки выполняется с помощью esbuild и значительно ускоряет время холодного запуска Vite по сравнению с любым сборщиком на основе JavaScript.
Перепишите импорт на действительные URL-адреса, такие как
/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd
, чтобы браузер мог их правильно импортировать.
Зависимости сильно кэшируются
Vite кэширует запросы зависимостей через заголовки HTTP, поэтому, если вы хотите локально отредактировать/отладить зависимость, выполните шаги здесь.
Горячая Замена Модуля (HMR)
Vite предоставляет HMR API поверх собственного ESM. Платформы с возможностями HMR могут использовать API для предоставления мгновенных и точных обновлений без перезагрузки страницы или стирания состояния приложения. Vite предоставляет сторонние интеграции HMR для Vue Single File Components и 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 использует esbuild для преобразования TypeScript в JavaScript, что примерно в 20–30 раз быстрее, чем ванильный tsc
, а обновления HMR могут отображаться в браузере менее чем за 50 мс.
Используйте синтаксис Импорт и экспорт только для типа, чтобы избежать потенциальных проблем, таких как неправильный пакет импорта только для типа, например:
import type { T } from 'only/types'
export type { T }
Параметры компилятора TypeScript
Некоторые поля конфигурации в разделе compilerOptions
в tsconfig.json
требуют особого внимания.
isolatedModules
Должно быть установлено значение true
.
Это связано с тем, что esbuild
выполняет транспиляцию только без информации о типе, он не поддерживает некоторые функции, такие как const enum и неявный импорт только типов.
Вы должны установить "isolatedModules": true
в вашем tsconfig.json
в разделе compilerOptions
, чтобы TS предупредил вас о функциях, которые не работают с изолированной транспиляцией.
Однако некоторые библиотеки (например, vue
) плохо работают с "isolatedModules": true
. Вы можете использовать "skipLibCheck": true
, чтобы временно подавить ошибки, пока они не будут исправлены вышестоящим.
useDefineForClassFields
Начиная с Vite 2.5.0, значением по умолчанию будет true
, если целью TypeScript является ESNext
или ES2022
или новее. Это соответствует поведению tsc
4.3.2 и более поздних версий. Это также стандартное поведение среды выполнения ECMAScript.
Другие цели TypeScript по умолчанию будут иметь значение false
.
Но это может показаться нелогичным для тех, кто работает с другими языками программирования или более старыми версиями TypeScript. Подробнее о переходе можно прочитать в примечаниях к выпуску TypeScript 3.7.
Если вы используете библиотеку, которая сильно зависит от полей класса, будьте осторожны с ее предполагаемым использованием библиотекой.
Большинство библиотек ожидают "useDefineForClassFields": true
, например, MobX.
Но несколько библиотек еще не перешли на это новое значение по умолчанию, в том числе lit-element
. В этих случаях явно установите для useDefineForClassFields
значение false
.
target
Vite не транспилирует TypeScript с настроенным значением target
по умолчанию, следуя тому же поведению, что и esbuild
.
Вместо этого можно использовать параметр esbuild.target
, который по умолчанию имеет значение esnext
для минимальной транспиляции. В сборках параметр build.target
имеет более высокий приоритет и также может быть установлен при необходимости.
useDefineForClassFields
Если target
не ESNext
или ES2022
или новее, или если файл tsconfig.json
отсутствует, для useDefineForClassFields
по умолчанию будет установлено значение false
, что может быть проблематичным со значением esbuild.target
по умолчанию esnext
. Он может передаваться в статические блоки инициализации, которые могут не поддерживаться вашим браузером.
Таким образом, рекомендуется установить для параметра target
значением ESNext
или ES2022
или новее или явно установить для useDefineForClassFields
значение true
при настройке tsconfig.json
.
Другие параметры компилятора, влияющие на результат сборки
extends
importsNotUsedAsValues
preserveValueImports
verbatimModuleSyntax
jsx
jsxFactory
jsxFragmentFactory
jsxImportSource
experimentalDecorators
alwaysStrict
skipLibCheck
Стартовые шаблоны Vite по умолчанию имеют "skipLibCheck": "true"
, чтобы избежать зависимостей проверки типов, поскольку они могут поддерживать только определенные версии и конфигурации TypeScript. Вы можете узнать больше по адресу vuejs/vue-cli#5688.
Клиентские типы
Типы Vite по умолчанию предназначены для его API Node.js. Чтобы изменить среду кода на стороне клиента в приложении Vite, добавьте файл объявления d.ts
:
/// <reference types="vite/client" />
Альтернативно, вы можете добавить vite/client
в compilerOptions.types
внутри tsconfig.json
:
{
"compilerOptions": {
"types": ["vite/client"]
}
}
Это обеспечит следующие типы прокладок:
- Импорт ассетов (например, импорт файла
.svg
) - Типы для Vite-injected переменных env в
import.meta.env
- Типы для HMR API в
import.meta.hot
TIP
Чтобы переопределить типизацию по умолчанию, добавьте файл определения типа, содержащий ваши типизации. Затем добавьте ссылку на тип перед vite/client
.
Например, чтобы сделать импорт *.svg
по умолчанию компонентом React:
vite-env-override.d.ts
(файл, содержащий ваши наборы текста):tsdeclare module '*.svg' { const content: React.FC<React.SVGProps<SVGElement>> export default content }
- Файл, содержащий ссылку на
vite/client
:ts/// <reference types="./vite-env-override.d.ts" /> /// <reference types="vite/client" />
Vue
Vite обеспечивает первоклассную поддержку Vue:
- Поддержка Vue 3 SFC через @vitejs/plugin-vue
- Поддержка Vue 3 JSX через @vitejs/plugin-vue-jsx
- Поддержка Vue 2.7 SFC через @vitejs/plugin-vue2
- Поддержка Vue 2.7 JSX через @vitejs/plugin-vue2-jsx
JSX
Файлы .jsx
и .tsx
также поддерживаются по умолчанию. Транспиляция JSX также выполняется через esbuild.
Пользователи Vue должны использовать официальный плагин @vitejs/plugin-vue-jsx, который предоставляет Vue 3 специальные функции, включая HMR, глобальное разрешение компонентов, директивы и слоты.
Если JSX не используется с React или Vue, пользовательские jsxFactory
и jsxFragment
можно настроить с помощью параметра esbuild
. Например, для Preact:
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxFactory: 'h',
jsxFragment: 'Fragment',
},
})
Подробнее в документации esbuild.
Вы можете внедрить помощники JSX с помощью jsxInject
(это опция только для Vite), чтобы избежать ручного импорта:
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxInject: `import React from 'react'`,
},
})
CSS
При импорте файлов .css
их содержимое будет добавлено на страницу через тег <style>
с поддержкой HMR.
@import
Inlining и Rebasing
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 */
.red {
color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red
Поведение модулей CSS можно настроить с помощью параметра css.modules
.
Если css.modules.localsConvention
настроен на включение локальных переменных camelCase (например, localsConvention: 'camelCaseOnly'
), вы также можете использовать именованный импорт:
// .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 плагины, но сам соответствующий препроцессор должен быть установлен:
# .scss and .sass
npm add -D sass
# .less
npm add -D less
# .styl and .stylus
npm add -D stylus
При использовании однофайловых компонентов Vue это также автоматически включает <style lang="sass">
и др.
Vite улучшает разрешение @import
для Sass и Less, так что псевдонимы Vite также учитываются. Кроме того, относительные ссылки url()
внутри импортированных файлов Sass/Less, которые находятся в каталогах, отличных от корневого файла, также автоматически переустанавливаются для обеспечения корректности.
Перемещение псевдонимов и URL-адресов @import
не поддерживается для Stylus из-за ограничений его API.
Вы также можете использовать модули CSS в сочетании с препроцессорами, добавив .module
к расширению файла, например, style.module.scss
.
Отключение внедрения CSS на страницу
Автоматическое внедрение содержимого CSS можно отключить с помощью параметра запроса ?inline
. В этом случае обработанная строка CSS возвращается как экспорт модуля по умолчанию, как обычно, но стили не внедряются на страницу.
import './foo.css' // will be injected into the page
import otherStyles from './bar.css?inline' // will not be injected
ПРИМЕЧАНИЕ
Импорт по умолчанию и именованный импорт из файлов CSS (например, import style from './foo.css'
) удален, начиная с Vite 5. Вместо этого используйте запрос ?inline
.
Lightning CSS
Начиная с Vite 4.4 существует экспериментальная поддержка Lightning CSS. Вы можете принять его, добавив css.transformer: 'lightningcss'
в свой файл конфигурации и установив дополнительную зависимость lightningcss
:
npm add -D lightningcss
Если этот параметр включен, файлы CSS будут обрабатываться с помощью Lightning CSS вместо PostCSS. Чтобы настроить его, вы можете передать параметры Lightning CSS в параметр конфигурации css.lightningcss
.
Чтобы настроить модули CSS, вы будете использовать css.lightningcss.cssModules
вместо css.modules
(который настраивает способ обработки PostCSS модулей CSS).
По умолчанию Vite использует esbuild для минимизации CSS. Lightning CSS также можно использовать в качестве минификатора CSS с помощью build.cssMinify: 'lightningcss'
.
ПРИМЕЧАНИЕ
Препроцессоры CSS не поддерживаются при использовании Lightning CSS.
Статические ресурсы
Импорт статического ресурса вернет разрешенный общедоступный URL-адрес при его обслуживании:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
Специальные запросы могут изменить способ загрузки ресурсов:
// Explicitly load assets as URL
import assetAsURL from './asset.js?url'
// Load assets as strings
import assetAsString from './shader.glsl?raw'
// Load Web Workers
import Worker from './worker.js?worker'
// Web Workers inlined as base64 strings at build time
import InlineWorker from './worker.js?worker&inline'
Дополнительные сведения см. в разделе Обработка статических ресурсов.
JSON
Файлы JSON можно импортировать напрямую — также поддерживается именованный импорт:
// import the entire object
import json from './example.json'
// import a root field as named exports - helps with tree-shaking!
import { field } from './example.json'
Импорт Glob
Vite поддерживает импорт нескольких модулей из файловой системы с помощью специальной функции import.meta.glob
:
const modules = import.meta.glob('./dir/*.js')
Вышеупомянутое будет преобразовано в следующее:
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js'),
}
Затем вы можете перебирать ключи объекта modules
для доступа к соответствующим модулям:
for (const path in modules) {
modules[path]().then((mod) => {
console.log(path, mod)
})
}
Совпадающие файлы по умолчанию загружаются с помощью динамического импорта и будут разделены на отдельные фрагменты во время сборки. Если вы предпочитаете импортировать все модули напрямую (например, полагаясь на то, что побочные эффекты в этих модулях будут применены в первую очередь), вы можете передать { eager: true }
в качестве второго аргумента:
const modules = import.meta.glob('./dir/*.js', { eager: true })
Вышеупомянутое будет преобразовано в следующее:
// code produced by vite
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
Глобальный импорт как
import.meta.glob
также поддерживает импорт файлов в виде строк (аналогично Импортировать актив как строку) с помощью синтаксиса Импорт Reflection:
const modules = import.meta.glob('./dir/*.js', { as: 'raw', eager: true })
Вышеупомянутое будет преобразовано в следующее:
// code produced by vite
const modules = {
'./dir/foo.js': 'export default "foo"\n',
'./dir/bar.js': 'export default "bar"\n',
}
{ as: 'url' }
также поддерживается для загрузки ресурсов в виде URL-адресов.
Несколько шаблонов
Первый аргумент может быть глобальным массивом, например:
const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
Негативные шаблоны
Также поддерживаются негативные глобальные шаблоны (с префиксом !
). Чтобы игнорировать некоторые файлы из результата, вы можете добавить к первому аргументу глобальные шаблоны исключения:
const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
}
Именованный импорт
Можно импортировать только части модулей с параметрами import
.
const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
// code produced by vite
const modules = {
'./dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
'./dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
}
В сочетании с eager
можно даже включить встряхивание дерева для этих модулей.
const modules = import.meta.glob('./dir/*.js', {
import: 'setup',
eager: true,
})
// code produced by vite:
import { setup as __glob__0_0 } from './dir/foo.js'
import { setup as __glob__0_1 } from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
Установите для import
значение default
, чтобы импортировать экспорт по умолчанию.
const modules = import.meta.glob('./dir/*.js', {
import: 'default',
eager: true,
})
// code produced by vite:
import __glob__0_0 from './dir/foo.js'
import __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
Пользовательские запросы
Вы также можете использовать опцию query
, чтобы предоставить пользовательские запросы для импорта для использования другими плагинами.
const modules = import.meta.glob('./dir/*.js', {
query: { foo: 'bar', bar: true },
})
// code produced by vite:
const modules = {
'./dir/foo.js': () => import('./dir/foo.js?foo=bar&bar=true'),
'./dir/bar.js': () => import('./dir/bar.js?foo=bar&bar=true'),
}
Предостережения по глобальному импорту
Обратите внимание, что:
- Это функция только для Vite и не является стандартом для Интернета или ES.
- Шаблоны glob обрабатываются как спецификаторы импорта: они должны быть либо относительными (начинаться с
./
), либо абсолютными (начинаться с/
, разрешаться относительно корня проекта), либо псевдонимом пути (смотрите параметрresolve.alias
). - Сопоставление универсальных объектов выполняется с помощью
fast-glob
- ознакомьтесь с его документацией для поддерживаемых глобальных шаблонов. - Вы также должны знать, что все аргументы в
import.meta.glob
должны быть переданы как литералы. Вы НЕ можете использовать в них переменные или выражения.
Динамический импорт
Подобно glob import, Vite также поддерживает динамический импорт с переменными.
const module = await import(`./dir/${file}.js`)
Обратите внимание, что переменные представляют имена файлов только на один уровень глубины. Если file
это 'foo/bar'
, импорт завершится ошибкой. Для более продвинутого использования вы можете использовать функцию glob import.
Веб-сборка
Предварительно скомпилированные файлы .wasm
можно импортировать с помощью ?init
. Экспортом по умолчанию будет функция инициализации, которая возвращает промис WebAssembly.Instance
:
import init from './example.wasm?init'
init().then((instance) => {
instance.exports.test()
})
Функция init также может принимать объект importObject, который передается в WebAssembly.instantiate
в качестве второго аргумента:
init({
imports: {
someFunc: () => {
/* ... */
},
},
}).then(() => {
/* ... */
})
В производственной сборке файлы .wasm
размером меньше, чем assetInlineLimit
, будут встроены как строки base64. В противном случае они будут рассматриваться как статический ресурс и извлекаться по требованию.
ПРИМЕЧАНИЕ
Предложение по интеграции модуля ES для WebAssembly в настоящее время не поддерживается. Для решения этой проблемы используйте vite-plugin-wasm
или другие плагины сообщества.
Доступ к модулю WebAssembly
Если вам нужен доступ к объекту Module
, например, чтобы создать его экземпляр несколько раз, используйте импорт явного URL-адреса для разрешения ресурса, а затем выполните создание экземпляра:
import wasmUrl from 'foo.wasm?url'
const main = async () => {
const responsePromise = fetch(wasmUrl)
const { module, instance } =
await WebAssembly.instantiateStreaming(responsePromise)
/* ... */
}
main()
Получение модуля в Node.js
В SSR функция fetch()
, выполняемая как часть импорта ?init
, может завершиться неудачно с сообщением TypeError: Invalid URL
. Смотрите проблему Поддержка Wasm в SSR.
Вот альтернатива, предполагающая, что базой проекта является текущий каталог:
import wasmUrl from 'foo.wasm?url'
import { readFile } from 'node:fs/promises'
const main = async () => {
const resolvedUrl = (await import('./test/boot.test.wasm?url')).default
const buffer = await readFile('.' + resolvedUrl)
const { instance } = await WebAssembly.instantiate(buffer, {
/* ... */
})
/* ... */
}
main()
Web Workers
Импорт с помощью конструкторов
Сценарий веб-воркера можно импортировать с помощью new Worker()
и new SharedWorker()
. По сравнению с рабочими суффиксами этот синтаксис ближе к стандартам и является рекомендуемым способом создания рабочих процессов.
const worker = new Worker(new URL('./worker.js', import.meta.url))
Конструктор воркеров также принимает параметры, которые можно использовать для создания "module" вокеров:
const worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module',
})
Импорт с суффиксами запроса
Сценарий веб-воркера можно импортировать напрямую, добавив ?worker
или ?sharedworker
к запросу на импорт. Экспортом по умолчанию будет настраиваемый рабочий конструктор:
import MyWorker from './worker?worker'
const worker = new MyWorker()
Рабочий скрипт также может использовать операторы import
ESM вместо importScripts()
. Примечание: Во время разработки это зависит от встроенной поддержки браузера, но для производственной сборки он компилируется.
По умолчанию рабочий скрипт будет выпущен как отдельный блок в производственной сборке. Если вы хотите встроить worker в виде строк base64, добавьте запрос inline
:
import MyWorker from './worker?worker&inline'
Если вы хотите получить работника как URL-адрес, добавьте запрос url
:
import MyWorker from './worker?worker&url'
Смотрите Параметры работника для получения подробной информации о настройке объединения всех вокеров.
Оптимизация сборки
Перечисленные ниже функции автоматически применяются как часть процесса сборки, и нет необходимости в явной настройке, если только вы не хотите их отключить.
Разделение кода CSS
Vite автоматически извлекает CSS, используемый модулями, в асинхронный блок и создает для него отдельный файл. Файл CSS автоматически загружается с помощью тега <link>
при загрузке связанного с ним асинхронного фрагмента, а асинхронный фрагмент гарантированно будет оцениваться только после загрузки CSS, чтобы избежать FOUC.
Если вы предпочитаете, чтобы весь CSS был извлечен в один файл, вы можете отключить разделение кода CSS, установив для параметра build.cssCodeSplit
значение false
.
Генерация директив предварительной загрузки
Vite автоматически генерирует директивы <link rel="modulepreload">
для входных блоков и их прямого импорта во встроенный HTML.
Оптимизация асинхронной загрузки чанков
В реальных приложениях Rollup часто генерирует "common" фрагменты — код, который используется двумя или более другими фрагментами. В сочетании с динамическим импортом довольно часто возникает следующий сценарий:
В неоптимизированных сценариях, когда импортируется асинхронный блок A
, браузер должен будет запросить и проанализировать A
прежде чем он сможет понять, что ему также нужен общий блок C
. Это приводит к дополнительному круговому обходу сети:
Entry ---> A ---> C
Vite автоматически переписывает вызовы динамического импорта с разделением кода с шагом предварительной загрузки, так что при запросе A
извлекается C
параллельно:
Entry ---> (A + C)
Для C
возможен дальнейший импорт, что приведет к еще большему количеству обращений в оба конца в неоптимизированном сценарии. Оптимизация Vite будет отслеживать весь прямой импорт, чтобы полностью исключить двусторонние операции независимо от глубины импорта.