> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/vitejs/vite/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Vite Features

> Learn about Vite's core features including dependency pre-bundling, HMR, TypeScript support, and more

At the very basic level, developing using Vite is not that different from using a static file server. However, Vite provides many enhancements over native ESM imports to support various features that are typically seen in bundler-based setups.

## npm Dependency Resolving and Pre-Bundling

Native ES imports do not support bare module imports like the following:

```js theme={null}
import { someMethod } from 'my-dep'
```

The above import will throw an error in the browser. Vite will detect such bare module imports in all served source files and perform the following:

1. [Pre-bundle](/concepts/dependency-pre-bundling) them to improve page loading speed and convert CommonJS / UMD modules to ESM. The pre-bundling step is performed with [esbuild](https://esbuild.github.io/) and makes Vite's cold start time significantly faster than any JavaScript-based bundler.

2. Rewrite the imports to valid URLs like `/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd` so that the browser can import them properly.

<Warning>
  **Dependencies are Strongly Cached**

  Vite caches dependency requests via HTTP headers, so if you wish to locally edit/debug a dependency, follow the steps in the [dependency pre-bundling guide](/concepts/dependency-pre-bundling#browser-cache).
</Warning>

## Hot Module Replacement

Vite provides an HMR API over native ESM. Frameworks with HMR capabilities can leverage the API to provide instant, precise updates without reloading the page or blowing away application state. Vite provides first-party HMR integrations for:

* [Vue Single File Components](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue)
* [React Fast Refresh](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react)
* Official integrations for Preact via [@prefresh/vite](https://github.com/JoviDeCroock/prefresh/tree/main/packages/vite)

<Note>
  You don't need to manually set these up - when you create an app via `create-vite`, the selected templates would have these pre-configured for you already.
</Note>

## TypeScript

Vite supports importing `.ts` files out of the box.

### Transpile Only

Note that Vite only performs transpilation on `.ts` files and does **NOT** perform type checking. It assumes type checking is taken care of by your IDE and build process.

The reason Vite does not perform type checking as part of the transform process is because the two jobs work fundamentally differently. Transpilation can work on a per-file basis and aligns perfectly with Vite's on-demand compile model. In comparison, type checking requires knowledge of the entire module graph. Shoe-horning type checking into Vite's transform pipeline will inevitably compromise Vite's speed benefits.

Vite's job is to get your source modules into a form that can run in the browser as fast as possible. To that end, we recommend separating static analysis checks from Vite's transform pipeline. This principle applies to other static analysis checks such as ESLint.

<Tabs>
  <Tab title="Production Builds">
    For production builds, you can run `tsc --noEmit` in addition to Vite's build command.
  </Tab>

  <Tab title="Development">
    During development, if you need more than IDE hints, we recommend running `tsc --noEmit --watch` in a separate process, or use [vite-plugin-checker](https://github.com/fi3ework/vite-plugin-checker) if you prefer having type errors directly reported in the browser.
  </Tab>
</Tabs>

Vite uses [esbuild](https://github.com/evanw/esbuild) to transpile TypeScript into JavaScript which is about 20\~30x faster than vanilla `tsc`, and HMR updates can reflect in the browser in under 50ms.

Use the [Type-Only Imports and Export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax to avoid potential problems like type-only imports being incorrectly bundled:

```ts theme={null}
import type { T } from 'only/types'
export type { T }
```

### TypeScript Compiler Options

Vite respects some of the options in `tsconfig.json` and sets the corresponding esbuild options. For each file, Vite uses the `tsconfig.json` in the closest parent directory.

When the options are set in both the Vite config and the `tsconfig.json`, the value in the Vite config takes precedence.

Some configuration fields under `compilerOptions` in `tsconfig.json` require special attention:

#### `isolatedModules`

Should be set to `true`.

It is because `esbuild` only performs transpilation without type information, it doesn't support certain features like const enum and implicit type-only imports.

You must set `"isolatedModules": true` in your `tsconfig.json` under `compilerOptions`, so that TS will warn you against the features that do not work with isolated transpilation.

<Tip>
  If a dependency doesn't work well with `"isolatedModules": true`, you can use `"skipLibCheck": true` to temporarily suppress the errors until it is fixed upstream.
</Tip>

#### `useDefineForClassFields`

The default value will be `true` if the TypeScript target is `ES2022` or newer including `ESNext`. It is consistent with the behavior of TypeScript 4.3.2+. Other TypeScript targets will default to `false`.

`true` is the standard ECMAScript runtime behavior.

If you are using a library that heavily relies on class fields, please be careful about the library's intended usage of it. While most libraries expect `"useDefineForClassFields": true`, you can explicitly set `useDefineForClassFields` to `false` if your library doesn't support it.

### Client Types

Vite's default types are for its Node.js API. To shim the environment of client-side code in a Vite application, you can add `vite/client` to `compilerOptions.types` inside `tsconfig.json`:

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

<Info>
  Note that if `compilerOptions.types` is specified, only these packages will be included in the global scope (instead of all visible "@types" packages). This is recommended since TS 5.9.
</Info>

`vite/client` provides the following type shims:

* Asset imports (e.g. importing an `.svg` file)
* Types for the Vite-injected constants on `import.meta.env`
* Types for the HMR API on `import.meta.hot`

## HTML

HTML files stand front-and-center of a Vite project, serving as the entry points for your application, making it simple to build single-page and multi-page applications.

Any HTML files in your project root can be directly accessed by its respective directory path:

* `<root>/index.html` → `http://localhost:5173/`
* `<root>/about.html` → `http://localhost:5173/about.html`
* `<root>/blog/index.html` → `http://localhost:5173/blog/index.html`

Assets referenced by HTML elements such as `<script type="module" src>` and `<link href>` are processed and bundled as part of the app. The full list of supported elements are:

* `<audio src>`
* `<embed src>`
* `<img src>` and `<img srcset>`
* `<image href>` and `<image xlink:href>`
* `<input src>`
* `<link href>` and `<link imagesrcset>`
* `<object data>`
* `<script type="module" src>`
* `<source src>` and `<source srcset>`
* `<track src>`
* `<use href>` and `<use xlink:href>`
* `<video src>` and `<video poster>`
* `<meta content>` (with specific attributes)

```html theme={null}
<!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>
```

<Tip>
  To opt-out of HTML processing on certain elements, you can add the `vite-ignore` attribute on the element, which can be useful when referencing external assets or CDN.
</Tip>

## CSS

Importing `.css` files will inject its content to the page via a `<style>` tag with HMR support.

### `@import` Inlining and Rebasing

Vite is pre-configured to support CSS `@import` inlining via `postcss-import`. Vite aliases are also respected for CSS `@import`. In addition, all CSS `url()` references, even if the imported files are in different directories, are always automatically rebased to ensure correctness.

`@import` aliases and URL rebasing are also supported for Sass and Less files.

### PostCSS

If the project contains valid PostCSS config (any format supported by [postcss-load-config](https://github.com/postcss/postcss-load-config), e.g. `postcss.config.js`), it will be automatically applied to all imported CSS.

<Note>
  CSS minification will run after PostCSS and will use the `build.cssTarget` option.
</Note>

### CSS Modules

Any CSS file ending with `.module.css` is considered a CSS modules file. Importing such a file will return the corresponding module object:

<CodeGroup>
  ```css example.module.css theme={null}
  .red {
    color: red;
  }
  ```

  ```js theme={null}
  import classes from './example.module.css'
  document.getElementById('foo').className = classes.red
  ```
</CodeGroup>

CSS modules behavior can be configured via the `css.modules` option.

If `css.modules.localsConvention` is set to enable camelCase locals (e.g. `localsConvention: 'camelCaseOnly'`), you can also use named imports:

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

### CSS Pre-processors

Because Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. [postcss-nesting](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting)) and author plain, future-standards-compliant CSS.

That said, Vite does provide built-in support for `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed:

```bash theme={null}
# .scss and .sass
npm add -D sass-embedded # or sass

# .less
npm add -D less

# .styl and .stylus
npm add -D stylus
```

<Info>
  If using Vue single file components, this also automatically enables `<style lang="sass">` et al.
</Info>

## JSON

JSON files can be directly imported - named imports are also supported:

```js theme={null}
// 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 Import

Vite supports importing multiple modules from the file system via the special `import.meta.glob` function:

```js theme={null}
const modules = import.meta.glob('./dir/*.js')
```

The above will be transformed into the following:

```js theme={null}
// code produced by vite
const modules = {
  './dir/bar.js': () => import('./dir/bar.js'),
  './dir/foo.js': () => import('./dir/foo.js'),
}
```

You can then iterate over the keys of the `modules` object to access the corresponding modules:

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

Matched files are by default lazy-loaded via dynamic import and will be split into separate chunks during build. If you'd rather import all the modules directly (e.g. relying on side-effects in these modules to be applied first), you can pass `{ eager: true }` as the second argument:

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

### Glob Import Features

<Tabs>
  <Tab title="Multiple Patterns">
    The first argument can be an array of globs:

    ```js theme={null}
    const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
    ```
  </Tab>

  <Tab title="Negative Patterns">
    Negative glob patterns are also supported (prefixed with `!`). To ignore some files from the result, you can add exclude glob patterns to the first argument:

    ```js theme={null}
    const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
    ```
  </Tab>

  <Tab title="Named Imports">
    It's possible to only import parts of the modules with the `import` options:

    ```ts theme={null}
    const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
    ```

    When combined with `eager` it's even possible to have tree-shaking enabled for those modules.
  </Tab>
</Tabs>

<Warning>
  **Glob Import Caveats**

  * This is a Vite-only feature and is not a web or ES standard.
  * The glob patterns are treated like import specifiers: they must be either relative (start with `./`) or absolute (start with `/`, resolved relative to project root) or an alias path.
  * The glob matching is done via `tinyglobby` - check out its documentation for supported glob patterns.
  * You should also be aware that all the arguments in the `import.meta.glob` must be **passed as literals**. You can NOT use variables or expressions in them.
</Warning>

## WebAssembly

Pre-compiled `.wasm` files can be imported with `?init`. The default export will be an initialization function that returns a Promise of the `WebAssembly.Instance`:

```js theme={null}
import init from './example.wasm?init'

init().then((instance) => {
  instance.exports.test()
})
```

The init function can also take an importObject which is passed along to `WebAssembly.instantiate` as its second argument:

```js theme={null}
import init from './example.wasm?init'

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

<Info>
  In the production build, `.wasm` files smaller than `assetInlineLimit` will be inlined as base64 strings. Otherwise, they will be treated as a static asset and fetched on-demand.
</Info>

<Warning>
  ES Module Integration Proposal for WebAssembly is not currently supported. Use `vite-plugin-wasm` or other community plugins to handle this.

  For SSR build, Node.js compatible runtimes are only supported due to the lack of a universal way to load a file.
</Warning>

## Web Workers

### Import with Constructors

A web worker script can be imported using `new Worker()` and `new SharedWorker()`. Compared to the worker suffixes, this syntax leans closer to the standards and is the **recommended** way to create workers.

```ts theme={null}
const worker = new Worker(new URL('./worker.js', import.meta.url))
```

The worker constructor also accepts options, which can be used to create "module" workers:

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

<Note>
  The worker detection will only work if the `new URL()` constructor is used directly inside the `new Worker()` declaration. Additionally, all options parameters must be static values (i.e. string literals).
</Note>

### Import with Query Suffixes

A web worker script can be directly imported by appending `?worker` or `?sharedworker` to the import request. The default export will be a custom worker constructor:

```js theme={null}
import MyWorker from './worker?worker'

const worker = new MyWorker()
```

<Info>
  The worker script can also use ESM `import` statements instead of `importScripts()`. **Note**: During development this relies on browser native support, but for the production build it is compiled away.
</Info>

By default, the worker script will be emitted as a separate chunk in the production build. If you wish to inline the worker as base64 strings, add the `inline` query:

```js theme={null}
import MyWorker from './worker?worker&inline'
```

If you wish to retrieve the worker as a URL, add the `url` query:

```js theme={null}
import MyWorker from './worker?worker&url'
```

## Content Security Policy (CSP)

To deploy CSP, certain directives or configs must be set due to Vite's internals.

### `'nonce-{RANDOM}'`

When `html.cspNonce` is set, Vite adds a nonce attribute with the specified value to any `<script>` and `<style>` tags, as well as `<link>` tags for stylesheets and module preloading. Additionally, when this option is set, Vite will inject a meta tag (`<meta property="csp-nonce" nonce="PLACEHOLDER" />`).

The nonce value of a meta tag with `property="csp-nonce"` will be used by Vite whenever necessary during both dev and after build.

<Warning>
  Ensure that you replace the placeholder with a unique value for each request. This is important to prevent bypassing a resource's policy, which can otherwise be easily done.
</Warning>

### `data:` URIs

By default, during build, Vite inlines small assets as data URIs. Allowing `data:` for related directives (e.g. `img-src`, `font-src`), or, disabling it by setting `build.assetsInlineLimit: 0` is necessary.

<Warning>
  Do not allow `data:` for `script-src`. It will allow injection of arbitrary scripts.
</Warning>

## Build Optimizations

<Info>
  Features listed below are automatically applied as part of the build process and there is no need for explicit configuration unless you want to disable them.
</Info>

### CSS Code Splitting

Vite automatically extracts the CSS used by modules in an async chunk and generates a separate file for it. The CSS file is automatically loaded via a `<link>` tag when the associated async chunk is loaded, and the async chunk is guaranteed to only be evaluated after the CSS is loaded to avoid FOUC.

If you'd rather have all the CSS extracted into a single file, you can disable CSS code splitting by setting `build.cssCodeSplit` to `false`.

### Preload Directives Generation

Vite automatically generates `<link rel="modulepreload">` directives for entry chunks and their direct imports in the built HTML.

### Async Chunk Loading Optimization

In real world applications, Rollup often generates "common" chunks - code that is shared between two or more other chunks. Combined with dynamic imports, it is quite common to have the following scenario:

```
Entry ---> A ---> C
```

In the non-optimized scenarios, when async chunk `A` is imported, the browser will have to request and parse `A` before it can figure out that it also needs the common chunk `C`. This results in an extra network roundtrip.

Vite automatically rewrites code-split dynamic import calls with a preload step so that when `A` is requested, `C` is fetched **in parallel**:

```
Entry ---> (A + C)
```

<Tip>
  It is possible for `C` to have further imports, which will result in even more roundtrips in the un-optimized scenario. Vite's optimization will trace all the direct imports to completely eliminate the roundtrips regardless of import depth.
</Tip>
