Skip to content

Commit

Permalink
feat: Environment API (#16471)
Browse files Browse the repository at this point in the history
Co-authored-by: Hiroshi Ogawa <[email protected]>
Co-authored-by: Dario Piotrowicz <[email protected]>
Co-authored-by: Vladimir Sheremet <[email protected]>
Co-authored-by: Arnaud Barré <[email protected]>
Co-authored-by: Anthony Fu <[email protected]>
Co-authored-by: Dominik G <[email protected]>
Co-authored-by: Igor Minar <[email protected]>
Co-authored-by: Viktor Lázár <[email protected]>
Co-authored-by: Joaquín Sánchez <[email protected]>
Co-authored-by: sapphi-red <[email protected]>
Co-authored-by: bluwy <[email protected]>
  • Loading branch information
12 people authored Sep 4, 2024
1 parent ccbfc1a commit 242f550
Show file tree
Hide file tree
Showing 165 changed files with 8,602 additions and 3,878 deletions.
49 changes: 46 additions & 3 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,13 @@ export default defineConfig({
link: '/guide/philosophy',
},
{
text: 'Migration from v4',
text: 'Migration from v5',
link: '/guide/migration',
},
{
text: 'Breaking Changes',
link: '/changes/',
},
],
},
{
Expand All @@ -283,8 +287,8 @@ export default defineConfig({
link: '/guide/api-javascript',
},
{
text: 'Vite Runtime API',
link: '/guide/api-vite-runtime',
text: 'Environment API',
link: '/guide/api-environment',
},
{
text: 'Config Reference',
Expand Down Expand Up @@ -332,6 +336,45 @@ export default defineConfig({
],
},
],
'/changes/': [
{
text: 'Breaking Changes',
link: '/changes/',
},
{
text: 'Current',
items: [],
},
{
text: 'Future',
items: [
{
text: 'this.environment in Hooks',
link: '/changes/this-environment-in-hooks',
},
{
text: 'HMR hotUpdate Plugin Hook',
link: '/changes/hotupdate-hook',
},
{
text: 'Move to per-environment APIs',
link: '/changes/per-environment-apis',
},
{
text: 'SSR using ModuleRunner API',
link: '/changes/ssr-using-modulerunner',
},
{
text: 'Shared plugins during build',
link: '/changes/shared-plugins-during-build',
},
],
},
{
text: 'Past',
items: [],
},
],
},

outline: {
Expand Down
4 changes: 3 additions & 1 deletion docs/blog/announcing-vite5-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ The new API brings many benefits:

The initial idea [was proposed by Pooya Parsa](https://github.com/nuxt/vite/pull/201) and implemented by [Anthony Fu](https://github.com/antfu) as the [vite-node](https://github.com/vitest-dev/vitest/tree/main/packages/vite-node#readme) package to [power Nuxt 3 Dev SSR](https://antfu.me/posts/dev-ssr-on-nuxt) and later also used as the base for [Vitest](https://vitest.dev). So the general idea of vite-node has been battle-tested for quite some time now. This is a new iteration of the API by [Vladimir Sheremet](https://github.com/sheremet-va), who had already re-implemented vite-node in Vitest and took the learnings to make the API even more powerful and flexible when adding it to Vite Core. The PR was one year in the makings, you can see the evolution and discussions with ecosystem maintainers [here](https://github.com/vitejs/vite/issues/12165).

Read more in the [Vite Runtime API guide](/guide/api-vite-runtime) and [give us feedback](https://github.com/vitejs/vite/discussions/15774).
::: info
The Vite Runtime API evolved into the Module Runner API, released in Vite 6 as part of the [Environment API](/guide/api-environment).
:::

## Features

Expand Down
122 changes: 122 additions & 0 deletions docs/changes/hotupdate-hook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# HMR `hotUpdate` Plugin Hook

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

We're planning to deprecate the `handleHotUpdate` plugin hook in favor of [`hotUpdate` hook](/guide/api-environment#the-hotupdate-hook) to be [Environment API](/guide/api-environment.md) aware, and handle additional watch events with `create` and `delete`.

Affected scope: `Vite Plugin Authors`

::: warning Future Deprecation
`hotUpdate` was first introduced in `v6.0`. The deprecation of `handleHotUpdate` is planned for `v7.0`. We don't yet recommend moving away from `handleHotUpdate` yet. If you want to experiment and give us feedback, you can use the `future.removePluginHookHandleHotUpdate` to `"warn"` in your vite config.
:::

## Motivation

The [`handleHotUpdate` hook](/guide/api-plugin.md#handlehotupdate) allows to perform custom HMR update handling. A list of modules to be updated is passed in the `HmrContext`

```ts
interface HmrContext {
file: string
timestamp: number
modules: Array<ModuleNode>
read: () => string | Promise<string>
server: ViteDevServer
}
```

This hook is called once for all environments, and the passed modules have mixed information from the Client and SSR environments only. Once frameworks move to custom environments, a new hook that is called for each of them is needed.

The new `hotUpdate` hook works in the same way as `handleHotUpdate` but it is called for each environment and receives a new `HotUpdateContext` instance:

```ts
interface HotUpdateContext {
type: 'create' | 'update' | 'delete'
file: string
timestamp: number
modules: Array<EnvironmentModuleNode>
read: () => string | Promise<string>
server: ViteDevServer
}
```

The current dev environment can be accessed like in other Plugin hooks with `this.environment`. The `modules` list will now be module nodes from the current environment only. Each environment update can define different update strategies.

This hook is also now called for additional watch events and not only for `'update'`. Use `type` to differentiate between them.

## Migration Guide

Filter and narrow down the affected module list so that the HMR is more accurate.

```js
handleHotUpdate({ modules }) {
return modules.filter(condition)
}

// Migrate to:

hotUpdate({ modules }) {
return modules.filter(condition)
}
```

Return an empty array and perform a full reload:

```js
handleHotUpdate({ server, modules, timestamp }) {
// Invalidate modules manually
const invalidatedModules = new Set()
for (const mod of modules) {
server.moduleGraph.invalidateModule(
mod,
invalidatedModules,
timestamp,
true
)
}
server.ws.send({ type: 'full-reload' })
return []
}

// Migrate to:

hotUpdate({ modules, timestamp }) {
// Invalidate modules manually
const invalidatedModules = new Set()
for (const mod of modules) {
this.environment.moduleGraph.invalidateModule(
mod,
invalidatedModules,
timestamp,
true
)
}
this.environment.hot.send({ type: 'full-reload' })
return []
}
```

Return an empty array and perform complete custom HMR handling by sending custom events to the client:

```js
handleHotUpdate({ server }) {
server.ws.send({
type: 'custom',
event: 'special-update',
data: {}
})
return []
}

// Migrate to...

hotUpdate() {
this.environment.hot.send({
type: 'custom',
event: 'special-update',
data: {}
})
return []
}
```
27 changes: 27 additions & 0 deletions docs/changes/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Breaking Changes

List of breaking changes in Vite including API deprecations, removals, and changes. Most of the changes below can be opt-in using the [`future` option](/config/shared-options.html#future) in your Vite config.

## Planned

These changes are planned for the next major version of Vite. The deprecation or usage warnings will guide you where possible, and we're reaching out to framework, plugin authors, and users to apply these changes.

- _No planned changes yet_

## Considering

These changes are being considered and are often experimental APIs that intend to improve upon current usage patterns. As not all changes are listed here, please check out the [Experimental Label in Vite GitHub Discussions](https://github.com/vitejs/vite/discussions/categories/feedback?discussions_q=label%3Aexperimental+category%3AFeedback) for the full list.

We don't recommend switching to these APIs yet. They are included in Vite to help us gather feedback. Please check these proposals and let us know how they work in your use case in each's linked GitHub Discussions.

- [`this.environment` in Hooks](/changes/this-environment-in-hooks)
- [HMR `hotUpdate` Plugin Hook](/changes/hotupdate-hook)
- [Move to per-environment APIs](/changes/per-environment-apis)
- [SSR using `ModuleRunner` API](/changes/ssr-using-modulerunner)
- [Shared plugins during build](/changes/shared-plugins-during-build)

## Past

The changes below has been done or reverted. They are no longer relevant in the current major version.

- _No past changes yet_
33 changes: 33 additions & 0 deletions docs/changes/per-environment-apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Move to per-environment APIs

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

Multiple APIs from ViteDevServer related to module graph has replaced with more isolated Environment APIs.

- `server.moduleGraph` -> [`environment.moduleGraph`](/guide/api-environment#separate-module-graphs)
- `server.transformRequest` -> `environment.transformRequest`
- `server.warmupRequest` -> `environment.warmupRequest`

Affect scope: `Vite Plugin Authors`

::: warning Future Deprecation
The Environment instance was first introduced at `v6.0`. The deprecation of `server.moduleGraph` and other methods that are now in environments is planned for `v7.0`. We don't recommend moving away from server methods yet. To identify your usage, set these in your vite config.

```ts
future: {
removeServerModuleGraph: 'warn',
removeServerTransformRequest: 'warn',
}
```

:::

## Motivation

// TODO:

## Migration Guide

// TODO:
22 changes: 22 additions & 0 deletions docs/changes/shared-plugins-during-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Shared Plugins during Build

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

// TODO:
See [Shared plugins during build](/guide/api-environment.md#shared-plugins-during-build).

Affect scope: `Vite Plugin Authors`

::: warning Future Default Change
`builder.sharedConfigBuild` was first introduce in `v6.0`. You can set it true to check how your plugins work with a shared config. We're looking for feedback about changing the default in a future major once the plugin ecosystem is ready.
:::

## Motivation

// TODO:

## Migration Guide

// TODO:
21 changes: 21 additions & 0 deletions docs/changes/ssr-using-modulerunner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SSR using `ModuleRunner` API

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

`server.ssrLoadModule` has been replaced by [Module Runner](/guide/api-environment#modulerunner).

Affect scope: `Vite Plugin Authors`

::: warning Future Deprecation
`ModuleRunner` was first introduce in `v6.0`. The deprecation of `server.ssrLoadModule` is planned for a future major. To identify your usage, set `future.removeSrLoadModule` to `"warn"` in your vite config.
:::

## Motivation

// TODO:

## Migration Guide

// TODO:
43 changes: 43 additions & 0 deletions docs/changes/this-environment-in-hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# `this.environment` in Hooks

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

Before Vite 6, only two environments were available: `client` and `ssr`. A single `options.ssr` plugin hook argument in `resolveId`, `load` and `transform` allowed plugin authors to differentiate between these two environments when processing modules in plugin hooks. In Vite 6, a Vite application can define any number of named environments as needed. We're introducing `this.environment` in the plugin context to interact with the environment of the current module in hooks.

Affect scope: `Vite Plugin Authors`

::: warning Future Deprecation
`this.environment` was introduced in `v6.0`. The deprecation of `options.ssr` is planned for `v7.0`. At that point we'll start recommending migrating your plugins to use the new API. To identify your usage, set `future.removePluginHookSsrArgument` to `"warn"` in your vite config.
:::

## Motivation

`this.environment` not only allow the plugin hook implementation to know the current environment name, it also gives access to the environment config options, module graph information, and transform pipeline (`environment.config`, `environment.moduleGraph`, `environment.transformRequest()`). Having the environment instance available in the context allows plugin authors to avoid the dependency of the whole dev server (typically cached at startup through the `configureServer` hook).

## Migration Guide

For the existing plugin to do a quick migration, replace the `options.ssr` argument with `this.environment.name !== 'client'` in the `resolveId`, `load` and `transform` hooks:

```ts
import { Plugin } from 'vite'

export function myPlugin(): Plugin {
return {
name: 'my-plugin',
resolveId(id, importer, options) {
const isSSR = options.ssr // [!code --]
const isSSR = this.environment.name !== 'client' // [!code ++]

if (isSSR) {
// SSR specific logic
} else {
// Client specific logic
}
},
}
}
```

For a more robust long term implementation, the plugin hook should handle for [multiple environments](/guide/api-environment.html#accessing-the-current-environment-in-hooks) using fine-grained environment options instead of relying on the environment name.
9 changes: 8 additions & 1 deletion docs/config/build-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,19 @@ When set to `true`, the build will also generate an SSR manifest for determining

Produce SSR-oriented build. The value can be a string to directly specify the SSR entry, or `true`, which requires specifying the SSR entry via `rollupOptions.input`.

## build.emitAssets

- **Type:** `boolean`
- **Default:** `false`

During non-client builds, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in other environments build. It is responsibility of the framework to merge the assets with a post build step.

## build.ssrEmitAssets

- **Type:** `boolean`
- **Default:** `false`

During the SSR build, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in both the client and SSR build. It is responsibility of the framework to merge the assets with a post build step.
During the SSR build, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in both the client and SSR build. It is responsibility of the framework to merge the assets with a post build step. This option will be replaced by `build.emitAssets` once Environment API is stable.

## build.minify

Expand Down
9 changes: 9 additions & 0 deletions docs/config/shared-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -490,3 +490,12 @@ Whether your application is a Single Page Application (SPA), a [Multi Page Appli
- `'custom'`: don't include HTML middlewares

Learn more in Vite's [SSR guide](/guide/ssr#vite-cli). Related: [`server.middlewareMode`](./server-options#server-middlewaremode).

## future

- **Type:** `Record<string, 'warn' | undefined>`
- **Related:** [Breaking Changes](/changes/)

Enable future breaking changes to prepare for a smooth migration to the next major version of Vite. The list may be updated, added, or removed at any time as new features are developed.

See the [Breaking Changes](/changes/) page for details of the possible options.
Loading

0 comments on commit 242f550

Please sign in to comment.