diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 7411edbf846b98..12ae8a255406d4 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,4 +1,5 @@ // @ts-check +const { builtinModules } = require('node:module') const { defineConfig } = require('eslint-define-config') module.exports = defineConfig({ @@ -42,18 +43,6 @@ module.exports = defineConfig({ tryExtensions: ['.ts', '.js', '.jsx', '.tsx', '.d.ts'] } ], - 'node/no-restricted-require': [ - 'error', - Object.keys(require('./packages/vite/package.json').devDependencies).map( - (d) => ({ - name: d, - message: - `devDependencies can only be imported using ESM syntax so ` + - `that they are included in the rollup bundle. If you are trying to ` + - `lazy load a dependency, use (await import('dependency')).default instead.` - }) - ) - ], 'node/no-extraneous-import': [ 'error', { @@ -93,6 +82,10 @@ module.exports = defineConfig({ { prefer: 'type-imports' } ], + 'import/no-nodejs-modules': [ + 'error', + { allow: builtinModules.map((mod) => `node:${mod}`) } + ], 'import/no-duplicates': 'error', 'import/order': 'error', 'sort-imports': [ @@ -107,6 +100,30 @@ module.exports = defineConfig({ ] }, overrides: [ + { + files: ['packages/**'], + excludedFiles: '**/__tests__/**', + rules: { + 'no-restricted-globals': ['error', 'require', '__dirname', '__filename'] + } + }, + { + files: 'packages/vite/**/*.*', + rules: { + 'node/no-restricted-require': [ + 'error', + Object.keys( + require('./packages/vite/package.json').devDependencies + ).map((d) => ({ + name: d, + message: + `devDependencies can only be imported using ESM syntax so ` + + `that they are included in the rollup bundle. If you are trying to ` + + `lazy load a dependency, use (await import('dependency')).default instead.` + })) + ] + } + }, { files: ['packages/vite/src/node/**'], rules: { @@ -120,9 +137,11 @@ module.exports = defineConfig({ } }, { - files: ['packages/plugin-*/**/*'], + files: ['packages/create-vite/template-*/**', '**/build.config.ts'], rules: { - 'no-restricted-globals': ['error', 'require', '__dirname', '__filename'] + 'no-undef': 'off', + 'node/no-missing-import': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off' } }, { @@ -132,30 +151,34 @@ module.exports = defineConfig({ 'node/no-extraneous-require': 'off', 'node/no-missing-import': 'off', 'node/no-missing-require': 'off', - 'no-undef': 'off', // engine field doesn't exist in playgrounds 'node/no-unsupported-features/es-builtins': [ 'error', { - version: '>=14.18.0' + version: '^14.18.0 || >=16.0.0' } ], 'node/no-unsupported-features/node-builtins': [ 'error', { - version: '>=14.18.0' + version: '^14.18.0 || >=16.0.0' } - ] + ], + '@typescript-eslint/explicit-module-boundary-types': 'off' } }, { - files: ['packages/create-vite/template-*/**', '**/build.config.ts'], + files: ['playground/**'], + excludedFiles: '**/__tests__/**', rules: { - 'node/no-missing-import': 'off' + 'no-undef': 'off', + 'no-empty': 'off', + 'no-constant-condition': 'off', + '@typescript-eslint/no-empty-function': 'off' } }, { - files: ['playground/**', '*.js'], + files: ['*.js'], rules: { '@typescript-eslint/explicit-module-boundary-types': 'off' } @@ -165,12 +188,6 @@ module.exports = defineConfig({ rules: { '@typescript-eslint/triple-slash-reference': 'off' } - }, - { - files: 'packages/vite/**/*.*', - rules: { - 'no-restricted-globals': ['error', 'require', '__dirname', '__filename'] - } } ], reportUnusedDisableDirectives: true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 0d84e28034a442..8c3987ca835d2d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -18,7 +18,7 @@ body: id: reproduction attributes: label: Reproduction - description: Please provide a link via [vite.new](https://vite.new/) or a link to a repo that can reproduce the problem you ran into. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required ([Why?](https://antfu.me/posts/why-reproductions-are-required)). If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided after 3 days, it will be auto-closed. + description: Please provide a link via [vite.new](https://vite.new/) or a link to a repo that can reproduce the problem you ran into. `npm create vite@latest` and `npm create vite-extra@latest` (for SSR or library repros) can be used as a starter template. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required ([Why?](https://antfu.me/posts/why-reproductions-are-required)). If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided after 3 days, it will be auto-closed. placeholder: Reproduction URL and steps validations: required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f190529faa247d..973b78df00591d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }} - name: Install Playwright - # does not need to explictly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved + # does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved run: pnpm playwright install chromium - name: Build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 65fb07f88fad9d..350f36b0f25351 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Vite Contributing Guide -Hi! We are really excited that you are interested in contributing to Vite. Before submitting your contribution, please make sure to take a moment and read through the following guide: +Hi! We're really excited that you're interested in contributing to Vite! Before submitting your contribution, please read through the following guide. ## Repo Setup @@ -8,7 +8,7 @@ The Vite repo is a monorepo using pnpm workspaces. The package manager used to i To develop and test the core `vite` package: -1. Run `pnpm i` in Vite's root folder +1. Run `pnpm i` in Vite's root folder. 2. Run `pnpm run build` in Vite's root folder. @@ -16,41 +16,41 @@ To develop and test the core `vite` package: You can alternatively use [Vite.js Docker Dev](https://github.com/nystudio107/vitejs-docker-dev) for a containerized Docker setup for Vite.js development. -> Vite uses pnpm v7. If you are working on multiple projects with different versions of pnpm, it's recommend to enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`. +> Vite uses pnpm v7. If you are working on multiple projects with different versions of pnpm, it's recommended to enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`. ## Debugging -If you want to use break point and explore code execution you can use the ["Run and debug"](https://code.visualstudio.com/docs/editor/debugging) feature from vscode. +To use breakpoints and explore code execution, you can use the ["Run and Debug"](https://code.visualstudio.com/docs/editor/debugging) feature from VS Code. 1. Add a `debugger` statement where you want to stop the code execution. -2. Click on the "Run and Debug" icon in the activity bar of the editor. +2. Click the "Run and Debug" icon in the activity bar of the editor, which opens the [_Run and Debug view_](https://code.visualstudio.com/docs/editor/debugging#_run-and-debug-view). -3. Click on the "JavaScript Debug Terminal" button. +3. Click the "JavaScript Debug Termimal" button in the _Run and Debug view_, which opens a terminal in VS Code. -4. It will open a terminal, then go to `playground/xxx` and run `pnpm run dev`. +4. From that terminal, go to `playground/xxx`, and run `pnpm run dev`. -5. The execution will stop and you'll use the [Debug toolbar](https://code.visualstudio.com/docs/editor/debugging#_debug-actions) to continue, step over, restart the process... +5. The execution will stop at the `debugger` statement, and you can use the [Debug toolbar](https://code.visualstudio.com/docs/editor/debugging#_debug-actions) to continue, step over, and restart the process... -### Debugging errors in Vitest tests using Playwright (Chromium) +### Debugging Errors in Vitest Tests Using Playwright (Chromium) Some errors are masked and hidden away because of the layers of abstraction and sandboxed nature added by Vitest, Playwright, and Chromium. In order to see what's actually going wrong and the contents of the devtools console in those instances, follow this setup: 1. Add a `debugger` statement to the `playground/vitestSetup.ts` -> `afterAll` hook. This will pause execution before the tests quit and the Playwright browser instance exits. -1. Run the tests with the `debug-serve` script command which will enable remote debugging: `pnpm run debug-serve resolve`. +2. Run the tests with the `debug-serve` script command, which will enable remote debugging: `pnpm run debug-serve resolve`. -1. Wait for inspector devtools to open in your browser and the debugger to attach. +3. Wait for inspector devtools to open in your browser and the debugger to attach. -1. In the sources panel in the right column, click the play button to resume execution and allow the tests to run which will open a Chromium instance. +4. In the sources panel in the right column, click the play button to resume execution, and allow the tests to run, which will open a Chromium instance. -1. Focusing the Chromium instance, you can open the browser devtools and inspect the console there to find the underlying problems. +5. Focusing the Chromium instance, you can open the browser devtools and inspect the console there to find the underlying problems. -1. To close everything, just stop the test process back in your terminal. +6. To close everything, just stop the test process back in your terminal. ## Testing Vite against external packages -You may wish to test your locally-modified copy of Vite against another package that is built with Vite. For pnpm, after building Vite, you can use [`pnpm.overrides`](https://pnpm.io/package_json#pnpmoverrides). Please note that `pnpm.overrides` must be specified in the root `package.json` and you must first list the package as a dependency in the root `package.json`: +You may wish to test your locally modified copy of Vite against another package that is built with Vite. For pnpm, after building Vite, you can use [`pnpm.overrides`](https://pnpm.io/package_json#pnpmoverrides) to do this. Note that `pnpm.overrides` must be specified in the root `package.json`, and you must list the package as a dependency in the root `package.json`: ```json { @@ -73,7 +73,7 @@ And re-run `pnpm install` to link the package. Each package under `playground/` contains a `__tests__` directory. The tests are run using [Vitest](https://vitest.dev/) + [Playwright](https://playwright.dev/) with custom integrations to make writing tests simple. The detailed setup is inside `vitest.config.e2e.js` and `playground/vitest*` files. -Before running the tests, make sure that [Vite has been built](#repo-setup). On Windows, you may want to [activate Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) to solve [issues with symlink creation for non-admins](https://github.com/vitejs/vite/issues/7390). Also you may want to [set git `core.symlinks` to `true` to solve issues with symlinks in git](https://github.com/vitejs/vite/issues/5242). +Before running the tests, make sure that [Vite has been built](#repo-setup). On Windows, you may want to [activate Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) to resolve [issues with symlink creation for non-admins](https://github.com/vitejs/vite/issues/7390). Also, you may want to [set git `core.symlinks` to `true` to resolve issues with symlinks in git](https://github.com/vitejs/vite/issues/5242). Each integration test can be run under either dev server mode or build mode. @@ -83,21 +83,21 @@ Each integration test can be run under either dev server mode or build mode. - `pnpm run test-build` runs tests only under build mode. -- You can also use `pnpm run test-serve [match]` or `pnpm run test-build [match]` to run tests in a specific playground package, e.g. `pnpm run test-serve asset` will run tests for both `playground/asset` and `vite/src/node/__tests__/asset` under serve mode and `vite/src/node/__tests__/**/*` just run in serve mode. +- `pnpm run test-serve [match]` or `pnpm run test-build [match]` runs tests in specific packages that match the given filter. e.g. `pnpm run test-serve asset` runs tests for both `playground/asset` and `vite/src/node/__tests__/asset` under serve mode. Note package matching is not available for the `pnpm test` script, which always runs all tests. ### Unit Tests -Other than tests under `playground/` for integration tests, packages might contains unit tests under their `__tests__` directory. Unit tests are powered by [Vitest](https://vitest.dev/). The detailed config is inside `vitest.config.ts` files. +Other than tests under `playground/` for integration tests, packages might contain unit tests under their `__tests__` directory. Unit tests are powered by [Vitest](https://vitest.dev/). The detailed config is inside `vitest.config.ts` files. - `pnpm run test-unit` runs unit tests under each package. -- You can also use `pnpm run test-unit [match]` to run related tests. +- `pnpm run test-unit [match]` runs tests in specific packages that match the given filter. ### Test Env and Helpers -Inside playground tests, you can import the `page` object from `~utils`, which is a Playwright [`Page`](https://playwright.dev/docs/api/class-page) instance that has already navigated to the served page of the current playground. So writing a test is as simple as: +Inside playground tests, you can import the `page` object from `~utils`, which is a Playwright [`Page`](https://playwright.dev/docs/api/class-page) instance that has already navigated to the served page of the current playground. So, writing a test is as simple as: ```js import { page } from '~utils' @@ -107,13 +107,13 @@ test('should work', async () => { }) ``` -Some common test helpers, e.g. `testDir`, `isBuild` or `editFile` are also available in the utils. Source code is located at `playground/test-utils.ts`. +Some common test helpers (e.g. `testDir`, `isBuild`, or `editFile`) are also available in the utils. Source code is located at `playground/test-utils.ts`. Note: The test build environment uses a [different default set of Vite config](https://github.com/vitejs/vite/blob/main/playground/vitestSetup.ts#L102-L122) to skip transpilation during tests to make it faster. This may produce a different result compared to the default production build. ### Extending the Test Suite -To add new tests, you should find a related playground to the fix or feature (or create a new one). As an example, static assets loading are tested in the [assets playground](https://github.com/vitejs/vite/tree/main/playground/assets). In this Vite App, there is a test for `?raw` imports, with [a section is defined in the `index.html` for it](https://github.com/vitejs/vite/blob/main/playground/assets/index.html#L121): +To add new tests, you should find a related playground to the fix or feature (or create a new one). As an example, static assets loading is tested in the [assets playground](https://github.com/vitejs/vite/tree/main/playground/assets). In this Vite app, there is a test for `?raw` imports with [a section defined in the `index.html` for it](https://github.com/vitejs/vite/blob/main/playground/assets/index.html#L121): ```html

?raw import

@@ -127,7 +127,7 @@ import rawSvg from './nested/fragment.svg?raw' text('.raw', rawSvg) ``` -Where the `text` util is defined as: +...where the `text` util is defined as: ```js function text(el, text) { @@ -145,34 +145,34 @@ test('?raw import', async () => { ## Note on Test Dependencies -In many test cases we need to mock dependencies using `link:` and `file:` protocols. `pnpm` treats `link:` as symlinks and `file:` as hardlinks. To test dependencies as if they are copied into `node_modules`, use the `file:` protocol, other cases should use the `link:` protocol. +In many test cases, we need to mock dependencies using `link:` and `file:` protocols. `pnpm` treats `link:` as symlinks and `file:` as hardlinks. To test dependencies as if they were copied into `node_modules`, use the `file:` protocol. Otherwise, use the `link:` protocol. ## Debug Logging -You can set the `DEBUG` environment variable to turn on debugging logs. E.g. `DEBUG="vite:resolve"`. To see all debug logs you can set `DEBUG="vite:*"`, but be warned that it will be quite noisy. You can run `grep -r "createDebugger('vite:" packages/vite/src/` to see a list of available debug scopes. +You can set the `DEBUG` environment variable to turn on debugging logs (e.g. `DEBUG="vite:resolve"`). To see all debug logs, you can set `DEBUG="vite:*"`, but be warned that it will be quite noisy. You can run `grep -r "createDebugger('vite:" packages/vite/src/` to see a list of available debug scopes. ## Pull Request Guidelines -- Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch. +- Checkout a topic branch from a base branch (e.g. `main`), and merge back against that branch. - If adding a new feature: - Add accompanying test case. - - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it. + - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first, and have it approved before working on it. -- If fixing bug: +- If fixing a bug: - - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`. + - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log (e.g. `fix: update entities encoding/decoding (fix #3899)`). - Provide a detailed description of the bug in the PR. Live demo preferred. - Add appropriate test coverage if applicable. -- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging. +- It's OK to have multiple small commits as you work on the PR. GitHub can automatically squash them before merging. - Make sure tests pass! - Commit messages must follow the [commit message convention](./.github.amrom.workers.devmit-convention.md) so that changelogs can be automatically generated. Commit messages are automatically validated before commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [yorkie](https://github.com/yyx990803/yorkie)). -- No need to worry about code style as long as you have installed the dev dependencies - modified files are automatically formatted with Prettier on commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [yorkie](https://github.com/yyx990803/yorkie)). +- No need to worry about code style as long as you have installed the dev dependencies. Modified files are automatically formatted with Prettier on commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [yorkie](https://github.com/yyx990803/yorkie)). ## Maintenance Guidelines @@ -196,62 +196,41 @@ You can set the `DEBUG` environment variable to turn on debugging logs. E.g. `DE Vite aims to be lightweight, and this includes being aware of the number of npm dependencies and their size. -We use rollup to pre-bundle most dependencies before publishing! Therefore most dependencies, even used in src code, should be added under `devDependencies` by default. This also creates a number of constraints that we need to be aware of in the codebase: +We use Rollup to pre-bundle most dependencies before publishing! Therefore, most dependencies, even those used in runtime source code, should be added under `devDependencies` by default. This also creates the following constraints that we need to be aware of in the codebase. ### Usage of `require()` -In some cases we intentionally lazy-require some dependencies to improve startup performance. However, note that we cannot use simple `require('somedep')` calls since these are ignored in ESM files so the dependency won't be included in the bundle, and the actual dependency won't even be there when published since they are in `devDependencies`. +In some cases, we intentionally lazy-require some dependencies to improve start-up performance. However, note that we cannot use simple `require('somedep')` calls since these are ignored in ESM files, so the dependency won't be included in the bundle, and the actual dependency won't even be there when published since they are in `devDependencies`. Instead, use `(await import('somedep')).default`. -### Think before adding a dependency +### Think Before Adding a Dependency Most deps should be added to `devDependencies` even if they are needed at runtime. Some exceptions are: - Type packages. Example: `@types/*`. - Deps that cannot be properly bundled due to binary files. Example: `esbuild`. -- Deps that ships its own types and its type is used in vite's own public types. Example: `rollup`. +- Deps that ship their own types that are used in Vite's own public types. Example: `rollup`. -Avoid deps that has large transitive dependencies that results in bloated size compared to the functionality it provides. For example, `http-proxy` itself plus `@types/http-proxy` is a little over 1MB in size, but `http-proxy-middleware` pulls in a ton of dependencies that makes it 7MB(!) when a minimal custom middleware on top of `http-proxy` only requires a couple lines of code. +Avoid deps with large transitive dependencies that result in bloated size compared to the functionality it provides. For example, `http-proxy` itself plus `@types/http-proxy` is a little over 1MB in size, but `http-proxy-middleware` pulls in a ton of dependencies that make it 7MB(!) when a minimal custom middleware on top of `http-proxy` only requires a couple of lines of code. -### Ensure type support +### Ensure Type Support -Vite aims to be fully usable as a dependency in a TypeScript project (e.g. it should provide proper typings for VitePress), and also in `vite.config.ts`. This means technically a dependency whose types are exposed needs to be part of `dependencies` instead of `devDependencies`. However, these means we won't be able to bundle it. +Vite aims to be fully usable as a dependency in a TypeScript project (e.g. it should provide proper typings for VitePress), and also in `vite.config.ts`. This means technically a dependency whose types are exposed needs to be part of `dependencies` instead of `devDependencies`. However, this also means we won't be able to bundle it. -To get around this, we inline some of these dependencies' types in `packages/vite/types`. This way we can still expose the typing but bundle the dependency's source code. +To get around this, we inline some of these dependencies' types in `packages/vite/types`. This way, we can still expose the typing but bundle the dependency's source code. -Use `pnpm run check-dist-types` to check bundled types does not rely on types in `devDependencies`. If you are adding `dependencies`, make sure to configure `tsconfig.check.json`. +Use `pnpm run check-dist-types` to check that the bundled types do not rely on types in `devDependencies`. If you are adding `dependencies`, make sure to configure `tsconfig.check.json`. -### Think before adding yet another option +### Think Before Adding Yet Another Option -We already have many config options, and we should avoid fixing an issue by adding yet another one. Before adding an option, try to think about: +We already have many config options, and we should avoid fixing an issue by adding yet another one. Before adding an option, consider whether the problem: -- Whether the problem is really worth addressing -- Whether the problem can be fixed with a smarter default -- Whether the problem has workaround using existing options -- Whether the problem can be addressed with a plugin instead +- is really worth addressing +- can be fixed with a smarter default +- has workaround using existing options +- can be addressed with a plugin instead -## Docs translation contribution +## Docs Translation Contribution -If you would like to start a translation in your language, you are welcome to contribute! Please join [the #translations channel in Vite Land](https://chat.vitejs.dev) to discuss and coordinate with others. - -The english docs are embedded in the main Vite repo, to allow contributors to work on docs, tests and implementation in the same PR. Translations are done by forking the main repo. - -### How to start a translation repo - -1. In order to get all doc files, you first need to clone this repo in your personal account. -2. Keep all the files in `docs/` and remove everything else. - - - You should setup your translation site based on all the files in `docs/` folder as a VitePress project. - (that said, `package.json` is need). - - - Refresh git history by removing `.git` and then `git init` - -3. Translate the docs. - - - During this stage, you may be translating documents and synchronizing updates at the same time, but don't worry about that, it's very common in translation contribution. - -4. Push your commits to your GitHub repo. you can setup a netlify preview as well. -5. Use [Ryu-cho](https://github.com/vuejs-translations/ryu-cho) tool to setup a GitHub Action, automatically track English docs update later. - -We recommend talking with others in Vite Land so you find more contributors for your language to share the maintenance work. Once the translation is done, communicate it to the Vite team so the repo can be moved to the official vitejs org in GitHub. +To add a new language to the Vite docs, see [`vite-docs-template`](https://github.com/tony19/vite-docs-template/blob/main/.github/CONTRIBUTING.md). diff --git a/README.md b/README.md index 9799c10e49598f..7449f11a54788b 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ - 🔩 Universal Plugin Interface - 🔑 Fully Typed APIs -Vite (French word for "quick", pronounced [`/vit/`](https://cdn.jsdelivr.net/gh/vitejs/vite@main/docs/public/vite.mp3), like "veet") is a new breed of frontend build tool that significantly improves the frontend development experience. It consists of two major parts: +Vite (French word for "quick", pronounced [`/vit/`](https://cdn.jsdelivr.net/gh/vitejs/vite@main/docs/public/vite.mp3), like "veet") is a new breed of frontend build tooling that significantly improves the frontend development experience. It consists of two major parts: - A dev server that serves your source files over [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), with [rich built-in features](https://vitejs.dev/guide/features.html) and astonishingly fast [Hot Module Replacement (HMR)](https://vitejs.dev/guide/features.html#hot-module-replacement). @@ -33,17 +33,6 @@ In addition, Vite is highly extensible via its [Plugin API](https://vitejs.dev/g [Read the Docs to Learn More](https://vitejs.dev). -## v3.0 - -Current Status: **Beta** (for internal testing, not recommended for production) - -The `main` branch is now for v3.0, if you are looking for current stable releases, check the [`v2` branch](https://github.com/vitejs/vite/tree/v2) branch instead. - -We will start drafting release notes and migration guide for v3.0 when we enter the beta stage. Before that you can check: - -- [v3.0 Milestone](https://github.com/vitejs/vite/milestone/5) -- [Breaking Change List](https://github.com/vitejs/vite/issues?q=label%3A%22breaking+change%22+is%3Aclosed+milestone%3A3.0) - ## Packages | Package | Version (click for changelogs) | diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 1ab27cb3ad754d..3578621b2a0331 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,12 +1,60 @@ -import { defineConfig } from 'vitepress' +import { defineConfig, DefaultTheme } from 'vitepress' const ogDescription = 'Next Generation Frontend Tooling' const ogImage = 'https://vitejs.dev/og-image.png' const ogTitle = 'Vite' const ogUrl = 'https://vitejs.dev' +// netlify envs +const deployURL = process.env.DEPLOY_PRIME_URL || '' +const commitRef = process.env.COMMIT_REF?.slice(0, 8) || 'dev' + +const deployType = (() => { + switch (deployURL) { + case 'https://main--vite-docs-main.netlify.app': + return 'main' + case '': + return 'local' + default: + return 'release' + } +})() +const additionalTitle = ((): string => { + switch (deployType) { + case 'main': + return ' (main branch)' + case 'local': + return ' (local)' + case 'release': + return '' + } +})() +const versionLinks = ((): DefaultTheme.NavItemWithLink[] => { + switch (deployType) { + case 'main': + case 'local': + return [ + { + text: 'Vite 3 Docs (release)', + link: 'https://vitejs.dev' + }, + { + text: 'Vite 2 Docs', + link: 'https://v2.vitejs.dev' + } + ] + case 'release': + return [ + { + text: 'Vite 2 Docs', + link: 'https://v2.vitejs.dev' + } + ] + } +})() + export default defineConfig({ - title: 'Vite', + title: `Vite${additionalTitle}`, description: 'Next Generation Frontend Tooling', head: [ @@ -15,11 +63,10 @@ export default defineConfig({ ['meta', { property: 'og:title', content: ogTitle }], ['meta', { property: 'og:image', content: ogImage }], ['meta', { property: 'og:url', content: ogUrl }], - ['meta', { property: 'twitter:description', content: ogDescription }], - ['meta', { property: 'twitter:title', content: ogTitle }], - ['meta', { property: 'twitter:card', content: 'summary_large_image' }], - ['meta', { property: 'twitter:image', content: ogImage }], - ['meta', { property: 'twitter:url', content: ogUrl }] + ['meta', { property: 'og:description', content: ogDescription }], + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], + ['meta', { name: 'twitter:site', content: '@vite_js' }], + ['meta', { name: 'theme-color', content: '#646cff' }] ], vue: { @@ -41,7 +88,8 @@ export default defineConfig({ ], algolia: { - apiKey: 'b573aa848fd57fb47d693b531297403c', + appId: '7H67QR5P0A', + apiKey: 'deaab78bcdfe96b599497d25acc6460e', indexName: 'vitejs', searchParameters: { facetFilters: ['tags:en'] @@ -63,7 +111,7 @@ export default defineConfig({ }, footer: { - message: 'Released under the MIT License.', + message: `Released under the MIT License. (${commitRef})`, copyright: 'Copyright © 2019-present Evan You & Vite Contributors' }, @@ -107,12 +155,7 @@ export default defineConfig({ }, { text: 'Version', - items: [ - { - text: 'Vite 2 Docs', - link: 'https://v2.vitejs.dev' - } - ] + items: versionLinks } ], @@ -169,6 +212,10 @@ export default defineConfig({ text: 'Comparisons', link: '/guide/comparisons' }, + { + text: 'Troubleshooting', + link: '/guide/troubleshooting' + }, { text: 'Migration from v2', link: '/guide/migration' diff --git a/docs/.vitepress/theme/components/AsideSponsors.vue b/docs/.vitepress/theme/components/AsideSponsors.vue index 9c90fcca3750a6..789f1e0e8addbf 100644 --- a/docs/.vitepress/theme/components/AsideSponsors.vue +++ b/docs/.vitepress/theme/components/AsideSponsors.vue @@ -18,5 +18,71 @@ const sponsors = computed(() => { + + diff --git a/docs/.vitepress/theme/components/SvgImage.vue b/docs/.vitepress/theme/components/SvgImage.vue new file mode 100644 index 00000000000000..3440988030d2db --- /dev/null +++ b/docs/.vitepress/theme/components/SvgImage.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 3b4d7e38df76ab..39f1f2ffcae120 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -3,6 +3,7 @@ import Theme from 'vitepress/theme' import './styles/vars.css' import HomeSponsors from './components/HomeSponsors.vue' import AsideSponsors from './components/AsideSponsors.vue' +import SvgImage from './components/SvgImage.vue' export default { ...Theme, @@ -11,5 +12,8 @@ export default { 'home-features-after': () => h(HomeSponsors), 'aside-ads-before': () => h(AsideSponsors) }) + }, + enhanceApp({ app }) { + app.component('SvgImage', SvgImage) } } diff --git a/docs/_data/team.js b/docs/_data/team.js index 43b56ad5bf481b..fd386685af6bc1 100644 --- a/docs/_data/team.js +++ b/docs/_data/team.js @@ -5,7 +5,7 @@ export const core = [ title: 'Creator', org: 'Vue.js', orgLink: 'https://vuejs.org/', - desc: 'Husband, father of two, independent open source developer.', + desc: 'Independent open source developer, creator of Vue.js and Vite.', links: [ { icon: 'github', link: 'https://github.com/yyx990803' }, { icon: 'twitter', link: 'https://twitter.com/youyuxi' } diff --git a/docs/blog/announcing-vite3.md b/docs/blog/announcing-vite3.md index d15d624822a671..4a1ff3144e26ad 100644 --- a/docs/blog/announcing-vite3.md +++ b/docs/blog/announcing-vite3.md @@ -2,38 +2,31 @@ sidebar: false head: - - meta - - name: og:type + - property: og:type content: website - - meta - - name: og:title + - property: og:title content: Announcing Vite 3 - - meta - - name: og:image + - property: og:image content: https://vitejs.dev/og-image-announcing-vite3.png - - meta - - name: og:url + - property: og:url content: https://vitejs.dev/blog/announcing-vite3 - - meta - - name: twitter:description + - property: og:description content: Vite 3 Release Announcement - - - meta - - name: twitter:title - content: Announcing Vite 3 - - meta - name: twitter:card content: summary_large_image - - - meta - - name: twitter:image - content: https://vitejs.dev/og-image-announcing-vite3.png - - - meta - - name: twitter:url - content: https://vitejs.dev/blog/announcing-vite3 --- # Vite 3.0 is out! In February last year, [Evan You](https://twitter.com/youyuxi) released Vite 2. Since then, its adoption has grown non-stop, reaching more than 1 million npm downloads per week. A sprawling ecosystem rapidly formed after the release. Vite is powering a renewed innovation race in Web frameworks. [Nuxt 3](https://v3.nuxtjs.org/) uses Vite by default. [SvelteKit](https://kit.svelte.dev/), [Astro](https://astro.build/), [Hydrogen](https://hydrogen.shopify.dev/), and [SolidStart](https://docs.solidjs.com/start) are all built with Vite. [Laravel has now decided to use Vite by default](https://laravel.com/docs/9.x/vite). [Vite Ruby](https://vite-ruby.netlify.app/) shows how Vite can improve Rails DX. [Vitest](https://vitest.dev) is making strides as a Vite-native alternative to Jest. Vite is behind [Cypress](https://docs.cypress.io/guides/component-testing/writing-your-first-component-test) and [Playwright](https://playwright.dev/docs/test-components)'s new Component Testing features, Storybook has [Vite as an official builder](https://github.com/storybookjs/builder-vite). And [the list goes on](https://patak.dev/vite/ecosystem.html). Maintainers from most of these projects got involved in improving the Vite core itself, working closely with the Vite [team](https://vitejs.dev/team) and other contributors. +![Vite 3 Announcement Cover Image](/og-image-announcing-vite3.png) + Today, 16 months from the v2 launch we are happy to announce the release of Vite 3. We decided to release a new Vite major at least every year to align with [Node.js's EOL](https://nodejs.org/en/about/releases/), and take the opportunity to review Vite's API regularly with a short migration path for projects in the ecosystem. Quick links: @@ -42,7 +35,7 @@ Quick links: - [Migration Guide](/guide/migration) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#300-2022-07-13) -If you are new to Vite, we recommend reading the [Why Vite Guide](https://vitejs.dev/guide/why.html). Then check out [the Getting Started](https://vitejs.dev/guide/getting-started) and [Features guide](https://vitejs.dev/guide/features) to see what Vite provides out of the box. As usual, contributions are welcome at [GitHub](https://github.com/vitejs/vite). More than [600 collaborators](https://github.com/vitejs/vite/graphs/contributors) have helped improve Vite so far. Follow the updates on [Twitter](https://twitter.com/vite_js), or join discussions with other Vite users on our [Discord chat server](http://chat.vitejs.dev/). +If you are new to Vite, we recommend reading the [Why Vite Guide](https://vitejs.dev/guide/why.html). Then check out [the Getting Started](https://vitejs.dev/guide/) and [Features guide](https://vitejs.dev/guide/features) to see what Vite provides out of the box. As usual, contributions are welcome at [GitHub](https://github.com/vitejs/vite). More than [600 collaborators](https://github.com/vitejs/vite/graphs/contributors) have helped improve Vite so far. Follow the updates on [Twitter](https://twitter.com/vite_js), or join discussions with other Vite users on our [Discord chat server](http://chat.vitejs.dev/). ## New Documentation @@ -108,7 +101,7 @@ The theme is now shared by all templates. This should help better convey the sco ### Vite CLI -
+
   VITE v3.0.0  ready in 320 ms
 
     Local:   http://127.0.0.1:5173/
@@ -150,7 +143,7 @@ import.meta.glob(['./dir/*.js', './another/*.js'])
 import.meta.glob(['./dir/*.js', '!**/bar.js'])
 ```
 
-[Named Imports](/guide/features.html#named-imports) can be specified to improve tree-shacking
+[Named Imports](/guide/features.html#named-imports) can be specified to improve tree-shaking
 
 ```js
 import.meta.glob('./dir/*.js', { import: 'setup' })
@@ -200,7 +193,7 @@ There are other deploy scenarios where this isn't enough. For example, if the ge
 
 ### Esbuild Deps Optimization at Build Time (Experimental)
 
-One of the main differences between dev and build time is how Vite handles dependencies. During build time, [`@rollupjs/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is used to allow importing CJS only dependencies (like React). When using the dev server, esbuild is used instead to pre-bundle and optimize dependencies, and an inline interop scheme is applied while transforming user code importing CJS deps. During the development of Vite 3, we introduced the changes needed to also allow the use of [esbuild to optimize dependencies during build time](/guide/migration.html#using-esbuild-deps-optimization-at-build-time). [`@rollupjs/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) can then be avoided, making dev and build time work in the same way.
+One of the main differences between dev and build time is how Vite handles dependencies. During build time, [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is used to allow importing CJS only dependencies (like React). When using the dev server, esbuild is used instead to pre-bundle and optimize dependencies, and an inline interop scheme is applied while transforming user code importing CJS deps. During the development of Vite 3, we introduced the changes needed to also allow the use of [esbuild to optimize dependencies during build time](/guide/migration.html#using-esbuild-deps-optimization-at-build-time). [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) can then be avoided, making dev and build time work in the same way.
 
 Given that Rollup v3 will be out in the next months, and we're going to follow up with another Vite major, we've decided to make this mode optional to reduce v3 scope and give Vite and the ecosystem more time to work out possible issues with the new CJS interop approach during build time. Frameworks may switch to using esbuild deps optimization during build time by default at their own pace before Vite 4.
 
@@ -218,11 +211,11 @@ Vite cares about its publish and install footprint; a fast installation of a new
 | Vite 3.0.0  |    3.05MB    |    17.8MB    |
 | Reduction   |     -30%     |     -7%      |
 
-In part, this reduction was possible by making some dependencies that most users weren't needing optional. First, [Terser](https://github.com/terser/terser) is no longer installed by default. This dependency was no longer needed since we already made esbuild the default minifier for both JS and CSS in Vite 2. If you use `build.minify: 'terser'`, you'll need to install it (`npm add -D terser`). We also moved [node-forge](https://github.com/digitalbazaar/forge) out of the monorepo, implementing support for automatic https certificate generation as a new plugins: [`@vitejs/plugin-basic-ssl`](/guide/migration.html#automatic-https-certificate-generation). It is recommended creating secure certificates, so this feature didn't justify the added size of this dependency.
+In part, this reduction was possible by making some dependencies that most users weren't needing optional. First, [Terser](https://github.com/terser/terser) is no longer installed by default. This dependency was no longer needed since we already made esbuild the default minifier for both JS and CSS in Vite 2. If you use `build.minify: 'terser'`, you'll need to install it (`npm add -D terser`). We also moved [node-forge](https://github.com/digitalbazaar/forge) out of the monorepo, implementing support for automatic https certificate generation as a new plugin: [`@vitejs/plugin-basic-ssl`](/guide/migration.html#automatic-https-certificate-generation). Since this feature only creates untrusted certificates that are not added to the local store, it didn't justify the added size.
 
 ## Bug Fixing
 
-A triaging marathon was spearheaded by [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), that recently joined the Vite team. During the past three months, the Vite open issues were reduced from 770 to 400. And this dive was achieved while the newly open PRs were at an all-time high.
+A triaging marathon was spearheaded by [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), that recently joined the Vite team. During the past three months, the Vite open issues were reduced from 770 to 400. And this dive was achieved while the newly open PRs were at an all-time high. At the same time, [@haoqunjiang](https://twitter.com/haoqunjiang) had also curated a comprehensive [overview of Vite issues](https://github.com/vitejs/vite/discussions/8232).
 
 [![Graph of open issues and pull requests in Vite](../images/v3-open-issues-and-PRs.png)](https://www.repotrends.com/vitejs/vite)
 
@@ -230,9 +223,9 @@ A triaging marathon was spearheaded by [@bluwyoo](https://twitter.com/bluwyoo),
 
 ## Compatibility Notes
 
-- Vite no longer supports Node.js 12, which reached its EOL. Node.js 14.18+ is now required.
+- Vite no longer supports Node.js 12 / 13 / 15, which reached its EOL. Node.js 14.18+ / 16+ is now required.
 - Vite is now published as ESM, with a CJS proxy to the ESM entry for compatibility.
-- The Modern Browser Baseline now targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_statements_import_meta) features.
+- The Modern Browser Baseline now targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta) features.
 - JS file extensions in SSR and library mode now use a valid extension (`js`, `mjs`, or `cjs`) for output JS entries and chunks based on their format and the package type.
 
 Learn more in the [Migration Guide](/guide/migration).
diff --git a/docs/config/build-options.md b/docs/config/build-options.md
index f2c9598f752ada..586f84d6b24fd0 100644
--- a/docs/config/build-options.md
+++ b/docs/config/build-options.md
@@ -6,7 +6,7 @@
 - **Default:** `'modules'`
 - **Related:** [Browser Compatibility](/guide/build#browser-compatibility)
 
-Browser compatibility target for the final bundle. The default value is a Vite special value, `'modules'`, which targets browsers with [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) support.
+Browser compatibility target for the final bundle. The default value is a Vite special value, `'modules'`, which targets browsers with [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta) support.
 
 Another special value is `'esnext'` - which assumes native dynamic imports support and will transpile as little as possible:
 
diff --git a/docs/config/index.md b/docs/config/index.md
index 34675192fe6484..48254361328e1e 100644
--- a/docs/config/index.md
+++ b/docs/config/index.md
@@ -15,7 +15,7 @@ export default {
 }
 ```
 
-Note Vite supports using ES modules syntax in the config file even if the project is not using native Node ESM via `type: "module"`. In this case, the config file is auto pre-processed before load.
+Note Vite supports using ES modules syntax in the config file even if the project is not using native Node ESM, e.g. `type: "module"` in `package.json`. In this case, the config file is auto pre-processed before load.
 
 You can also explicitly specify a config file to use with the `--config` CLI option (resolved relative to `cwd`):
 
@@ -23,19 +23,6 @@ You can also explicitly specify a config file to use with the `--config` CLI opt
 vite --config my-config.js
 ```
 
-::: tip NOTE
-Vite will inject `__filename`, `__dirname` in config files and its deps. Declaring these variables at top level will result in an error:
-
-```js
-const __filename = 'value' // SyntaxError: Identifier '__filename' has already been declared
-
-const func = () => {
-  const __filename = 'value' // no error
-}
-```
-
-:::
-
 ## Config Intellisense
 
 Since Vite ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints:
diff --git a/docs/config/preview-options.md b/docs/config/preview-options.md
index 10ec82f38e3848..32589a5091d12b 100644
--- a/docs/config/preview-options.md
+++ b/docs/config/preview-options.md
@@ -65,7 +65,7 @@ Automatically open the app in the browser on server start. When the value is a s
 - **Type:** `Record`
 - **Default:** [`server.proxy`](./server-options#server-proxy)
 
-Configure custom proxy rules for the dev server. Expects an object of `{ key: options }` pairs. If the key starts with `^`, it will be interpreted as a `RegExp`. The `configure` option can be used to access the proxy instance.
+Configure custom proxy rules for the preview server. Expects an object of `{ key: options }` pairs. If the key starts with `^`, it will be interpreted as a `RegExp`. The `configure` option can be used to access the proxy instance.
 
 Uses [`http-proxy`](https://github.com/http-party/node-http-proxy). Full options [here](https://github.com/http-party/node-http-proxy#options).
 
@@ -74,4 +74,4 @@ Uses [`http-proxy`](https://github.com/http-party/node-http-proxy). Full options
 - **Type:** `boolean | CorsOptions`
 - **Default:** [`server.cors`](./server-options#server-cors)
 
-Configure CORS for the dev server. This is enabled by default and allows any origin. Pass an [options object](https://github.com/expressjs/cors) to fine tune the behavior or `false` to disable.
+Configure CORS for the preview server. This is enabled by default and allows any origin. Pass an [options object](https://github.com/expressjs/cors) to fine tune the behavior or `false` to disable.
diff --git a/docs/config/server-options.md b/docs/config/server-options.md
index 33208bd4b04155..29a3582665c7a6 100644
--- a/docs/config/server-options.md
+++ b/docs/config/server-options.md
@@ -145,6 +145,8 @@ Set `server.hmr.overlay` to `false` to disable the server error overlay.
 
 When `server.hmr.server` is defined, Vite will process the HMR connection requests through the provided server. If not in middleware mode, Vite will attempt to process HMR connection requests through the existing server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port.
 
+Check out [`vite-setup-catalogue`](https://github.com/sapphi-red/vite-setup-catalogue) for some examples.
+
 ::: tip NOTE
 
 With the default configuration, reverse proxies in front of Vite are expected to support proxying WebSocket. If the Vite HMR client fails to connect WebSocket, the client will fallback to connecting the WebSocket directly to the Vite HMR server bypassing the reverse proxies:
diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md
index 835354133f2caa..8f7d151499e906 100644
--- a/docs/config/shared-options.md
+++ b/docs/config/shared-options.md
@@ -110,6 +110,10 @@ When aliasing to file system paths, always use absolute paths. Relative alias va
 
 More advanced custom resolution can be achieved through [plugins](/guide/api-plugin).
 
+::: warning Using with SSR
+If you have configured aliases for [SSR externalized dependencies](/guide/ssr.md#ssr-externals), you may want to alias the actual `node_modules` packages. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.js.org/en/aliases) support aliasing via the `npm:` prefix.
+:::
+
 ## resolve.dedupe
 
 - **Type:** `string[]`
diff --git a/docs/guide/backend-integration.md b/docs/guide/backend-integration.md
index 3cde869121d6d7..92bb4d084d23e6 100644
--- a/docs/guide/backend-integration.md
+++ b/docs/guide/backend-integration.md
@@ -33,6 +33,7 @@ If you need a custom integration, you can follow the steps in this guide to conf
 
    ```html
    
+   
    
    ```
 
diff --git a/docs/guide/build.md b/docs/guide/build.md
index e5a4af31c865d2..30dadbbb2473df 100644
--- a/docs/guide/build.md
+++ b/docs/guide/build.md
@@ -4,7 +4,7 @@ When it is time to deploy your app for production, simply run the `vite build` c
 
 ## Browser Compatibility
 
-The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) and [`import.meta`](https://caniuse.com/mdn-javascript_statements_import_meta):
+The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta):
 
 - Chrome >=87
 - Firefox >=78
@@ -128,7 +128,7 @@ import { defineConfig } from 'vite'
 export default defineConfig({
   build: {
     lib: {
-      entry: path.resolve(__dirname, 'lib/main.js'),
+      entry: resolve(__dirname, 'lib/main.js'),
       name: 'MyLib',
       // the proper extensions will be added
       fileName: 'my-lib'
@@ -163,8 +163,8 @@ Running `vite build` with this config uses a Rollup preset that is oriented towa
 ```
 $ vite build
 building for production...
-[write] my-lib.mjs 0.08kb, brotli: 0.07kb
-[write] my-lib.umd.js 0.30kb, brotli: 0.16kb
+dist/my-lib.js      0.08 KiB / gzip: 0.07 KiB
+dist/my-lib.umd.cjs 0.30 KiB / gzip: 0.16 KiB
 ```
 
 Recommended `package.json` for your lib:
@@ -172,22 +172,31 @@ Recommended `package.json` for your lib:
 ```json
 {
   "name": "my-lib",
+  "type": "module",
   "files": ["dist"],
-  "main": "./dist/my-lib.umd.js",
-  "module": "./dist/my-lib.mjs",
+  "main": "./dist/my-lib.umd.cjs",
+  "module": "./dist/my-lib.js",
   "exports": {
     ".": {
-      "import": "./dist/my-lib.mjs",
-      "require": "./dist/my-lib.umd.js"
+      "import": "./dist/my-lib.js",
+      "require": "./dist/my-lib.umd.cjs"
     }
   }
 }
 ```
 
+::: tip Note
+If the `package.json` does not contain `"type": "module"`, Vite will generate different file extensions for Node.js compatibility. `.js` will become `.mjs` and `.cjs` will become `.js`.
+:::
+
+::: tip Environment Variables
+In library mode, all `import.meta.env.*` usage are statically replaced when building for production. However, `process.env.*` usage are not, so that consumers of your library can dynamically change it. If this is undesirable, you can use `define: { 'process.env.``NODE_ENV': '"production"' }` for example to statically replace them.
+:::
+
 ## Advanced Base Options
 
 ::: warning
-This feature is experimental, the API may change in a future minor without following semver. Please fix the minor version of Vite when using it.
+This feature is experimental, the API may change in a future minor without following semver. Please always pin Vite's version to a minor when using it.
 :::
 
 For advanced use cases, the deployed assets and public files may be in different paths, for example to use different cache strategies.
@@ -199,9 +208,9 @@ A user may choose to deploy in three different paths:
 
 A single static [base](#public-base-path) isn't enough in these scenarios. Vite provides experimental support for advanced base options during build, using `experimental.renderBuiltUrl`.
 
-```js
+```ts
 experimental: {
-  renderBuiltUrl: (filename: string, { hostType: 'js' | 'css' | 'html' }) => {
+  renderBuiltUrl(filename: string, { hostType }: { hostType: 'js' | 'css' | 'html' }) {
     if (hostType === 'js') {
       return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
     } else {
@@ -211,15 +220,15 @@ experimental: {
 }
 ```
 
-If the hashed assets and public files aren't deployed together, options for each group can be defined independently using asset `type` included in the third `context` param given to the function.
+If the hashed assets and public files aren't deployed together, options for each group can be defined independently using asset `type` included in the second `context` param given to the function.
 
-```js
+```ts
 experimental: {
-  renderBuiltUrl(filename: string, { hostType: 'js' | 'css' | 'html', type: 'public' | 'asset' }) {
+  renderBuiltUrl(filename: string, { hostId, hostType, type }: { hostId: string, hostType: 'js' | 'css' | 'html', type: 'public' | 'asset' }) {
     if (type === 'public') {
       return 'https://www.domain.com/' + filename
     }
-    else if (path.extname(importer) === '.js') {
+    else if (path.extname(hostId) === '.js') {
       return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
     }
     else {
diff --git a/docs/guide/env-and-mode.md b/docs/guide/env-and-mode.md
index 43da3c3b8ace38..c69badcda5db2e 100644
--- a/docs/guide/env-and-mode.md
+++ b/docs/guide/env-and-mode.md
@@ -46,7 +46,7 @@ In addition, environment variables that already exist when Vite is executed have
 
 Loaded env variables are also exposed to your client source code via `import.meta.env` as strings.
 
-To prevent accidentally leaking env variables to the client, only variables prefixed with `VITE_` are exposed to your Vite-processed code. e.g. the following file:
+To prevent accidentally leaking env variables to the client, only variables prefixed with `VITE_` are exposed to your Vite-processed code. e.g. for the following env variables:
 
 ```
 VITE_SOME_KEY=123
@@ -60,7 +60,7 @@ console.log(import.meta.env.VITE_SOME_KEY) // 123
 console.log(import.meta.env.DB_PASSWORD) // undefined
 ```
 
-If you want to customize env variables prefix, see [envPrefix](/config/index#envprefix) option.
+If you want to customize the env variables prefix, see the [envPrefix](/config/shared-options.html#envprefix) option.
 
 :::warning SECURITY NOTES
 
@@ -71,9 +71,9 @@ If you want to customize env variables prefix, see [envPrefix](/config/index#env
 
 ### IntelliSense for TypeScript
 
-By default, Vite provides type definition for `import.meta.env` in [`vite/client.d.ts`](https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts). While you can define more custom env variables in `.env.[mode]` files, you may want to get TypeScript IntelliSense for user-defined env variables which prefixed with `VITE_`.
+By default, Vite provides type definitions for `import.meta.env` in [`vite/client.d.ts`](https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts). While you can define more custom env variables in `.env.[mode]` files, you may want to get TypeScript IntelliSense for user-defined env variables that are prefixed with `VITE_`.
 
-To achieve, you can create an `env.d.ts` in `src` directory, then augment `ImportMetaEnv` like this:
+To achieve this, you can create an `env.d.ts` in `src` directory, then augment `ImportMetaEnv` like this:
 
 ```typescript
 /// 
@@ -98,7 +98,7 @@ If your code relies on types from browser environments such as [DOM](https://git
 
 ## Modes
 
-By default, the dev server (`dev` command) runs in `development` mode and the `build` command run in `production` mode.
+By default, the dev server (`dev` command) runs in `development` mode and the `build` command runs in `production` mode.
 
 This means when running `vite build`, it will load the env variables from `.env.production` if there is one:
 
diff --git a/docs/guide/features.md b/docs/guide/features.md
index b7449e15bfc1c9..0f69035a71dea5 100644
--- a/docs/guide/features.md
+++ b/docs/guide/features.md
@@ -102,14 +102,28 @@ This will provide the following type shims:
 - Types for the Vite-injected [env variables](./env-and-mode#env-variables) on `import.meta.env`
 - Types for the [HMR API](./api-hmr) on `import.meta.hot`
 
+::: tip
+To override the default typing, declare it before the triple-slash reference. For example, to make the default import of `*.svg` a React component:
+
+```ts
+declare module '*.svg' {
+  const content: React.FC>
+  export default content
+}
+
+/// 
+```
+
+:::
+
 ## Vue
 
 Vite provides first-class Vue support:
 
 - Vue 3 SFC support via [@vitejs/plugin-vue](https://github.com/vitejs/vite/tree/main/packages/plugin-vue)
 - Vue 3 JSX support via [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx)
-- Vue 2.7 support via [vitejs/vite-plugin-vue2](https://github.com/vitejs/vite-plugin-vue2)
-- Vue <2.7 support via [underfin/vite-plugin-vue2](https://github.com/underfin/vite-plugin-vue2)
+- Vue 2.7 support via [@vitejs/plugin-vue2](https://github.com/vitejs/vite-plugin-vue2)
+- Vue <2.7 support via [vite-plugin-vue2](https://github.com/underfin/vite-plugin-vue2)
 
 ## JSX
 
@@ -538,7 +552,10 @@ Vite automatically generates `` directives for entry c
 
 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:
 
-![graph](/images/graph.png)
+
+
 
 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:
 
diff --git a/docs/guide/index.md b/docs/guide/index.md
index 0236b895aedee1..e88dbbb045d823 100644
--- a/docs/guide/index.md
+++ b/docs/guide/index.md
@@ -18,7 +18,7 @@ You can learn more about the rationale behind the project in the [Why Vite](./wh
 
 ## Browser Support
 
-The default build targets browsers that support both [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import). Legacy browsers can be supported via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) - see the [Building for Production](./build) section for more details.
+The default build targets browsers that support [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta). Legacy browsers can be supported via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) - see the [Building for Production](./build) section for more details.
 
 ## Trying Vite Online
 
@@ -38,7 +38,7 @@ The supported template presets are:
 ## Scaffolding Your First Vite Project
 
 ::: tip Compatibility Note
-Vite requires [Node.js](https://nodejs.org/en/) version >=14.18.0. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
+Vite requires [Node.js](https://nodejs.org/en/) version 14.18+, 16+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
 :::
 
 With NPM:
diff --git a/docs/guide/migration.md b/docs/guide/migration.md
index 70333ed9112cc0..2b6ae6949c9b19 100644
--- a/docs/guide/migration.md
+++ b/docs/guide/migration.md
@@ -2,11 +2,11 @@
 
 ## Node.js Support
 
-Vite no longer supports Node.js 12, which reached its EOL. Node.js 14.18+ is now required.
+Vite no longer supports Node.js 12 / 13 / 15, which reached its EOL. Node.js 14.18+ / 16+ is now required.
 
 ## Modern Browser Baseline change
 
-The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) and [`import.meta`](https://caniuse.com/mdn-javascript_statements_import_meta):
+The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta):
 
 - Chrome >=87
 - Firefox >=78
@@ -106,7 +106,7 @@ export default {
 
 ### Using esbuild deps optimization at build time
 
-In v3, Vite allows the use of esbuild to optimize dependencies during build time. If enabled, it removes one of the most significant differences between dev and prod present in v2. [`@rollupjs/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is no longer needed in this case since esbuild converts CJS-only dependencies to ESM.
+In v3, Vite allows the use of esbuild to optimize dependencies during build time. If enabled, it removes one of the most significant differences between dev and prod present in v2. [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is no longer needed in this case since esbuild converts CJS-only dependencies to ESM.
 
 If you want to try this build strategy, you can use `optimizeDeps.disabled: false` (the default in v3 is `disabled: 'build'`). `@rollup/plugin-commonjs`
 can be removed by passing `build.commonjsOptions: { include: [] }`
diff --git a/docs/guide/ssr.md b/docs/guide/ssr.md
index 747572d1b0b66b..e0e97ebde0f336 100644
--- a/docs/guide/ssr.md
+++ b/docs/guide/ssr.md
@@ -61,11 +61,14 @@ When building an SSR app, you likely want to have full control over your main se
 
 **server.js**
 
-```js{17-19}
+```js{15-18}
 import fs from 'fs'
 import path from 'path'
+import { fileURLToPath } from 'url'
 import express from 'express'
-import {createServer as createViteServer} from 'vite'
+import { createServer as createViteServer } from 'vite'
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
 
 async function createServer() {
   const app = express()
@@ -208,7 +211,7 @@ If the routes and the data needed for certain routes are known ahead of time, we
 
 Dependencies are "externalized" from Vite's SSR transform module system by default when running SSR. This speeds up both dev and build.
 
-If a dependency needs to be transformed by Vite's pipeline, for example, because Vite features are used untranspiled in them, they can be added to [`ssr.noExternal`](../config/ssr-options.md#ssrnoexternal).
+If a dependency needs to be transformed by Vite's pipeline, for example, because Vite features are used untranspiled in them, they can be added to [`ssr.noExternal`](../config/ssr-options.md#ssr-noexternal).
 
 :::warning Working with Aliases
 If you have configured aliases that redirects one package to another, you may want to alias the actual `node_modules` packages instead to make it work for SSR externalized dependencies. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.js.org/en/aliases) support aliasing via the `npm:` prefix.
@@ -264,4 +267,4 @@ Use a post hook so that your SSR middleware runs _after_ Vite's middlewares.
 
 ## SSR Format
 
-By default, Vite generates the SSR bundle in ESM. There is experimental support for configuring `ssr.format`, but it isn't recommended. Future efforts around SSR development will be based on ESM, and commonjs remain available for backward compatibility. If using ESM for SSR isn't possible in your project, you can set `legacy.buildSsrCjsExternalHeuristics: true` to generate a CJS bundle using the same [externalization heuristics of Vite v2](https://v2.vitejs.dev/guide/ssr.html#ssr-externals).
+By default, Vite generates the SSR bundle in ESM. There is experimental support for configuring `ssr.format`, but it isn't recommended. Future efforts around SSR development will be based on ESM, and CommonJS remain available for backward compatibility. If using ESM for SSR isn't possible in your project, you can set `legacy.buildSsrCjsExternalHeuristics: true` to generate a CJS bundle using the same [externalization heuristics of Vite v2](https://v2.vitejs.dev/guide/ssr.html#ssr-externals).
diff --git a/docs/guide/static-deploy.md b/docs/guide/static-deploy.md
index 756f6a9c85d010..138a58b0319dec 100644
--- a/docs/guide/static-deploy.md
+++ b/docs/guide/static-deploy.md
@@ -64,7 +64,7 @@ Now the `preview` command will launch the server at `http://localhost:8080`.
 
 2. Inside your project, create `deploy.sh` with the following content (with highlighted lines uncommented appropriately), and run it to deploy:
 
-   ```bash{13,20,23}
+   ```bash{13,21,24}
    #!/usr/bin/env sh
 
    # abort on errors
@@ -131,6 +131,8 @@ You can also run the above script in your CI setup to enable automatic deploymen
 
 ## Netlify
 
+### Netlify CLI
+
 1. Install the [Netlify CLI](https://cli.netlify.com/).
 2. Create a new site using `ntl init`.
 3. Deploy using `ntl deploy`.
@@ -153,6 +155,16 @@ The Netlify CLI will share with you a preview URL to inspect. When you are ready
 $ ntl deploy --prod
 ```
 
+### Netlify with Git
+
+1. Push your code to a git repository (GitHub, GitLab, BitBucket, Azure DevOps).
+2. [Import the project](https://app.netlify.com/start) to Netlify.
+3. Choose the branch, output directory, and set up environment variables if applicable.
+4. Click on **Deploy**.
+5. Your Vite app is deployed!
+
+After your project has been imported and deployed, all subsequent pushes to branches other than the production branch along with pull requests will generate [Preview Deployments](https://docs.netlify.com/site-deploys/deploy-previews/), and all changes made to the Production Branch (commonly “main”) will result in a [Production Deployment](https://docs.netlify.com/site-deploys/overview/#definitions).
+
 ## Vercel
 
 ### Vercel CLI
@@ -331,3 +343,26 @@ Install the extension in VS Code and navigate to your app root. Open the Static
 Follow the wizard started by the extension to give your app a name, choose a framework preset, and designate the app root (usually `/`) and built file location `/dist`. The wizard will run and will create a GitHub action in your repo in a `.github` folder.
 
 The action will work to deploy your app (watch its progress in your repo's Actions tab) and, when successfully completed, you can view your app in the address provided in the extension's progress window by clicking the 'Browse Website' button that appears when the GitHub action has run.
+
+## Render
+
+You can deploy your Vite app as a Static Site on [Render](https://render.com/).
+
+1. Create a [Render account](https://dashboard.render.com/register).
+
+2. In the [Dashboard](https://dashboard.render.com/), click the **New** button and select **Static Site**.
+
+3. Connect your GitHub/GitLab account or use a public repository.
+
+4. Specify a project name and branch.
+
+   - **Build Command**: `npm run build`
+   - **Publish Directory**: `dist`
+
+5. Click **Create Static Site**.
+
+   Your app should be deployed at `https://.onrender.com/`.
+
+By default, any new commit pushed to the specified branch will automatically trigger a new deploy. [Auto-Deploy](https://render.com/docs/deploys#toggling-auto-deploy-for-a-service) can be configured in the project settings.
+
+You can also add a [custom domain](https://render.com/docs/custom-domains) to your project.
diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md
new file mode 100644
index 00000000000000..1665a982a91119
--- /dev/null
+++ b/docs/guide/troubleshooting.md
@@ -0,0 +1,91 @@
+# Troubleshooting
+
+See [Rollup's troubleshooting guide](https://rollupjs.org/guide/en/#troubleshooting) for more information too.
+
+If the suggestions here don't work, please try posting questions on [GitHub Discussions](https://github.com/vitejs/vite/discussions) or in the `#help` channel of [Vite Land Discord](https://chat.vitejs.dev).
+
+## CLI
+
+### `Error: Cannot find module 'C:\foo\bar&baz\vite\bin\vite.js'`
+
+The path to your project folder may include `&`, which doesn't work with `npm` on Windows ([npm/cmd-shim#45](https://github.com/npm/cmd-shim/issues/45)).
+
+You will need to either:
+
+- Switch to another package manager (e.g. `pnpm`, `yarn`)
+- Remove `&` from the path to your project
+
+## Dev Server
+
+### Requests are stalled forever
+
+If you are using Linux, file descriptor limits and inotify limits may be causing the issue. As Vite does not bundle most of the files, browsers may request many files which require many file descriptors, going over the limit.
+
+To solve this:
+
+- Increase file descriptor limit by `ulimit`
+
+  ```shell
+  # Check current limit
+  $ ulimit -Sn
+  # Change limit (temporary)
+  $ ulimit -Sn 10000 # You might need to change the hard limit too
+  # Restart your browser
+  ```
+
+- Increase the following inotify related limits by `sysctl`
+
+  ```shell
+  # Check current limits
+  $ sysctl fs.inotify
+  # Change limits (temporary)
+  $ sudo sysctl fs.inotify.max_queued_events=16384
+  $ sudo sysctl fs.inotify.max_user_instances=8192
+  $ sudo sysctl fs.inotify.max_user_watches=524288
+  ```
+
+### 431 Request Header Fields Too Large
+
+When the server / WebSocket server receives a large HTTP header, the request will be dropped and the following warning will be shown.
+
+> Server responded with status code 431. See https://vitejs.dev/guide/troubleshooting.html#_431-request-header-fields-too-large.
+
+This is because Node.js limits request header size to mitigate [CVE-2018-12121](https://www.cve.org/CVERecord?id=CVE-2018-12121).
+
+To avoid this, try to reduce your request header size. For example, if the cookie is long, delete it. Or you can use [`--max-http-header-size`](https://nodejs.org/api/cli.html#--max-http-header-sizesize) to change max header size.
+
+## HMR
+
+### Vite detects a file change but the HMR is not working
+
+You may be importing a file with a different case. For example, `src/foo.js` exists and `src/bar.js` contains:
+
+```js
+import './Foo.js' // should be './foo.js'
+```
+
+Related issue: [#964](https://github.com/vitejs/vite/issues/964)
+
+### Vite does not detect a file change
+
+If you are running Vite with WSL2, Vite cannot watch file changes in some conditions. See [`server.watch` option](/config/server-options.md#server-watch).
+
+### A full reload happens instead of HMR
+
+If HMR is not handled by Vite or a plugin, a full reload will happen.
+
+Also if there is a dependency loop, a full reload will happen. To solve this, try removing the loop.
+
+## Others
+
+### Syntax Error / Type Error happens
+
+Vite cannot handle and does not support code that only runs on non-strict mode (sloppy mode). This is because Vite uses ESM and it is always [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) inside ESM.
+
+For example, you might see these errors.
+
+> [ERROR] With statements cannot be used with the "esm" output format due to strict mode
+
+> TypeError: Cannot create property 'foo' on boolean 'false'
+
+If these code are used inside dependecies, you could use [`patch-package`](https://github.com/ds300/patch-package) (or [`yarn patch`](https://yarnpkg.com/cli/patch) or [`pnpm patch`](https://pnpm.io/cli/patch)) for an escape hatch.
diff --git a/docs/guide/why.md b/docs/guide/why.md
index 8a38c36ef89953..24b1acfef6358f 100644
--- a/docs/guide/why.md
+++ b/docs/guide/why.md
@@ -6,7 +6,7 @@ Before ES modules were available in browsers, developers had no native mechanism
 
 Over time we have seen tools like [webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org) and [Parcel](https://parceljs.org/), which greatly improved the development experience for frontend developers.
 
-However, as we build more and more ambitious applications, the amount of JavaScript we are dealing with is also increasing dramatically. It is not uncommon for large scale projects to contain thousands of modules. We are starting to hit a performance bottleneck for JavaScript based tooling: it can often take an unreasonably long wait (sometimes up to minutes!) to spin up a dev server, and even with HMR, file edits can take a couple of seconds to be reflected in the browser. The slow feedback loop can greatly affect developers' productivity and happiness.
+However, as we build more and more ambitious applications, the amount of JavaScript we are dealing with is also increasing dramatically. It is not uncommon for large scale projects to contain thousands of modules. We are starting to hit a performance bottleneck for JavaScript based tooling: it can often take an unreasonably long wait (sometimes up to minutes!) to spin up a dev server, and even with Hot Module Replacement (HMR), file edits can take a couple of seconds to be reflected in the browser. The slow feedback loop can greatly affect developers' productivity and happiness.
 
 Vite aims to address these issues by leveraging new advancements in the ecosystem: the availability of native ES modules in the browser, and the rise of JavaScript tools written in compile-to-native languages.
 
@@ -24,9 +24,12 @@ Vite improves the dev server start time by first dividing the modules in an appl
 
   Vite serves source code over [native ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). This is essentially letting the browser take over part of the job of a bundler: Vite only needs to transform and serve source code on demand, as the browser requests it. Code behind conditional dynamic imports is only processed if actually used on the current screen.
 
-  ![bundler based dev server](/images/bundler.png)
-
-  ![esm based dev server](/images/esm.png)
+
+
+
 
 ### Slow Updates
 
diff --git a/docs/images/bundler.png b/docs/images/bundler.png
deleted file mode 100644
index 22d0a072dc7303..00000000000000
Binary files a/docs/images/bundler.png and /dev/null differ
diff --git a/docs/images/bundler.svg b/docs/images/bundler.svg
new file mode 100644
index 00000000000000..598f708c8c5cc5
--- /dev/null
+++ b/docs/images/bundler.svg
@@ -0,0 +1,37 @@
+
+Bundle based dev server
+
+
+entry
+
+···
+
+route
+
+route
+
+
+
+
+
+
+
+
+
+
+module
+
+module
+
+module
+
+module
+
+···
+
+
+
+Bundle
+
+Server
ready
+
diff --git a/docs/images/diagrams.fig b/docs/images/diagrams.fig
new file mode 100644
index 00000000000000..300edd04609ba8
Binary files /dev/null and b/docs/images/diagrams.fig differ
diff --git a/docs/images/esm.png b/docs/images/esm.png
deleted file mode 100644
index 2998a6d0688dee..00000000000000
Binary files a/docs/images/esm.png and /dev/null differ
diff --git a/docs/images/esm.svg b/docs/images/esm.svg
new file mode 100644
index 00000000000000..ac772db0bb80a4
--- /dev/null
+++ b/docs/images/esm.svg
@@ -0,0 +1,51 @@
+
+Native ESM based dev server
+
+entry
+
+
+···
+
+
+route
+
+route
+
+
+
+
+
+
+
+
+
+
+
+module
+
+module
+
+module
+
+module
+
+···
+
+Server
ready
+
+
+Dynamic import
(code split point)
+HTTP request
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/images/graph.png b/docs/images/graph.png
deleted file mode 100644
index 8b45aa9b673a6e..00000000000000
Binary files a/docs/images/graph.png and /dev/null differ
diff --git a/docs/images/graph.svg b/docs/images/graph.svg
new file mode 100644
index 00000000000000..df02c439121b29
--- /dev/null
+++ b/docs/images/graph.svg
@@ -0,0 +1,16 @@
+
+
+Entry
+
+async chunk A
+
+common chunk C
+
+async chunk B
+
+
+dynamic import
+direct import
+
+
+
diff --git a/docs/public/viteconf.svg b/docs/public/viteconf.svg
new file mode 100644
index 00000000000000..a01c0bd224407c
--- /dev/null
+++ b/docs/public/viteconf.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/netlify.toml b/netlify.toml
index f618d808000f61..10bc161218e1cc 100644
--- a/netlify.toml
+++ b/netlify.toml
@@ -4,4 +4,4 @@
 [build]
   publish = "docs/.vitepress/dist"
   command = "npx pnpm i --store=node_modules/.pnpm-store --frozen-lockfile && npm run ci-docs"
-  ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF docs package.json pnpm-lock.yaml netlify.toml"
\ No newline at end of file
+  ignore = "./scripts/docs-check.sh"
diff --git a/package.json b/package.json
index ab9cbb5990503d..01b9666a888999 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "vite-monorepo",
   "private": true,
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "homepage": "https://vitejs.dev/",
   "keywords": [
@@ -16,7 +16,7 @@
     "preinstall": "npx only-allow pnpm",
     "postinstall": "simple-git-hooks",
     "format": "prettier --write --cache .",
-    "lint": "eslint --cache packages/*/{src,types,__tests__}/** playground/**/__tests__/**/*.ts scripts/**",
+    "lint": "eslint --cache .",
     "typecheck": "tsc -p scripts --noEmit && tsc -p playground --noEmit",
     "test": "run-s test-unit test-serve test-build",
     "test-serve": "vitest run -c vitest.config.e2e.ts",
@@ -36,21 +36,19 @@
     "ci-docs": "run-s build docs-build"
   },
   "devDependencies": {
-    "@babel/types": "^7.18.8",
-    "@microsoft/api-extractor": "^7.28.4",
-    "@rollup/plugin-typescript": "^8.3.3",
+    "@babel/types": "^7.18.10",
+    "@microsoft/api-extractor": "^7.29.0",
+    "@rollup/plugin-typescript": "^8.3.4",
     "@types/babel__core": "^7.1.19",
     "@types/babel__standalone": "^7.1.4",
     "@types/convert-source-map": "^1.5.2",
     "@types/cross-spawn": "^6.0.2",
     "@types/debug": "^4.1.7",
-    "@types/estree": "^0.0.52",
+    "@types/estree": "^1.0.0",
     "@types/etag": "^1.8.1",
     "@types/fs-extra": "^9.0.13",
-    "@types/hash-sum": "^1.0.0",
     "@types/less": "^3.0.3",
     "@types/micromatch": "^4.0.2",
-    "@types/mime": "^2.0.3",
     "@types/minimist": "^1.2.2",
     "@types/node": "^17.0.42",
     "@types/prompts": "^2.4.0",
@@ -59,39 +57,36 @@
     "@types/semver": "^7.3.10",
     "@types/stylus": "^0.48.38",
     "@types/ws": "^8.5.3",
-    "@typescript-eslint/eslint-plugin": "^5.30.5",
-    "@typescript-eslint/parser": "^5.30.5",
+    "@typescript-eslint/eslint-plugin": "^5.33.0",
+    "@typescript-eslint/parser": "^5.33.0",
     "conventional-changelog-cli": "^2.2.2",
     "cross-env": "^7.0.3",
     "esbuild": "^0.14.47",
-    "eslint": "^8.19.0",
-    "eslint-define-config": "^1.5.1",
+    "eslint": "^8.21.0",
+    "eslint-define-config": "^1.6.0",
     "eslint-plugin-import": "^2.26.0",
     "eslint-plugin-node": "^11.1.0",
     "execa": "^6.1.0",
     "fs-extra": "^10.1.0",
-    "kill-port": "^1.6.1",
     "lint-staged": "^13.0.3",
     "minimist": "^1.2.6",
-    "node-fetch": "^3.2.6",
     "npm-run-all": "^4.1.5",
     "picocolors": "^1.0.0",
-    "playwright-chromium": "^1.23.2",
-    "pnpm": "^7.5.0",
+    "playwright-chromium": "^1.24.2",
+    "pnpm": "^7.9.0",
     "prettier": "2.7.1",
     "prompts": "^2.4.2",
     "rimraf": "^3.0.2",
-    "rollup": "^2.75.6",
+    "rollup": ">=2.75.6 <2.77.0 || ~2.77.0",
     "semver": "^7.3.7",
     "simple-git-hooks": "^2.8.0",
-    "sirv": "^2.0.2",
     "tslib": "^2.4.0",
-    "tsx": "^3.7.1",
+    "tsx": "^3.8.1",
     "typescript": "^4.6.4",
-    "unbuild": "^0.7.4",
+    "unbuild": "^0.7.6",
     "vite": "workspace:*",
     "vitepress": "^1.0.0-alpha.4",
-    "vitest": "^0.18.0",
+    "vitest": "^0.21.0",
     "vue": "^3.2.37"
   },
   "simple-git-hooks": {
@@ -112,7 +107,7 @@
       "eslint --cache --fix"
     ]
   },
-  "packageManager": "pnpm@7.5.0",
+  "packageManager": "pnpm@7.9.0",
   "pnpm": {
     "overrides": {
       "vite": "workspace:*",
diff --git a/packages/create-vite/CHANGELOG.md b/packages/create-vite/CHANGELOG.md
index be26f7b3cce15a..4068e766bbcfcc 100644
--- a/packages/create-vite/CHANGELOG.md
+++ b/packages/create-vite/CHANGELOG.md
@@ -1,3 +1,16 @@
+## 3.0.1 (2022-08-11)
+
+* fix: mention that Node.js 13/15 support is dropped (fixes #9113) (#9116) ([2826303](https://github.com/vitejs/vite/commit/2826303)), closes [#9113](https://github.com/vitejs/vite/issues/9113) [#9116](https://github.com/vitejs/vite/issues/9116)
+* fix(create-vite): update vanilla-ts brand color (#9254) ([bff3abb](https://github.com/vitejs/vite/commit/bff3abb)), closes [#9254](https://github.com/vitejs/vite/issues/9254)
+* fix(deps): update all non-major dependencies (#9176) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70)), closes [#9176](https://github.com/vitejs/vite/issues/9176)
+* fix(deps): update all non-major dependencies (#9575) ([8071325](https://github.com/vitejs/vite/commit/8071325)), closes [#9575](https://github.com/vitejs/vite/issues/9575)
+* chore: remove unused `favicon.svg` (#9181) ([33b5b0d](https://github.com/vitejs/vite/commit/33b5b0d)), closes [#9181](https://github.com/vitejs/vite/issues/9181)
+* chore: tidy up eslint config (#9468) ([f4addcf](https://github.com/vitejs/vite/commit/f4addcf)), closes [#9468](https://github.com/vitejs/vite/issues/9468)
+* chore(deps): update all non-major dependencies (#9347) ([2fcb027](https://github.com/vitejs/vite/commit/2fcb027)), closes [#9347](https://github.com/vitejs/vite/issues/9347)
+* chore(deps): update all non-major dependencies (#9478) ([c530d16](https://github.com/vitejs/vite/commit/c530d16)), closes [#9478](https://github.com/vitejs/vite/issues/9478)
+
+
+
 ## 3.0.0 (2022-07-13)
 
 * chore: bump minors and rebuild lock (#8074) ([aeb5b74](https://github.com/vitejs/vite/commit/aeb5b74)), closes [#8074](https://github.com/vitejs/vite/issues/8074)
diff --git a/packages/create-vite/README.md b/packages/create-vite/README.md
index 519268a4d79da2..015fd257461ed5 100644
--- a/packages/create-vite/README.md
+++ b/packages/create-vite/README.md
@@ -3,7 +3,7 @@
 ## Scaffolding Your First Vite Project
 
 > **Compatibility Note:**
-> Vite requires [Node.js](https://nodejs.org/en/) version >=14.18.0. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
+> Vite requires [Node.js](https://nodejs.org/en/) version 14.18+, 16+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.
 
 With NPM:
 
diff --git a/packages/create-vite/package.json b/packages/create-vite/package.json
index d89821f2405ee6..5e99524d2a77a7 100644
--- a/packages/create-vite/package.json
+++ b/packages/create-vite/package.json
@@ -1,6 +1,6 @@
 {
   "name": "create-vite",
-  "version": "3.0.0",
+  "version": "3.0.1",
   "type": "module",
   "license": "MIT",
   "author": "Evan You",
@@ -14,7 +14,7 @@
   ],
   "main": "index.js",
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
diff --git a/packages/create-vite/template-lit-ts/package.json b/packages/create-vite/template-lit-ts/package.json
index 9ac74b11ea8f67..9fa7c37cd99e8a 100644
--- a/packages/create-vite/template-lit-ts/package.json
+++ b/packages/create-vite/template-lit-ts/package.json
@@ -17,10 +17,10 @@
     "build": "tsc && vite build"
   },
   "dependencies": {
-    "lit": "^2.2.7"
+    "lit": "^2.2.8"
   },
   "devDependencies": {
     "typescript": "^4.6.4",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-lit-ts/src/my-element.ts b/packages/create-vite/template-lit-ts/src/my-element.ts
index da680eb1d0f19c..dde5d8cd50de89 100644
--- a/packages/create-vite/template-lit-ts/src/my-element.ts
+++ b/packages/create-vite/template-lit-ts/src/my-element.ts
@@ -1,4 +1,4 @@
-import { html, css, LitElement } from 'lit'
+import { LitElement, css, html } from 'lit'
 import { customElement, property } from 'lit/decorators.js'
 import litLogo from './assets/lit.svg'
 
diff --git a/packages/create-vite/template-lit/package.json b/packages/create-vite/template-lit/package.json
index bc4f15d8277c38..2b52a43d7a3757 100644
--- a/packages/create-vite/template-lit/package.json
+++ b/packages/create-vite/template-lit/package.json
@@ -15,9 +15,9 @@
     "build": "vite build"
   },
   "dependencies": {
-    "lit": "^2.2.7"
+    "lit": "^2.2.8"
   },
   "devDependencies": {
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-lit/src/my-element.js b/packages/create-vite/template-lit/src/my-element.js
index 411701454b89de..7c0c0426e49116 100644
--- a/packages/create-vite/template-lit/src/my-element.js
+++ b/packages/create-vite/template-lit/src/my-element.js
@@ -1,4 +1,4 @@
-import { html, css, LitElement } from 'lit'
+import { LitElement, css, html } from 'lit'
 import litLogo from './assets/lit.svg'
 
 /**
diff --git a/packages/create-vite/template-preact-ts/package.json b/packages/create-vite/template-preact-ts/package.json
index 3b2a0782034603..6740904b1692c8 100644
--- a/packages/create-vite/template-preact-ts/package.json
+++ b/packages/create-vite/template-preact-ts/package.json
@@ -9,11 +9,11 @@
     "preview": "vite preview"
   },
   "dependencies": {
-    "preact": "^10.9.0"
+    "preact": "^10.10.1"
   },
   "devDependencies": {
     "@preact/preset-vite": "^2.3.0",
     "typescript": "^4.6.4",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-preact/package.json b/packages/create-vite/template-preact/package.json
index c23859f67f7259..e0494c1c77a2e6 100644
--- a/packages/create-vite/template-preact/package.json
+++ b/packages/create-vite/template-preact/package.json
@@ -9,10 +9,10 @@
     "preview": "vite preview"
   },
   "dependencies": {
-    "preact": "^10.9.0"
+    "preact": "^10.10.1"
   },
   "devDependencies": {
     "@preact/preset-vite": "^2.3.0",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-react-ts/package.json b/packages/create-vite/template-react-ts/package.json
index a50daeb100cd80..f88aa1744a4bd6 100644
--- a/packages/create-vite/template-react-ts/package.json
+++ b/packages/create-vite/template-react-ts/package.json
@@ -13,10 +13,10 @@
     "react-dom": "^18.2.0"
   },
   "devDependencies": {
-    "@types/react": "^18.0.15",
+    "@types/react": "^18.0.17",
     "@types/react-dom": "^18.0.6",
-    "@vitejs/plugin-react": "^2.0.0",
+    "@vitejs/plugin-react": "^2.0.1",
     "typescript": "^4.6.4",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-react/package.json b/packages/create-vite/template-react/package.json
index 8da24a1e6f37a5..4f312ad0a63c1a 100644
--- a/packages/create-vite/template-react/package.json
+++ b/packages/create-vite/template-react/package.json
@@ -13,9 +13,9 @@
     "react-dom": "^18.2.0"
   },
   "devDependencies": {
-    "@types/react": "^18.0.15",
+    "@types/react": "^18.0.17",
     "@types/react-dom": "^18.0.6",
-    "@vitejs/plugin-react": "^2.0.0",
-    "vite": "^3.0.0"
+    "@vitejs/plugin-react": "^2.0.1",
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-svelte-ts/package.json b/packages/create-vite/template-svelte-ts/package.json
index 840e12ccf4f727..68da7b6136b0a0 100644
--- a/packages/create-vite/template-svelte-ts/package.json
+++ b/packages/create-vite/template-svelte-ts/package.json
@@ -17,6 +17,6 @@
     "svelte-preprocess": "^4.10.7",
     "tslib": "^2.4.0",
     "typescript": "^4.6.4",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-svelte/package.json b/packages/create-vite/template-svelte/package.json
index a013a8d12ab2bd..a142f278cb2dd5 100644
--- a/packages/create-vite/template-svelte/package.json
+++ b/packages/create-vite/template-svelte/package.json
@@ -11,6 +11,6 @@
   "devDependencies": {
     "@sveltejs/vite-plugin-svelte": "^1.0.1",
     "svelte": "^3.49.0",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-vanilla-ts/favicon.svg b/packages/create-vite/template-vanilla-ts/favicon.svg
deleted file mode 100644
index de4aeddc12bdfe..00000000000000
--- a/packages/create-vite/template-vanilla-ts/favicon.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/create-vite/template-vanilla-ts/package.json b/packages/create-vite/template-vanilla-ts/package.json
index d01e7542d12f7f..dea7fe68c9cd3a 100644
--- a/packages/create-vite/template-vanilla-ts/package.json
+++ b/packages/create-vite/template-vanilla-ts/package.json
@@ -10,6 +10,6 @@
   },
   "devDependencies": {
     "typescript": "^4.6.4",
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-vanilla-ts/src/style.css b/packages/create-vite/template-vanilla-ts/src/style.css
index 12320801d3635d..ac37d84b935425 100644
--- a/packages/create-vite/template-vanilla-ts/src/style.css
+++ b/packages/create-vite/template-vanilla-ts/src/style.css
@@ -53,7 +53,7 @@ h1 {
   filter: drop-shadow(0 0 2em #646cffaa);
 }
 .logo.vanilla:hover {
-  filter: drop-shadow(0 0 2em #f7df1eaa);
+  filter: drop-shadow(0 0 2em #3178c6aa);
 }
 
 .card {
diff --git a/packages/create-vite/template-vanilla/package.json b/packages/create-vite/template-vanilla/package.json
index 7a2186365da8eb..93792cc4720e0d 100644
--- a/packages/create-vite/template-vanilla/package.json
+++ b/packages/create-vite/template-vanilla/package.json
@@ -9,6 +9,6 @@
     "preview": "vite preview"
   },
   "devDependencies": {
-    "vite": "^3.0.0"
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/create-vite/template-vue-ts/package.json b/packages/create-vite/template-vue-ts/package.json
index 65f699266a576c..2385dc04fcf25d 100644
--- a/packages/create-vite/template-vue-ts/package.json
+++ b/packages/create-vite/template-vue-ts/package.json
@@ -12,9 +12,9 @@
     "vue": "^3.2.37"
   },
   "devDependencies": {
-    "@vitejs/plugin-vue": "^3.0.0",
+    "@vitejs/plugin-vue": "^3.0.2",
     "typescript": "^4.6.4",
-    "vite": "^3.0.0",
-    "vue-tsc": "^0.38.4"
+    "vite": "^3.0.6",
+    "vue-tsc": "^0.39.5"
   }
 }
diff --git a/packages/create-vite/template-vue/package.json b/packages/create-vite/template-vue/package.json
index 17fa3246866674..65cbd6f84d6fca 100644
--- a/packages/create-vite/template-vue/package.json
+++ b/packages/create-vite/template-vue/package.json
@@ -12,7 +12,7 @@
     "vue": "^3.2.37"
   },
   "devDependencies": {
-    "@vitejs/plugin-vue": "^3.0.0",
-    "vite": "^3.0.0"
+    "@vitejs/plugin-vue": "^3.0.2",
+    "vite": "^3.0.6"
   }
 }
diff --git a/packages/plugin-legacy/CHANGELOG.md b/packages/plugin-legacy/CHANGELOG.md
index 11783e3f959c44..7d38d423c5c3a6 100644
--- a/packages/plugin-legacy/CHANGELOG.md
+++ b/packages/plugin-legacy/CHANGELOG.md
@@ -1,3 +1,15 @@
+## 2.0.1 (2022-08-11)
+
+* fix: mention that Node.js 13/15 support is dropped (fixes #9113) (#9116) ([2826303](https://github.com/vitejs/vite/commit/2826303)), closes [#9113](https://github.com/vitejs/vite/issues/9113) [#9116](https://github.com/vitejs/vite/issues/9116)
+* fix(deps): update all non-major dependencies (#9176) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70)), closes [#9176](https://github.com/vitejs/vite/issues/9176)
+* fix(deps): update all non-major dependencies (#9575) ([8071325](https://github.com/vitejs/vite/commit/8071325)), closes [#9575](https://github.com/vitejs/vite/issues/9575)
+* fix(legacy): skip esbuild transform for systemjs (#9635) ([ac16abd](https://github.com/vitejs/vite/commit/ac16abd)), closes [#9635](https://github.com/vitejs/vite/issues/9635)
+* chore: fix code typos (#9033) ([ed02861](https://github.com/vitejs/vite/commit/ed02861)), closes [#9033](https://github.com/vitejs/vite/issues/9033)
+* chore(deps): update all non-major dependencies (#9347) ([2fcb027](https://github.com/vitejs/vite/commit/2fcb027)), closes [#9347](https://github.com/vitejs/vite/issues/9347)
+* chore(deps): update all non-major dependencies (#9478) ([c530d16](https://github.com/vitejs/vite/commit/c530d16)), closes [#9478](https://github.com/vitejs/vite/issues/9478)
+
+
+
 ## 2.0.0 (2022-07-13)
 
 * chore: 3.0 release notes and bump peer deps (#9072) ([427ba26](https://github.com/vitejs/vite/commit/427ba26)), closes [#9072](https://github.com/vitejs/vite/issues/9072)
diff --git a/packages/plugin-legacy/LICENSE b/packages/plugin-legacy/LICENSE
new file mode 100644
index 00000000000000..9c1b313d7b1816
--- /dev/null
+++ b/packages/plugin-legacy/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json
index 168095efcd9d30..fe8524ed2c58bf 100644
--- a/packages/plugin-legacy/package.json
+++ b/packages/plugin-legacy/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@vitejs/plugin-legacy",
-  "version": "2.0.0",
+  "version": "2.0.1",
   "license": "MIT",
   "author": "Evan You",
   "files": [
@@ -23,7 +23,7 @@
     "prepublishOnly": "npm run build"
   },
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
@@ -35,8 +35,8 @@
   },
   "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
   "dependencies": {
-    "@babel/standalone": "^7.18.8",
-    "core-js": "^3.23.4",
+    "@babel/standalone": "^7.18.12",
+    "core-js": "^3.24.1",
     "magic-string": "^0.26.2",
     "regenerator-runtime": "^0.13.9",
     "systemjs": "^6.12.1"
@@ -46,7 +46,7 @@
     "vite": "^3.0.0"
   },
   "devDependencies": {
-    "@babel/core": "^7.18.6",
+    "@babel/core": "^7.18.10",
     "vite": "workspace:*"
   }
 }
diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts
index ca79a56f160146..0de7b072edbab8 100644
--- a/packages/plugin-legacy/src/index.ts
+++ b/packages/plugin-legacy/src/index.ts
@@ -710,6 +710,21 @@ function polyfillsPlugin(
           (excludeSystemJS ? '' : `import "systemjs/dist/s.min.js";`)
         )
       }
+    },
+    renderChunk(_, __, opts) {
+      // systemjs includes code that can't be minified down to es5 by esbuild
+      if (!excludeSystemJS) {
+        // @ts-ignore avoid esbuild transform on legacy chunks since it produces
+        // legacy-unsafe code - e.g. rewriting object properties into shorthands
+        opts.__vite_skip_esbuild__ = true
+
+        // @ts-ignore force terser for legacy chunks. This only takes effect if
+        // minification isn't disabled, because that leaves out the terser plugin
+        // entirely.
+        opts.__vite_force_terser__ = true
+      }
+
+      return null
     }
   }
 }
diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md
index 78b6de12fea5f0..8df2a245c5f296 100644
--- a/packages/plugin-react/CHANGELOG.md
+++ b/packages/plugin-react/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 2.0.1 (2022-08-11)
+
+* fix: don't count class declarations as react fast refresh boundry (fixes #3675) (#8887) ([5a18284](https://github.com/vitejs/vite/commit/5a18284)), closes [#3675](https://github.com/vitejs/vite/issues/3675) [#8887](https://github.com/vitejs/vite/issues/8887)
+* fix: mention that Node.js 13/15 support is dropped (fixes #9113) (#9116) ([2826303](https://github.com/vitejs/vite/commit/2826303)), closes [#9113](https://github.com/vitejs/vite/issues/9113) [#9116](https://github.com/vitejs/vite/issues/9116)
+* fix(deps): update all non-major dependencies (#9176) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70)), closes [#9176](https://github.com/vitejs/vite/issues/9176)
+* fix(deps): update all non-major dependencies (#9575) ([8071325](https://github.com/vitejs/vite/commit/8071325)), closes [#9575](https://github.com/vitejs/vite/issues/9575)
+* fix(plugin-react): wrong substitution causes `React is not defined` (#9386) ([8a5b575](https://github.com/vitejs/vite/commit/8a5b575)), closes [#9386](https://github.com/vitejs/vite/issues/9386)
+* docs: fix server options link (#9242) ([29db3ea](https://github.com/vitejs/vite/commit/29db3ea)), closes [#9242](https://github.com/vitejs/vite/issues/9242)
+
+
+
 ## 2.0.0 (2022-07-13)
 
 * chore: 3.0 release notes and bump peer deps (#9072) ([427ba26](https://github.com/vitejs/vite/commit/427ba26)), closes [#9072](https://github.com/vitejs/vite/issues/9072)
diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md
index e8d27d0e57242b..6a8f3cb0ac9e21 100644
--- a/packages/plugin-react/README.md
+++ b/packages/plugin-react/README.md
@@ -83,7 +83,7 @@ Here's the [complete list of Babel parser plugins](https://babeljs.io/docs/en/ba
 
 ## Middleware mode
 
-In [middleware mode](https://vitejs.dev/config/#server-middlewaremode), you should make sure your entry `index.html` file is transformed by Vite. Here's an example for an Express server:
+In [middleware mode](https://vitejs.dev/config/server-options.html#server-middlewaremode), you should make sure your entry `index.html` file is transformed by Vite. Here's an example for an Express server:
 
 ```js
 app.get('/', async (req, res, next) => {
diff --git a/packages/plugin-react/package.json b/packages/plugin-react/package.json
index 9f5332d16165f1..7b13e17ac9217b 100644
--- a/packages/plugin-react/package.json
+++ b/packages/plugin-react/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@vitejs/plugin-react",
-  "version": "2.0.0",
+  "version": "2.0.1",
   "license": "MIT",
   "author": "Evan You",
   "contributors": [
@@ -27,7 +27,7 @@
     "prepublishOnly": "npm run build"
   },
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
@@ -39,8 +39,8 @@
   },
   "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-react#readme",
   "dependencies": {
-    "@babel/core": "^7.18.6",
-    "@babel/plugin-transform-react-jsx": "^7.18.6",
+    "@babel/core": "^7.18.10",
+    "@babel/plugin-transform-react-jsx": "^7.18.10",
     "@babel/plugin-transform-react-jsx-development": "^7.18.6",
     "@babel/plugin-transform-react-jsx-self": "^7.18.6",
     "@babel/plugin-transform-react-jsx-source": "^7.18.6",
diff --git a/packages/plugin-react/src/fast-refresh.ts b/packages/plugin-react/src/fast-refresh.ts
index 6e5019d1e059df..b3b095a65cf2ae 100644
--- a/packages/plugin-react/src/fast-refresh.ts
+++ b/packages/plugin-react/src/fast-refresh.ts
@@ -92,6 +92,7 @@ export function isRefreshBoundary(ast: t.File): boolean {
     }
     const { declaration, specifiers } = node
     if (declaration) {
+      if (declaration.type === 'ClassDeclaration') return false
       if (declaration.type === 'VariableDeclaration') {
         return declaration.declarations.every((variable) =>
           isComponentLikeIdentifier(variable.id)
diff --git a/packages/plugin-react/src/jsx-runtime/babel-restore-jsx.ts b/packages/plugin-react/src/jsx-runtime/babel-restore-jsx.ts
index 669a0aeeced207..91b4db5411bf26 100644
--- a/packages/plugin-react/src/jsx-runtime/babel-restore-jsx.ts
+++ b/packages/plugin-react/src/jsx-runtime/babel-restore-jsx.ts
@@ -4,6 +4,10 @@
  */
 import type * as babel from '@babel/core'
 
+interface PluginOptions {
+  reactAlias: string
+}
+
 /**
  * Visitor factory for babel, converting React.createElement(...) to ...
  *
@@ -17,7 +21,10 @@ import type * as babel from '@babel/core'
  *
  * Any of those arguments might also be missing (undefined) and/or invalid.
  */
-export default function ({ types: t }: typeof babel): babel.PluginObj {
+export default function (
+  { types: t }: typeof babel,
+  { reactAlias = 'React' }: PluginOptions
+): babel.PluginObj {
   /**
    * Get a `JSXElement` from a `CallExpression`.
    * Returns `null` if this impossible.
@@ -48,7 +55,7 @@ export default function ({ types: t }: typeof babel): babel.PluginObj {
     if (
       t.isJSXMemberExpression(name) &&
       t.isJSXIdentifier(name.object) &&
-      name.object.name === 'React' &&
+      name.object.name === reactAlias &&
       name.property.name === 'Fragment'
     ) {
       return t.jsxFragment(
@@ -182,7 +189,7 @@ export default function ({ types: t }: typeof babel): babel.PluginObj {
   const isReactCreateElement = (node: any) =>
     t.isCallExpression(node) &&
     t.isMemberExpression(node.callee) &&
-    t.isIdentifier(node.callee.object, { name: 'React' }) &&
+    t.isIdentifier(node.callee.object, { name: reactAlias }) &&
     t.isIdentifier(node.callee.property, { name: 'createElement' }) &&
     !node.callee.computed
 
diff --git a/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts b/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts
index 7d5b14bfc9cfd4..00ea39673ec415 100644
--- a/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts
+++ b/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts
@@ -81,7 +81,10 @@ describe('restore-jsx', () => {
     expect(
       await jsx(`import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
       React__default.createElement(foo)`)
-    ).toBeNull()
+    ).toMatchInlineSnapshot(`
+      "import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
+      React__default.createElement(foo);"
+    `)
     expect(
       await jsx(`import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
       React__default.createElement("h1")`)
@@ -104,7 +107,12 @@ describe('restore-jsx', () => {
     expect(
       await jsx(`import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
       React__default.createElement(foo, {hi: there})`)
-    ).toBeNull()
+    ).toMatchInlineSnapshot(`
+      "import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
+      React__default.createElement(foo, {
+        hi: there
+      });"
+    `)
     expect(
       await jsx(`import React__default, { PureComponent, Component, forwardRef, memo, createElement } from 'react';
     React__default.createElement("h1", {hi: there})`)
@@ -114,4 +122,26 @@ describe('restore-jsx', () => {
       React__default.createElement(Foo, {hi: there})`)
     ).toMatch(`;`)
   })
+
+  it('should handle Fragment', async () => {
+    expect(
+      await jsx(`import R, { Fragment } from 'react';
+        R.createElement(Fragment)
+      `)
+    ).toMatchInlineSnapshot(`
+      "import R, { Fragment } from 'react';
+      ;"
+    `)
+  })
+
+  it('should handle Fragment alias', async () => {
+    expect(
+      await jsx(`import RA, { Fragment as F } from 'react';
+        RA.createElement(F, null, RA.createElement(RA.Fragment))
+      `)
+    ).toMatchInlineSnapshot(`
+      "import RA, { Fragment as F } from 'react';
+      <>;"
+    `)
+  })
 })
diff --git a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts
index d67a54e8f08aad..ddc3c1530e0d9f 100644
--- a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts
+++ b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts
@@ -33,34 +33,12 @@ export async function restoreJSX(
     return jsxNotFound
   }
 
-  let hasCompiledJsx = false
-
-  const fragmentPattern = `\\b${reactAlias}\\.Fragment\\b`
-  const createElementPattern = `\\b${reactAlias}\\.createElement\\(\\s*([A-Z"'][\\w$.]*["']?)`
-
-  // Replace the alias with "React" so JSX can be reverse compiled.
-  code = code
-    .replace(new RegExp(fragmentPattern, 'g'), () => {
-      hasCompiledJsx = true
-      return 'React.Fragment'
-    })
-    .replace(new RegExp(createElementPattern, 'g'), (original, component) => {
-      if (/^[a-z][\w$]*$/.test(component)) {
-        // Take care not to replace the alias for `createElement` calls whose
-        // component is a lowercased variable, since the `restoreJSX` Babel
-        // plugin leaves them untouched.
-        return original
-      }
-      hasCompiledJsx = true
-      return (
-        'React.createElement(' +
-        // Assume `Fragment` is equivalent to `React.Fragment` so modules
-        // that use `import {Fragment} from 'react'` are reverse compiled.
-        (component === 'Fragment' ? 'React.Fragment' : component)
-      )
-    })
+  const reactJsxRE = new RegExp(
+    `\\b${reactAlias}\\.(createElement|Fragment)\\b`,
+    'g'
+  )
 
-  if (!hasCompiledJsx) {
+  if (!reactJsxRE.test(code)) {
     return jsxNotFound
   }
 
@@ -73,7 +51,7 @@ export async function restoreJSX(
     parserOpts: {
       plugins: ['jsx']
     },
-    plugins: [await getBabelRestoreJSX()]
+    plugins: [[await getBabelRestoreJSX(), { reactAlias }]]
   })
 
   return [result?.ast, isCommonJS]
diff --git a/packages/plugin-vue-jsx/package.json b/packages/plugin-vue-jsx/package.json
index a6ea702884f7b3..39eba505c6d54e 100644
--- a/packages/plugin-vue-jsx/package.json
+++ b/packages/plugin-vue-jsx/package.json
@@ -23,7 +23,7 @@
     "prepublishOnly": "npm run build"
   },
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
@@ -35,9 +35,9 @@
   },
   "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx#readme",
   "dependencies": {
-    "@babel/core": "^7.18.6",
+    "@babel/core": "^7.18.10",
     "@babel/plugin-syntax-import-meta": "^7.10.4",
-    "@babel/plugin-transform-typescript": "^7.18.8",
+    "@babel/plugin-transform-typescript": "^7.18.12",
     "@vue/babel-plugin-jsx": "^1.1.1"
   },
   "devDependencies": {
diff --git a/packages/plugin-vue/CHANGELOG.md b/packages/plugin-vue/CHANGELOG.md
index b71b477954bd1c..7044a8b7aef3a4 100644
--- a/packages/plugin-vue/CHANGELOG.md
+++ b/packages/plugin-vue/CHANGELOG.md
@@ -1,3 +1,18 @@
+## 3.0.2 (2022-08-11)
+
+* chore: fix code typos (#9033) ([ed02861](https://github.com/vitejs/vite/commit/ed02861)), closes [#9033](https://github.com/vitejs/vite/issues/9033)
+* chore: narrow down rollup version (#9637) ([fcf4d98](https://github.com/vitejs/vite/commit/fcf4d98)), closes [#9637](https://github.com/vitejs/vite/issues/9637)
+
+
+
+## 3.0.1 (2022-07-18)
+
+* fix: mention that Node.js 13/15 support is dropped (fixes #9113) (#9116) ([2826303](https://github.com/vitejs/vite/commit/2826303)), closes [#9113](https://github.com/vitejs/vite/issues/9113) [#9116](https://github.com/vitejs/vite/issues/9116)
+* fix(vue): remove ssr.external config (#9128) ([ec91f98](https://github.com/vitejs/vite/commit/ec91f98)), closes [#9128](https://github.com/vitejs/vite/issues/9128)
+* refactor(vue): limit passable compilerOptions (#8994) ([b7b3e65](https://github.com/vitejs/vite/commit/b7b3e65)), closes [#8994](https://github.com/vitejs/vite/issues/8994)
+
+
+
 ## 3.0.0 (2022-07-13)
 
 * chore: 3.0 release notes and bump peer deps (#9072) ([427ba26](https://github.com/vitejs/vite/commit/427ba26)), closes [#9072](https://github.com/vitejs/vite/issues/9072)
diff --git a/packages/plugin-vue/LICENSE b/packages/plugin-vue/LICENSE
index b3d494d14e9c88..9c1b313d7b1816 100644
--- a/packages/plugin-vue/LICENSE
+++ b/packages/plugin-vue/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2019-present, Yuxi (Evan) You and contributors
+Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/packages/plugin-vue/README.md b/packages/plugin-vue/README.md
index 5f2236edf02604..be02ab7ae4ab36 100644
--- a/packages/plugin-vue/README.md
+++ b/packages/plugin-vue/README.md
@@ -45,9 +45,18 @@ export interface Options {
   reactivityTransform?: boolean | string | RegExp | (string | RegExp)[]
 
   // options to pass on to vue/compiler-sfc
-  script?: Partial
-  template?: Partial
-  style?: Partial
+  script?: Partial>
+  template?: Partial<
+    Pick<
+      SFCTemplateCompileOptions,
+      | 'compiler'
+      | 'compilerOptions'
+      | 'preprocessOptions'
+      | 'preprocessCustomRequire'
+      | 'transformAssetUrls'
+    >
+  >
+  style?: Partial>
 }
 ```
 
diff --git a/packages/plugin-vue/package.json b/packages/plugin-vue/package.json
index b588b166dace47..f50a11c9f796ef 100644
--- a/packages/plugin-vue/package.json
+++ b/packages/plugin-vue/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@vitejs/plugin-vue",
-  "version": "3.0.0",
+  "version": "3.0.2",
   "license": "MIT",
   "author": "Evan You",
   "files": [
@@ -23,7 +23,7 @@
     "prepublishOnly": "npm run build"
   },
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
@@ -42,7 +42,7 @@
     "@jridgewell/gen-mapping": "^0.3.2",
     "@jridgewell/trace-mapping": "^0.3.14",
     "debug": "^4.3.4",
-    "rollup": "^2.75.6",
+    "rollup": ">=2.75.6 <2.77.0 || ~2.77.0",
     "slash": "^4.0.0",
     "source-map": "^0.6.1",
     "vite": "workspace:*",
diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts
index 6bc0db06fe2b10..5a7a6947929be4 100644
--- a/packages/plugin-vue/src/index.ts
+++ b/packages/plugin-vue/src/index.ts
@@ -30,9 +30,18 @@ export interface Options {
   isProduction?: boolean
 
   // options to pass on to vue/compiler-sfc
-  script?: Partial
-  template?: Partial
-  style?: Partial
+  script?: Partial>
+  template?: Partial<
+    Pick<
+      SFCTemplateCompileOptions,
+      | 'compiler'
+      | 'compilerOptions'
+      | 'preprocessOptions'
+      | 'preprocessCustomRequire'
+      | 'transformAssetUrls'
+    >
+  >
+  style?: Partial>
 
   /**
    * Transform Vue SFCs into custom elements.
@@ -124,7 +133,9 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
           __VUE_PROD_DEVTOOLS__: config.define?.__VUE_PROD_DEVTOOLS__ ?? false
         },
         ssr: {
-          external: ['vue', '@vue/server-renderer']
+          external: config.legacy?.buildSsrCjsExternalHeuristics
+            ? ['vue', '@vue/server-renderer']
+            : []
         }
       }
     },
diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md
index acc3b4194113ce..36c428084e362a 100644
--- a/packages/vite/CHANGELOG.md
+++ b/packages/vite/CHANGELOG.md
@@ -1,3 +1,111 @@
+## 3.0.6 (2022-08-11)
+
+* chore: narrow down rollup version (#9637) ([fcf4d98](https://github.com/vitejs/vite/commit/fcf4d98)), closes [#9637](https://github.com/vitejs/vite/issues/9637)
+* feat: show warning on 431 response (#9324) ([e8b61bb](https://github.com/vitejs/vite/commit/e8b61bb)), closes [#9324](https://github.com/vitejs/vite/issues/9324)
+* fix: avoid using `import.meta.url` for relative assets if output is not ESM (fixes #9297) (#9381) ([6d95225](https://github.com/vitejs/vite/commit/6d95225)), closes [#9297](https://github.com/vitejs/vite/issues/9297) [#9381](https://github.com/vitejs/vite/issues/9381)
+* fix: json HMR (fixes #9521) (#9610) ([e45d95f](https://github.com/vitejs/vite/commit/e45d95f)), closes [#9521](https://github.com/vitejs/vite/issues/9521) [#9610](https://github.com/vitejs/vite/issues/9610)
+* fix: legacy no emit worker (#9500) ([9d0b18b](https://github.com/vitejs/vite/commit/9d0b18b)), closes [#9500](https://github.com/vitejs/vite/issues/9500)
+* fix: use browser field if it is not likely UMD or CJS (fixes #9445) (#9459) ([c868e64](https://github.com/vitejs/vite/commit/c868e64)), closes [#9445](https://github.com/vitejs/vite/issues/9445) [#9459](https://github.com/vitejs/vite/issues/9459)
+* fix(optimizer): ignore EACCES errors while scanner (fixes #8916) (#9509) ([4e6a77f](https://github.com/vitejs/vite/commit/4e6a77f)), closes [#8916](https://github.com/vitejs/vite/issues/8916) [#9509](https://github.com/vitejs/vite/issues/9509)
+* fix(ssr): rename objectPattern dynamic key (fixes #9585) (#9609) ([ee7f78f](https://github.com/vitejs/vite/commit/ee7f78f)), closes [#9585](https://github.com/vitejs/vite/issues/9585) [#9609](https://github.com/vitejs/vite/issues/9609)
+
+
+
+## 3.0.5 (2022-08-09)
+
+* fix: allow tree-shake glob eager css in js (#9547) ([2e309d6](https://github.com/vitejs/vite/commit/2e309d6)), closes [#9547](https://github.com/vitejs/vite/issues/9547)
+* fix: ignore tsconfig target when bundling config (#9457) ([c5e7895](https://github.com/vitejs/vite/commit/c5e7895)), closes [#9457](https://github.com/vitejs/vite/issues/9457)
+* fix: log worker plugins in debug mode (#9553) ([c1fa219](https://github.com/vitejs/vite/commit/c1fa219)), closes [#9553](https://github.com/vitejs/vite/issues/9553)
+* fix: tree-shake modulepreload polyfill (#9531) ([1f11a70](https://github.com/vitejs/vite/commit/1f11a70)), closes [#9531](https://github.com/vitejs/vite/issues/9531)
+* fix: update dep types (fixes #9475) (#9489) ([937cecc](https://github.com/vitejs/vite/commit/937cecc)), closes [#9475](https://github.com/vitejs/vite/issues/9475) [#9489](https://github.com/vitejs/vite/issues/9489)
+* fix(build): normalized output log (#9594) ([8bae103](https://github.com/vitejs/vite/commit/8bae103)), closes [#9594](https://github.com/vitejs/vite/issues/9594)
+* fix(config): try catch unlink after load (#9577) ([d35a1e2](https://github.com/vitejs/vite/commit/d35a1e2)), closes [#9577](https://github.com/vitejs/vite/issues/9577)
+* fix(config): use file url for import path (fixes #9471) (#9473) ([22084a6](https://github.com/vitejs/vite/commit/22084a6)), closes [#9471](https://github.com/vitejs/vite/issues/9471) [#9473](https://github.com/vitejs/vite/issues/9473)
+* fix(deps): update all non-major dependencies (#9575) ([8071325](https://github.com/vitejs/vite/commit/8071325)), closes [#9575](https://github.com/vitejs/vite/issues/9575)
+* fix(ssr): check root import extension for external (#9494) ([ff89df5](https://github.com/vitejs/vite/commit/ff89df5)), closes [#9494](https://github.com/vitejs/vite/issues/9494)
+* fix(ssr): use appendRight for import (#9554) ([dfec6ca](https://github.com/vitejs/vite/commit/dfec6ca)), closes [#9554](https://github.com/vitejs/vite/issues/9554)
+* refactor(resolve): remove commonjs plugin handling (#9460) ([2042b91](https://github.com/vitejs/vite/commit/2042b91)), closes [#9460](https://github.com/vitejs/vite/issues/9460)
+* chore: init imports var before use (#9569) ([905b8eb](https://github.com/vitejs/vite/commit/905b8eb)), closes [#9569](https://github.com/vitejs/vite/issues/9569)
+* chore: node prefix lint (#9514) ([9e9cd23](https://github.com/vitejs/vite/commit/9e9cd23)), closes [#9514](https://github.com/vitejs/vite/issues/9514)
+* chore: tidy up eslint config (#9468) ([f4addcf](https://github.com/vitejs/vite/commit/f4addcf)), closes [#9468](https://github.com/vitejs/vite/issues/9468)
+* chore(deps): update all non-major dependencies (#9478) ([c530d16](https://github.com/vitejs/vite/commit/c530d16)), closes [#9478](https://github.com/vitejs/vite/issues/9478)
+* docs: fix incomplete comment (#9466) ([5169c51](https://github.com/vitejs/vite/commit/5169c51)), closes [#9466](https://github.com/vitejs/vite/issues/9466)
+* feat(ssr): debug failed node resolve (#9432) ([364aae1](https://github.com/vitejs/vite/commit/364aae1)), closes [#9432](https://github.com/vitejs/vite/issues/9432)
+
+
+
+## 3.0.4 (2022-07-29)
+
+* fix: __VITE_PUBLIC_ASSET__hash__ in HTML (#9247) ([a2b24ee](https://github.com/vitejs/vite/commit/a2b24ee)), closes [#9247](https://github.com/vitejs/vite/issues/9247)
+* fix: inline dynamic imports for ssr-webworker (fixes #9385) (#9401) ([cd69358](https://github.com/vitejs/vite/commit/cd69358)), closes [#9385](https://github.com/vitejs/vite/issues/9385) [#9401](https://github.com/vitejs/vite/issues/9401)
+* fix: normalise css paths in manifest on windows (fixes #9295) (#9353) ([13e6450](https://github.com/vitejs/vite/commit/13e6450)), closes [#9295](https://github.com/vitejs/vite/issues/9295) [#9353](https://github.com/vitejs/vite/issues/9353)
+* fix: support stylesheets with link tag and media/disable prop (#6751) ([e6c8965](https://github.com/vitejs/vite/commit/e6c8965)), closes [#6751](https://github.com/vitejs/vite/issues/6751)
+* fix: url constructor import asset no as url (#9399) ([122c6e7](https://github.com/vitejs/vite/commit/122c6e7)), closes [#9399](https://github.com/vitejs/vite/issues/9399)
+* fix(glob): server perf when globbing huge dirs (#9425) ([156a3a4](https://github.com/vitejs/vite/commit/156a3a4)), closes [#9425](https://github.com/vitejs/vite/issues/9425)
+* fix(glob): support static template literals (#9352) ([183c6fb](https://github.com/vitejs/vite/commit/183c6fb)), closes [#9352](https://github.com/vitejs/vite/issues/9352)
+* fix(ssr): allow virtual paths on node modules (#9405) ([e60368f](https://github.com/vitejs/vite/commit/e60368f)), closes [#9405](https://github.com/vitejs/vite/issues/9405)
+* chore(deps): update all non-major dependencies (#9347) ([2fcb027](https://github.com/vitejs/vite/commit/2fcb027)), closes [#9347](https://github.com/vitejs/vite/issues/9347)
+
+
+
+## 3.0.3 (2022-07-25)
+
+* fix: client type error (#9289) ([b82ddfb](https://github.com/vitejs/vite/commit/b82ddfb)), closes [#9289](https://github.com/vitejs/vite/issues/9289)
+* fix: don't modify config (#9262) ([bbc8318](https://github.com/vitejs/vite/commit/bbc8318)), closes [#9262](https://github.com/vitejs/vite/issues/9262)
+* fix: entries in ssr.external (#9286) ([d420f01](https://github.com/vitejs/vite/commit/d420f01)), closes [#9286](https://github.com/vitejs/vite/issues/9286)
+* fix: externalize explicitly configured linked packages (#9346) ([c33e365](https://github.com/vitejs/vite/commit/c33e365)), closes [#9346](https://github.com/vitejs/vite/issues/9346)
+* fix: make `resolveConfig()` concurrent safe (#9224) ([dfaeb2b](https://github.com/vitejs/vite/commit/dfaeb2b)), closes [#9224](https://github.com/vitejs/vite/issues/9224)
+* fix: scanner and optimizer should skip wasm (#9257) ([c616077](https://github.com/vitejs/vite/commit/c616077)), closes [#9257](https://github.com/vitejs/vite/issues/9257)
+* fix: ssrLoadModule executes code in non-strict mode, fixes #9197 (#9199) ([5866cfb](https://github.com/vitejs/vite/commit/5866cfb)), closes [#9197](https://github.com/vitejs/vite/issues/9197) [#9199](https://github.com/vitejs/vite/issues/9199)
+* fix: support multiline dynamic imports (#9314) ([e66cf69](https://github.com/vitejs/vite/commit/e66cf69)), closes [#9314](https://github.com/vitejs/vite/issues/9314)
+* fix: support vite client in safari 13 (#9315) ([2415193](https://github.com/vitejs/vite/commit/2415193)), closes [#9315](https://github.com/vitejs/vite/issues/9315)
+* fix: worker relative base should use import.meta.url (#9204) ([0358b04](https://github.com/vitejs/vite/commit/0358b04)), closes [#9204](https://github.com/vitejs/vite/issues/9204)
+* fix(glob): handle glob prop access (#9281) ([0580215](https://github.com/vitejs/vite/commit/0580215)), closes [#9281](https://github.com/vitejs/vite/issues/9281)
+* fix(scan): handle .ts import as .js alias (#9282) ([0b083ca](https://github.com/vitejs/vite/commit/0b083ca)), closes [#9282](https://github.com/vitejs/vite/issues/9282)
+* fix(ssr): no external symlink package (#9296) ([ea27701](https://github.com/vitejs/vite/commit/ea27701)), closes [#9296](https://github.com/vitejs/vite/issues/9296)
+* chore: adjust comments/typos (#9325) ([ffb2ba3](https://github.com/vitejs/vite/commit/ffb2ba3)), closes [#9325](https://github.com/vitejs/vite/issues/9325)
+* chore: fix code typos (#9033) ([ed02861](https://github.com/vitejs/vite/commit/ed02861)), closes [#9033](https://github.com/vitejs/vite/issues/9033)
+* docs: fix `@rollup/plugin-commonjs` name (#9313) ([c417364](https://github.com/vitejs/vite/commit/c417364)), closes [#9313](https://github.com/vitejs/vite/issues/9313)
+* docs: fix server options link (#9242) ([29db3ea](https://github.com/vitejs/vite/commit/29db3ea)), closes [#9242](https://github.com/vitejs/vite/issues/9242)
+* docs: update browser baseline features (#9316) ([b82ee5d](https://github.com/vitejs/vite/commit/b82ee5d)), closes [#9316](https://github.com/vitejs/vite/issues/9316)
+* feat: supports cts and mts files (#9268) ([0602017](https://github.com/vitejs/vite/commit/0602017)), closes [#9268](https://github.com/vitejs/vite/issues/9268)
+* feat: worker config call config hook (#9212) ([3e510ab](https://github.com/vitejs/vite/commit/3e510ab)), closes [#9212](https://github.com/vitejs/vite/issues/9212)
+* feat(css): use esbuild.log* options when minifying (#9210) ([88baa53](https://github.com/vitejs/vite/commit/88baa53)), closes [#9210](https://github.com/vitejs/vite/issues/9210)
+
+
+
+## 3.0.2 (2022-07-18)
+
+* fix: fs serve only edit pathname (fixes #9148) (#9173) ([28cffc9](https://github.com/vitejs/vite/commit/28cffc9)), closes [#9148](https://github.com/vitejs/vite/issues/9148) [#9173](https://github.com/vitejs/vite/issues/9173)
+* fix: prevent null pathname error (#9188) ([d66ffd0](https://github.com/vitejs/vite/commit/d66ffd0)), closes [#9188](https://github.com/vitejs/vite/issues/9188)
+* fix: return 500 on proxy error only if possible (fixes #9172) (#9193) ([b2f6bdc](https://github.com/vitejs/vite/commit/b2f6bdc)), closes [#9172](https://github.com/vitejs/vite/issues/9172) [#9193](https://github.com/vitejs/vite/issues/9193)
+* fix(deps): update all non-major dependencies (#9176) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70)), closes [#9176](https://github.com/vitejs/vite/issues/9176)
+* fix(dev): build.ssr is set during dev, fix #9134 (#9187) ([99b0e67](https://github.com/vitejs/vite/commit/99b0e67)), closes [#9134](https://github.com/vitejs/vite/issues/9134) [#9187](https://github.com/vitejs/vite/issues/9187)
+* fix(ssr): strip NULL_BYTE_PLACEHOLDER before import (#9124) ([c5f2dc7](https://github.com/vitejs/vite/commit/c5f2dc7)), closes [#9124](https://github.com/vitejs/vite/issues/9124)
+
+
+
+## 3.0.1 (2022-07-18)
+
+* fix: avoid errors when loading the overlay code in workers (#9064) ([a52b45e](https://github.com/vitejs/vite/commit/a52b45e)), closes [#9064](https://github.com/vitejs/vite/issues/9064)
+* fix: check server after tsconfig reload (#9106) ([d12d469](https://github.com/vitejs/vite/commit/d12d469)), closes [#9106](https://github.com/vitejs/vite/issues/9106)
+* fix: disable keepNames in `vite:esbuild` (fixes #9164) (#9166) ([e6f3b02](https://github.com/vitejs/vite/commit/e6f3b02)), closes [#9164](https://github.com/vitejs/vite/issues/9164) [#9166](https://github.com/vitejs/vite/issues/9166)
+* fix: externalize workspace relative import when bundle config (#9140) ([5a8a3ab](https://github.com/vitejs/vite/commit/5a8a3ab)), closes [#9140](https://github.com/vitejs/vite/issues/9140)
+* fix: mention that Node.js 13/15 support is dropped (fixes #9113) (#9116) ([2826303](https://github.com/vitejs/vite/commit/2826303)), closes [#9113](https://github.com/vitejs/vite/issues/9113) [#9116](https://github.com/vitejs/vite/issues/9116)
+* fix: resolve drive relative path (#9097) ([b393451](https://github.com/vitejs/vite/commit/b393451)), closes [#9097](https://github.com/vitejs/vite/issues/9097)
+* fix: respect .mjs .cjs extension in all modes (#9141) ([5ea70b3](https://github.com/vitejs/vite/commit/5ea70b3)), closes [#9141](https://github.com/vitejs/vite/issues/9141)
+* fix: return 500 on proxy error only if possible (fixes #9172) (#9175) ([d2f02a8](https://github.com/vitejs/vite/commit/d2f02a8)), closes [#9172](https://github.com/vitejs/vite/issues/9172) [#9175](https://github.com/vitejs/vite/issues/9175)
+* fix: server.proxy ws error causes crash (#9123) ([c2426d1](https://github.com/vitejs/vite/commit/c2426d1)), closes [#9123](https://github.com/vitejs/vite/issues/9123)
+* fix: ssr.external/noExternal should apply to packageName (#9146) ([5844d8e](https://github.com/vitejs/vite/commit/5844d8e)), closes [#9146](https://github.com/vitejs/vite/issues/9146)
+* fix: use correct require extension to load config (#9118) ([ebf682e](https://github.com/vitejs/vite/commit/ebf682e)), closes [#9118](https://github.com/vitejs/vite/issues/9118)
+* fix(esbuild): always support dynamic import and import meta (#9105) ([57a7936](https://github.com/vitejs/vite/commit/57a7936)), closes [#9105](https://github.com/vitejs/vite/issues/9105)
+* feat: allow declaring dirname (#9154) ([1e078ad](https://github.com/vitejs/vite/commit/1e078ad)), closes [#9154](https://github.com/vitejs/vite/issues/9154)
+* refactor: always load config with esbuild bundled code (#9121) ([a2b3131](https://github.com/vitejs/vite/commit/a2b3131)), closes [#9121](https://github.com/vitejs/vite/issues/9121)
+* docs: update default for optimizeDeps.disabled (#9078) ([4fbf9a8](https://github.com/vitejs/vite/commit/4fbf9a8)), closes [#9078](https://github.com/vitejs/vite/issues/9078)
+* chore: 3.0 release notes and bump peer deps (#9072) ([427ba26](https://github.com/vitejs/vite/commit/427ba26)), closes [#9072](https://github.com/vitejs/vite/issues/9072)
+
+
+
 ## 3.0.0 (2022-07-13)
 
 ### Main Changes
@@ -23,7 +131,7 @@
 - Experimental Features
   - [Build Advanced Base Options](https://vitejs.dev/guide/build.html#advanced-base-options)
   - [HMR Partial Accept](https://github.com/vitejs/vite/pull/7324)
-  - Vite now allows the use of [esbuild to optimize dependencies during build time](https://vitejs.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time) avoiding the need of [`@rollupjs/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs), removing one of the difference id dependency handling between dev and prod.
+  - Vite now allows the use of [esbuild to optimize dependencies during build time](https://vitejs.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time) avoiding the need of [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs), removing one of the difference id dependency handling between dev and prod.
 - Bundle size reduction
   - Terser is now an optional dependency. If you use `build.minify: 'terser'`, you'll need to install it (`npm add -D terser`)
   - node-forge moved out of the monorepo to [@vitejs/plugin-basic-ssl](https://vitejs.dev/guide/migration.html#automatic-https-certificate-generation)
diff --git a/packages/vite/bin/vite.js b/packages/vite/bin/vite.js
index 5814f260dc427c..13e9529510e4a3 100755
--- a/packages/vite/bin/vite.js
+++ b/packages/vite/bin/vite.js
@@ -50,7 +50,7 @@ if (profileIndex > 0) {
   if (next && !next.startsWith('-')) {
     process.argv.splice(profileIndex, 1)
   }
-  const inspector = await import('inspector').then((r) => r.default)
+  const inspector = await import('node:inspector').then((r) => r.default)
   const session = (global.__vite_profile_session = new inspector.Session())
   session.connect()
   session.post('Profiler.enable', () => {
diff --git a/packages/vite/package.json b/packages/vite/package.json
index b503fc06db2910..999483420115b9 100644
--- a/packages/vite/package.json
+++ b/packages/vite/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vite",
-  "version": "3.0.0",
+  "version": "3.0.6",
   "type": "module",
   "license": "MIT",
   "author": "Evan You",
@@ -32,7 +32,7 @@
     "types"
   ],
   "engines": {
-    "node": ">=14.18.0"
+    "node": "^14.18.0 || >=16.0.0"
   },
   "repository": {
     "type": "git",
@@ -59,27 +59,27 @@
   "//": "READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!",
   "dependencies": {
     "esbuild": "^0.14.47",
-    "postcss": "^8.4.14",
+    "postcss": "^8.4.16",
     "resolve": "^1.22.1",
-    "rollup": "^2.75.6"
+    "rollup": ">=2.75.6 <2.77.0 || ~2.77.0"
   },
   "optionalDependencies": {
     "fsevents": "~2.3.2"
   },
   "devDependencies": {
     "@ampproject/remapping": "^2.2.0",
-    "@babel/parser": "^7.18.8",
-    "@babel/types": "^7.18.8",
+    "@babel/parser": "^7.18.11",
+    "@babel/types": "^7.18.10",
     "@jridgewell/trace-mapping": "^0.3.14",
     "@rollup/plugin-alias": "^3.1.9",
-    "@rollup/plugin-commonjs": "^22.0.1",
-    "@rollup/plugin-dynamic-import-vars": "^1.4.3",
+    "@rollup/plugin-commonjs": "^22.0.2",
+    "@rollup/plugin-dynamic-import-vars": "^1.4.4",
     "@rollup/plugin-json": "^4.1.0",
     "@rollup/plugin-node-resolve": "13.3.0",
-    "@rollup/plugin-typescript": "^8.3.3",
+    "@rollup/plugin-typescript": "^8.3.4",
     "@rollup/pluginutils": "^4.2.1",
     "@vue/compiler-dom": "^3.2.37",
-    "acorn": "^8.7.1",
+    "acorn": "^8.8.0",
     "cac": "^6.7.12",
     "chokidar": "^3.5.3",
     "connect": "^3.7.0",
@@ -96,10 +96,10 @@
     "fast-glob": "^3.2.11",
     "http-proxy": "^1.18.1",
     "json5": "^2.2.1",
-    "launch-editor-middleware": "^2.4.0",
+    "launch-editor-middleware": "^2.5.0",
     "magic-string": "^0.26.2",
     "micromatch": "^4.0.5",
-    "mlly": "^0.5.4",
+    "mlly": "^0.5.7",
     "mrmime": "^1.0.1",
     "okie": "^1.0.1",
     "open": "^8.4.0",
@@ -119,7 +119,7 @@
     "tslib": "^2.4.0",
     "types": "link:./types",
     "ufo": "^0.8.5",
-    "ws": "^8.8.0"
+    "ws": "^8.8.1"
   },
   "peerDependencies": {
     "less": "*",
diff --git a/packages/vite/rollup.config.ts b/packages/vite/rollup.config.ts
index a630c2a813198c..a271d4f3562906 100644
--- a/packages/vite/rollup.config.ts
+++ b/packages/vite/rollup.config.ts
@@ -11,7 +11,7 @@ import MagicString from 'magic-string'
 import colors from 'picocolors'
 import fg from 'fast-glob'
 import { sync as resolve } from 'resolve'
-import type { Plugin } from 'rollup'
+import type { Plugin, RollupOptions } from 'rollup'
 import { defineConfig } from 'rollup'
 import pkg from './package.json'
 
@@ -185,7 +185,7 @@ function createCjsConfig(isProduction: boolean) {
   })
 }
 
-export default (commandLineArgs: any) => {
+export default (commandLineArgs: any): RollupOptions[] => {
   const isDev = commandLineArgs.watch
   const isProduction = !isDev
 
diff --git a/packages/vite/src/client/overlay.ts b/packages/vite/src/client/overlay.ts
index 150c570fbc8aaf..f9a22b7db2c6b3 100644
--- a/packages/vite/src/client/overlay.ts
+++ b/packages/vite/src/client/overlay.ts
@@ -115,6 +115,9 @@ code {
 const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g
 const codeframeRE = /^(?:>?\s+\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm
 
+// Allow `ErrorOverlay` to extend `HTMLElement` even in environments where
+// `HTMLElement` was not originally defined.
+const { HTMLElement = class {} as typeof globalThis.HTMLElement } = globalThis
 export class ErrorOverlay extends HTMLElement {
   root: ShadowRoot
 
@@ -184,6 +187,7 @@ export class ErrorOverlay extends HTMLElement {
 }
 
 export const overlayId = 'vite-error-overlay'
+const { customElements } = globalThis // Ensure `customElements` is defined before the next line.
 if (customElements && !customElements.get(overlayId)) {
   customElements.define(overlayId, ErrorOverlay)
 }
diff --git a/packages/vite/src/client/tsconfig.json b/packages/vite/src/client/tsconfig.json
index b662c5cef0d6d7..10e3e3fee1d5d7 100644
--- a/packages/vite/src/client/tsconfig.json
+++ b/packages/vite/src/client/tsconfig.json
@@ -3,6 +3,7 @@
   "include": ["./", "../../types"],
   "compilerOptions": {
     "types": [],
+    "target": "ES2019",
     "lib": ["ESNext", "DOM"],
     "declaration": false
   }
diff --git a/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts b/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts
index 5f063301799cff..d1c98348c5c453 100644
--- a/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts
+++ b/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts
@@ -21,7 +21,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       format: 'esm',
       keepNames: true,
       minify: true,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -62,7 +66,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       minifyIdentifiers: false,
       minifySyntax: true,
       minifyWhitespace: true,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -87,7 +95,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       minifyIdentifiers: false,
       minifySyntax: false,
       minifyWhitespace: false,
-      treeShaking: false
+      treeShaking: false,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -114,7 +126,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       minifyIdentifiers: true,
       minifySyntax: true,
       minifyWhitespace: false,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -138,7 +154,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       format: 'cjs',
       keepNames: true,
       minify: true,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -167,7 +187,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       minifyIdentifiers: true,
       minifySyntax: true,
       minifyWhitespace: false,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 
@@ -197,7 +221,11 @@ describe('resolveEsbuildTranspileOptions', () => {
       minifyIdentifiers: true,
       minifySyntax: false,
       minifyWhitespace: true,
-      treeShaking: true
+      treeShaking: true,
+      supported: {
+        'dynamic-import': true,
+        'import-meta': true
+      }
     })
   })
 })
diff --git a/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap b/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
index 3efbb7a0306f86..6eeb763c4117bd 100644
--- a/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
+++ b/packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.test.ts.snap
@@ -2,43 +2,43 @@
 
 exports[`fixture > transform 1`] = `
 "import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"../../../../../../types/importMeta\\";
-export const basic = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
-export const basicEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
-export const ignore = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
-export const namedEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
-export const namedDefault = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
-export const eagerAs = Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
-export const rawImportModule = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
-export const excludeSelf = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
-export const customQueryString = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom\\")});
-export const customQueryObject = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true\\")});
-export const parent = Object.assign({});
-export const rootMixedRelative = Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])});
-export const cleverCwd1 = Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
-export const cleverCwd2 = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
+export const basic = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
+export const basicEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
+export const ignore = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
+export const namedEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
+export const namedDefault = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
+export const eagerAs = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
+export const rawImportModule = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
+export const excludeSelf = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
+export const customQueryString = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom\\")});
+export const customQueryObject = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true\\")});
+export const parent = /* #__PURE__ */ Object.assign({});
+export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])});
+export const cleverCwd1 = /* #__PURE__ */ Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
+export const cleverCwd2 = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
 "
 `;
 
 exports[`fixture > transform with restoreQueryExtension 1`] = `
 "import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"../../../../../../types/importMeta\\";
-export const basic = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
-export const basicEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
-export const ignore = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
-export const namedEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
-export const namedDefault = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
-export const eagerAs = Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
-export const rawImportModule = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
-export const excludeSelf = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
-export const customQueryString = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom&lang.ts\\")});
-export const customQueryObject = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true&lang.ts\\")});
-export const parent = Object.assign({});
-export const rootMixedRelative = Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])});
-export const cleverCwd1 = Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
-export const cleverCwd2 = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
+export const basic = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
+export const basicEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
+export const ignore = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
+export const namedEager = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
+export const namedDefault = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
+export const eagerAs = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
+export const rawImportModule = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
+export const excludeSelf = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
+export const customQueryString = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom&lang.ts\\")});
+export const customQueryObject = /* #__PURE__ */ Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true&lang.ts\\")});
+export const parent = /* #__PURE__ */ Object.assign({});
+export const rootMixedRelative = /* #__PURE__ */ Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])});
+export const cleverCwd1 = /* #__PURE__ */ Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
+export const cleverCwd2 = /* #__PURE__ */ Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
 "
 `;
 
 exports[`fixture > virtual modules 1`] = `
-"Object.assign({\\"/modules/a.ts\\": () => import(\\"/modules/a.ts\\"),\\"/modules/b.ts\\": () => import(\\"/modules/b.ts\\"),\\"/modules/index.ts\\": () => import(\\"/modules/index.ts\\")})
-Object.assign({\\"/../fixture-b/a.ts\\": () => import(\\"/../fixture-b/a.ts\\"),\\"/../fixture-b/b.ts\\": () => import(\\"/../fixture-b/b.ts\\"),\\"/../fixture-b/index.ts\\": () => import(\\"/../fixture-b/index.ts\\")})"
+"/* #__PURE__ */ Object.assign({\\"/modules/a.ts\\": () => import(\\"/modules/a.ts\\"),\\"/modules/b.ts\\": () => import(\\"/modules/b.ts\\"),\\"/modules/index.ts\\": () => import(\\"/modules/index.ts\\")})
+/* #__PURE__ */ Object.assign({\\"/../fixture-b/a.ts\\": () => import(\\"/../fixture-b/a.ts\\"),\\"/../fixture-b/b.ts\\": () => import(\\"/../fixture-b/b.ts\\"),\\"/../fixture-b/index.ts\\": () => import(\\"/../fixture-b/index.ts\\")})"
 `;
diff --git a/packages/vite/src/node/__tests__/plugins/importGlob/parse.test.ts b/packages/vite/src/node/__tests__/plugins/importGlob/parse.test.ts
index 7f9c181037b450..7fb6286339d262 100644
--- a/packages/vite/src/node/__tests__/plugins/importGlob/parse.test.ts
+++ b/packages/vite/src/node/__tests__/plugins/importGlob/parse.test.ts
@@ -272,10 +272,40 @@ describe('parse negatives', async () => {
     expect(
       await runError('import.meta.glob(`hi ${hey}`)')
     ).toMatchInlineSnapshot(
-      '[Error: Invalid glob import syntax: Could only use literals]'
+      '[Error: Invalid glob import syntax: Expected glob to be a string, but got dynamic template literal]'
     )
   })
 
+  it('template with unicode', async () => {
+    expect(await run('import.meta.glob(`/\u0068\u0065\u006c\u006c\u006f`)'))
+      .toMatchInlineSnapshot(`
+      [
+        {
+          "globs": [
+            "/hello",
+          ],
+          "options": {},
+          "start": 0,
+        },
+      ]
+    `)
+  })
+
+  it('template without expressions', async () => {
+    expect(await run('import.meta.glob(`/**/*.page.client.*([a-zA-Z0-9])`)'))
+      .toMatchInlineSnapshot(`
+      [
+        {
+          "globs": [
+            "/**/*.page.client.*([a-zA-Z0-9])",
+          ],
+          "options": {},
+          "start": 0,
+        },
+      ]
+    `)
+  })
+
   it('be string', async () => {
     expect(await runError('import.meta.glob(1)')).toMatchInlineSnapshot(
       '[Error: Invalid glob import syntax: Expected glob to be a string, but got "number"]'
diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts
index 973dcef199d8ee..fffeae697abc8b 100644
--- a/packages/vite/src/node/build.ts
+++ b/packages/vite/src/node/build.ts
@@ -3,6 +3,7 @@ import path from 'node:path'
 import colors from 'picocolors'
 import type {
   ExternalOption,
+  InternalModuleFormat,
   ModuleFormat,
   OutputOptions,
   Plugin,
@@ -444,11 +445,13 @@ async function doBuild(
         )
       }
 
-      const ssrWorkerBuild = ssr && config.ssr?.target !== 'webworker'
-      const cjsSsrBuild = ssr && config.ssr?.format === 'cjs'
+      const ssrNodeBuild = ssr && config.ssr.target === 'node'
+      const ssrWorkerBuild = ssr && config.ssr.target === 'webworker'
+      const cjsSsrBuild = ssr && config.ssr.format === 'cjs'
+
       const format = output.format || (cjsSsrBuild ? 'cjs' : 'es')
       const jsExt =
-        ssrWorkerBuild || libOptions
+        ssrNodeBuild || libOptions
           ? resolveOutputJsExtension(format, getPkgJson(config.root)?.type)
           : 'js'
       return {
@@ -466,10 +469,10 @@ async function doBuild(
           ? `[name].${jsExt}`
           : libOptions
           ? resolveLibFilename(libOptions, format, config.root, jsExt)
-          : path.posix.join(options.assetsDir, `[name].[hash].js`),
+          : path.posix.join(options.assetsDir, `[name].[hash].${jsExt}`),
         chunkFileNames: libOptions
           ? `[name].[hash].${jsExt}`
-          : path.posix.join(options.assetsDir, `[name].[hash].js`),
+          : path.posix.join(options.assetsDir, `[name].[hash].${jsExt}`),
         assetFileNames: libOptions
           ? `[name].[ext]`
           : path.posix.join(options.assetsDir, `[name].[hash].[ext]`),
@@ -824,6 +827,50 @@ function injectSsrFlag>(
   return { ...(options ?? {}), ssr: true } as T & { ssr: boolean }
 }
 
+/*
+  The following functions are copied from rollup
+  https://github.com/rollup/rollup/blob/c5269747cd3dd14c4b306e8cea36f248d9c1aa01/src/ast/nodes/MetaProperty.ts#L189-L232
+
+  https://github.com/rollup/rollup
+  The MIT License (MIT)
+  Copyright (c) 2017 [these people](https://github.com/rollup/rollup/graphs/contributors)
+  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+const getResolveUrl = (path: string, URL = 'URL') => `new ${URL}(${path}).href`
+
+const getRelativeUrlFromDocument = (relativePath: string, umd = false) =>
+  getResolveUrl(
+    `'${relativePath}', ${
+      umd ? `typeof document === 'undefined' ? location.href : ` : ''
+    }document.currentScript && document.currentScript.src || document.baseURI`
+  )
+
+const relativeUrlMechanisms: Record<
+  InternalModuleFormat,
+  (relativePath: string) => string
+> = {
+  amd: (relativePath) => {
+    if (relativePath[0] !== '.') relativePath = './' + relativePath
+    return getResolveUrl(`require.toUrl('${relativePath}'), document.baseURI`)
+  },
+  cjs: (relativePath) =>
+    `(typeof document === 'undefined' ? ${getResolveUrl(
+      `'file:' + __dirname + '/${relativePath}'`,
+      `(require('u' + 'rl').URL)`
+    )} : ${getRelativeUrlFromDocument(relativePath)})`,
+  es: (relativePath) => getResolveUrl(`'${relativePath}', import.meta.url`),
+  iife: (relativePath) => getRelativeUrlFromDocument(relativePath),
+  system: (relativePath) => getResolveUrl(`'${relativePath}', module.meta.url`),
+  umd: (relativePath) =>
+    `(typeof document === 'undefined' && typeof location === 'undefined' ? ${getResolveUrl(
+      `'file:' + __dirname + '/${relativePath}'`,
+      `(require('u' + 'rl').URL)`
+    )} : ${getRelativeUrlFromDocument(relativePath, true)})`
+}
+/* end of copy */
+
 export type RenderBuiltAssetUrl = (
   filename: string,
   type: {
@@ -840,10 +887,13 @@ export function toOutputFilePathInString(
   hostId: string,
   hostType: 'js' | 'css' | 'html',
   config: ResolvedConfig,
+  format: InternalModuleFormat,
   toRelative: (
     filename: string,
     hostType: string
-  ) => string | { runtime: string }
+  ) => string | { runtime: string } = getToImportMetaURLBasedRelativePath(
+    format
+  )
 ): string | { runtime: string } {
   const { renderBuiltUrl } = config.experimental
   let relative = config.base === '' || config.base === './'
@@ -871,6 +921,17 @@ export function toOutputFilePathInString(
   return config.base + filename
 }
 
+function getToImportMetaURLBasedRelativePath(
+  format: InternalModuleFormat
+): (filename: string, importer: string) => { runtime: string } {
+  const toRelativePath = relativeUrlMechanisms[format]
+  return (filename, importer) => ({
+    runtime: toRelativePath(
+      path.posix.relative(path.dirname(importer), filename)
+    )
+  })
+}
+
 export function toOutputFilePathWithoutRuntime(
   filename: string,
   type: 'asset' | 'public',
diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts
index 3ece9213dab76a..fa0a25e463b811 100644
--- a/packages/vite/src/node/config.ts
+++ b/packages/vite/src/node/config.ts
@@ -27,7 +27,6 @@ import {
   dynamicImport,
   isExternalUrl,
   isObject,
-  isTS,
   lookupFile,
   mergeAlias,
   mergeConfig,
@@ -258,14 +257,14 @@ export interface UserConfig {
 
 export interface ExperimentalOptions {
   /**
-   * Append fake `&lang.(ext)` when queries are specified, to preseve the file extension for following plugins to process.
+   * Append fake `&lang.(ext)` when queries are specified, to preserve the file extension for following plugins to process.
    *
    * @experimental
    * @default false
    */
   importGlobRestoreExtension?: boolean
   /**
-   * Allow finegrain contol over assets and public files paths
+   * Allow finegrain control over assets and public files paths
    *
    * @experimental
    */
@@ -396,6 +395,23 @@ export async function resolveConfig(
   mode = inlineConfig.mode || config.mode || mode
   configEnv.mode = mode
 
+  // Some plugins that aren't intended to work in the bundling of workers (doing post-processing at build time for example).
+  // And Plugins may also have cached that could be corrupted by being used in these extra rollup calls.
+  // So we need to separate the worker plugin from the plugin that vite needs to run.
+  const rawWorkerUserPlugins = (
+    (await asyncFlatten(config.worker?.plugins || [])) as Plugin[]
+  ).filter((p) => {
+    if (!p) {
+      return false
+    } else if (!p.apply) {
+      return true
+    } else if (typeof p.apply === 'function') {
+      return p.apply({ ...config, mode }, configEnv)
+    } else {
+      return p.apply === command
+    }
+  })
+
   // resolve plugins
   const rawUserPlugins = (
     (await asyncFlatten(config.plugins || [])) as Plugin[]
@@ -413,13 +429,6 @@ export async function resolveConfig(
   const [prePlugins, normalPlugins, postPlugins] =
     sortUserPlugins(rawUserPlugins)
 
-  // resolve worker
-  const resolvedWorkerOptions: ResolveWorkerOptions = {
-    format: config.worker?.format || 'iife',
-    plugins: [],
-    rollupOptions: config.worker?.rollupOptions || {}
-  }
-
   // run config hooks
   const userPlugins = [...prePlugins, ...normalPlugins, ...postPlugins]
   for (const p of userPlugins) {
@@ -578,8 +587,32 @@ export async function resolveConfig(
 
   const BASE_URL = resolvedBase
 
-  const resolved: ResolvedConfig = {
-    ...config,
+  // resolve worker
+  let workerConfig = mergeConfig({}, config)
+  const [workerPrePlugins, workerNormalPlugins, workerPostPlugins] =
+    sortUserPlugins(rawWorkerUserPlugins)
+
+  // run config hooks
+  const workerUserPlugins = [
+    ...workerPrePlugins,
+    ...workerNormalPlugins,
+    ...workerPostPlugins
+  ]
+  for (const p of workerUserPlugins) {
+    if (p.config) {
+      const res = await p.config(workerConfig, configEnv)
+      if (res) {
+        workerConfig = mergeConfig(workerConfig, res)
+      }
+    }
+  }
+  const resolvedWorkerOptions: ResolveWorkerOptions = {
+    format: workerConfig.worker?.format || 'iife',
+    plugins: [],
+    rollupOptions: workerConfig.worker?.rollupOptions || {}
+  }
+
+  const resolvedConfig: ResolvedConfig = {
     configFile: configFile ? normalizePath(configFile) : undefined,
     configFileDependencies: configFileDependencies.map((name) =>
       normalizePath(path.resolve(name))
@@ -629,6 +662,44 @@ export async function resolveConfig(
       ...config.experimental
     }
   }
+  const resolved: ResolvedConfig = {
+    ...config,
+    ...resolvedConfig
+  }
+
+  ;(resolved.plugins as Plugin[]) = await resolvePlugins(
+    resolved,
+    prePlugins,
+    normalPlugins,
+    postPlugins
+  )
+
+  const workerResolved: ResolvedConfig = {
+    ...workerConfig,
+    ...resolvedConfig,
+    isWorker: true,
+    mainConfig: resolved
+  }
+
+  resolvedConfig.worker.plugins = await resolvePlugins(
+    workerResolved,
+    workerPrePlugins,
+    workerNormalPlugins,
+    workerPostPlugins
+  )
+
+  // call configResolved hooks
+  await Promise.all(
+    userPlugins
+      .map((p) => p.configResolved?.(resolved))
+      .concat(
+        resolvedConfig.worker.plugins.map((p) =>
+          p.configResolved?.(workerResolved)
+        )
+      )
+  )
+
+  // validate config
 
   if (middlewareMode === 'ssr') {
     logger.warn(
@@ -660,40 +731,14 @@ export async function resolveConfig(
     )
   }
 
-  // Some plugins that aren't intended to work in the bundling of workers (doing post-processing at build time for example).
-  // And Plugins may also have cached that could be corrupted by being used in these extra rollup calls.
-  // So we need to separate the worker plugin from the plugin that vite needs to run.
-  const [workerPrePlugins, workerNormalPlugins, workerPostPlugins] =
-    sortUserPlugins(config.worker?.plugins as Plugin[])
-  const workerResolved: ResolvedConfig = {
-    ...resolved,
-    isWorker: true,
-    mainConfig: resolved
-  }
-  resolved.worker.plugins = await resolvePlugins(
-    workerResolved,
-    workerPrePlugins,
-    workerNormalPlugins,
-    workerPostPlugins
-  )
-  // call configResolved worker plugins hooks
-  await Promise.all(
-    resolved.worker.plugins.map((p) => p.configResolved?.(workerResolved))
-  )
-  ;(resolved.plugins as Plugin[]) = await resolvePlugins(
-    resolved,
-    prePlugins,
-    normalPlugins,
-    postPlugins
-  )
-
-  // call configResolved hooks
-  await Promise.all(userPlugins.map((p) => p.configResolved?.(resolved)))
-
   if (process.env.DEBUG) {
     debug(`using resolved config: %O`, {
       ...resolved,
-      plugins: resolved.plugins.map((p) => p.name)
+      plugins: resolved.plugins.map((p) => p.name),
+      worker: {
+        ...resolved.worker,
+        plugins: resolved.worker.plugins.map((p) => p.name)
+      }
     })
   }
 
@@ -816,7 +861,6 @@ export async function loadConfigFromFile(
   const getTime = () => `${(performance.now() - start).toFixed(2)}ms`
 
   let resolvedPath: string | undefined
-  let dependencies: string[] = []
 
   if (configFile) {
     // explicit config path is always resolved from cwd
@@ -852,42 +896,13 @@ export async function loadConfigFromFile(
   }
 
   try {
-    let userConfig: UserConfigExport | undefined
-
-    if (isESM) {
-      const fileUrl = pathToFileURL(resolvedPath)
-      const bundled = await bundleConfigFile(resolvedPath, true)
-      dependencies = bundled.dependencies
-
-      if (isTS(resolvedPath)) {
-        // before we can register loaders without requiring users to run node
-        // with --experimental-loader themselves, we have to do a hack here:
-        // bundle the config file w/ ts transforms first, write it to disk,
-        // load it with native Node ESM, then delete the file.
-        fs.writeFileSync(resolvedPath + '.mjs', bundled.code)
-        try {
-          userConfig = (await dynamicImport(`${fileUrl}.mjs?t=${Date.now()}`))
-            .default
-        } finally {
-          fs.unlinkSync(resolvedPath + '.mjs')
-        }
-        debug(`TS + native esm config loaded in ${getTime()}`, fileUrl)
-      } else {
-        // using Function to avoid this from being compiled away by TS/Rollup
-        // append a query so that we force reload fresh config in case of
-        // server restart
-        userConfig = (await dynamicImport(`${fileUrl}?t=${Date.now()}`)).default
-        debug(`native esm config loaded in ${getTime()}`, fileUrl)
-      }
-    }
-
-    if (!userConfig) {
-      // Bundle config file and transpile it to cjs using esbuild.
-      const bundled = await bundleConfigFile(resolvedPath)
-      dependencies = bundled.dependencies
-      userConfig = await loadConfigFromBundledFile(resolvedPath, bundled.code)
-      debug(`bundled config file loaded in ${getTime()}`)
-    }
+    const bundled = await bundleConfigFile(resolvedPath, isESM)
+    const userConfig = await loadConfigFromBundledFile(
+      resolvedPath,
+      bundled.code,
+      isESM
+    )
+    debug(`bundled config file loaded in ${getTime()}`)
 
     const config = await (typeof userConfig === 'function'
       ? userConfig(configEnv)
@@ -898,7 +913,7 @@ export async function loadConfigFromFile(
     return {
       path: normalizePath(resolvedPath),
       config,
-      dependencies
+      dependencies: bundled.dependencies
     }
   } catch (e) {
     createLogger(logLevel).error(
@@ -911,33 +926,65 @@ export async function loadConfigFromFile(
 
 async function bundleConfigFile(
   fileName: string,
-  isESM = false
+  isESM: boolean
 ): Promise<{ code: string; dependencies: string[] }> {
+  const dirnameVarName = '__vite_injected_original_dirname'
+  const filenameVarName = '__vite_injected_original_filename'
   const importMetaUrlVarName = '__vite_injected_original_import_meta_url'
   const result = await build({
     absWorkingDir: process.cwd(),
     entryPoints: [fileName],
     outfile: 'out.js',
     write: false,
+    target: ['node14.18', 'node16'],
     platform: 'node',
     bundle: true,
     format: isESM ? 'esm' : 'cjs',
     sourcemap: 'inline',
     metafile: true,
     define: {
+      __dirname: dirnameVarName,
+      __filename: filenameVarName,
       'import.meta.url': importMetaUrlVarName
     },
     plugins: [
       {
         name: 'externalize-deps',
         setup(build) {
-          build.onResolve({ filter: /.*/ }, (args) => {
-            const id = args.path
+          build.onResolve({ filter: /.*/ }, ({ path: id, importer }) => {
+            // externalize bare imports
             if (id[0] !== '.' && !path.isAbsolute(id)) {
               return {
                 external: true
               }
             }
+            // bundle the rest and make sure that the we can also access
+            // it's third-party dependencies. externalize if not.
+            // monorepo/
+            // ├─ package.json
+            // ├─ utils.js -----------> bundle (share same node_modules)
+            // ├─ vite-project/
+            // │  ├─ vite.config.js --> entry
+            // │  ├─ package.json
+            // ├─ foo-project/
+            // │  ├─ utils.js --------> external (has own node_modules)
+            // │  ├─ package.json
+            const idFsPath = path.resolve(path.dirname(importer), id)
+            const idPkgPath = lookupFile(idFsPath, [`package.json`], {
+              pathOnly: true
+            })
+            if (idPkgPath) {
+              const idPkgDir = path.dirname(idPkgPath)
+              // if this file needs to go up one or more directory to reach the vite config,
+              // that means it has it's own node_modules (e.g. foo-project)
+              if (path.relative(idPkgDir, fileName).startsWith('..')) {
+                return {
+                  // normalize actual import after bundled as a single vite config
+                  path: pathToFileURL(idFsPath).href,
+                  external: true
+                }
+              }
+            }
           })
         }
       },
@@ -947,14 +994,16 @@ async function bundleConfigFile(
           build.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => {
             const contents = await fs.promises.readFile(args.path, 'utf8')
             const injectValues =
-              `const __dirname = ${JSON.stringify(path.dirname(args.path))};` +
-              `const __filename = ${JSON.stringify(args.path)};` +
+              `const ${dirnameVarName} = ${JSON.stringify(
+                path.dirname(args.path)
+              )};` +
+              `const ${filenameVarName} = ${JSON.stringify(args.path)};` +
               `const ${importMetaUrlVarName} = ${JSON.stringify(
                 pathToFileURL(args.path).href
               )};`
 
             return {
-              loader: isTS(args.path) ? 'ts' : 'js',
+              loader: args.path.endsWith('ts') ? 'ts' : 'js',
               contents: injectValues + contents
             }
           })
@@ -976,22 +1025,46 @@ interface NodeModuleWithCompile extends NodeModule {
 const _require = createRequire(import.meta.url)
 async function loadConfigFromBundledFile(
   fileName: string,
-  bundledCode: string
-): Promise {
-  const realFileName = fs.realpathSync(fileName)
-  const defaultLoader = _require.extensions['.js']
-  _require.extensions['.js'] = (module: NodeModule, filename: string) => {
-    if (filename === realFileName) {
-      ;(module as NodeModuleWithCompile)._compile(bundledCode, filename)
-    } else {
-      defaultLoader(module, filename)
+  bundledCode: string,
+  isESM: boolean
+): Promise {
+  // for esm, before we can register loaders without requiring users to run node
+  // with --experimental-loader themselves, we have to do a hack here:
+  // write it to disk, load it with native Node ESM, then delete the file.
+  if (isESM) {
+    const fileBase = `${fileName}.timestamp-${Date.now()}`
+    const fileNameTmp = `${fileBase}.mjs`
+    const fileUrl = `${pathToFileURL(fileBase)}.mjs`
+    fs.writeFileSync(fileNameTmp, bundledCode)
+    try {
+      return (await dynamicImport(fileUrl)).default
+    } finally {
+      try {
+        fs.unlinkSync(fileNameTmp)
+      } catch {
+        // already removed if this function is called twice simultaneously
+      }
+    }
+  }
+  // for cjs, we can register a custom loader via `_require.extensions`
+  else {
+    const extension = path.extname(fileName)
+    const realFileName = fs.realpathSync(fileName)
+    const loaderExt = extension in _require.extensions ? extension : '.js'
+    const defaultLoader = _require.extensions[loaderExt]!
+    _require.extensions[loaderExt] = (module: NodeModule, filename: string) => {
+      if (filename === realFileName) {
+        ;(module as NodeModuleWithCompile)._compile(bundledCode, filename)
+      } else {
+        defaultLoader(module, filename)
+      }
     }
+    // clear cache in case of server restart
+    delete _require.cache[_require.resolve(fileName)]
+    const raw = _require(fileName)
+    _require.extensions[loaderExt] = defaultLoader
+    return raw.__esModule ? raw.default : raw
   }
-  // clear cache in case of server restart
-  delete _require.cache[_require.resolve(fileName)]
-  const raw = _require(fileName)
-  _require.extensions['.js'] = defaultLoader
-  return raw.__esModule ? raw.default : raw
 }
 
 export function getDepOptimizationConfig(
diff --git a/packages/vite/src/node/constants.ts b/packages/vite/src/node/constants.ts
index 5a108652ef7ce6..35bf9231909850 100644
--- a/packages/vite/src/node/constants.ts
+++ b/packages/vite/src/node/constants.ts
@@ -11,8 +11,9 @@ export const DEFAULT_MAIN_FIELDS = [
   'jsnext'
 ]
 
-// Support browserslist
-// "defaults and supports es6-module and supports es6-module-dynamic-import",
+// Baseline support browserslist
+// "defaults and supports es6-module and supports es6-module-dynamic-import"
+// Higher browser versions may be needed for extra features.
 export const ESBUILD_MODULES_TARGET = [
   'es2020', // support import.meta.url
   'edge88',
@@ -24,6 +25,7 @@ export const ESBUILD_MODULES_TARGET = [
 export const DEFAULT_EXTENSIONS = [
   '.mjs',
   '.js',
+  '.mts',
   '.ts',
   '.jsx',
   '.tsx',
@@ -41,7 +43,7 @@ export const DEFAULT_CONFIG_FILES = [
 
 export const JS_TYPES_RE = /\.(?:j|t)sx?$|\.mjs$/
 
-export const OPTIMIZABLE_ENTRY_RE = /\.(?:(m|c)?js|ts)$/
+export const OPTIMIZABLE_ENTRY_RE = /\.(?:[cm]?[jt]s)$/
 
 export const SPECIAL_QUERY_RE = /[\?&](?:worker|sharedworker|raw|url)\b/
 
diff --git a/packages/vite/src/node/http.ts b/packages/vite/src/node/http.ts
index 18ce37f6a327e1..3317814252018b 100644
--- a/packages/vite/src/node/http.ts
+++ b/packages/vite/src/node/http.ts
@@ -6,6 +6,7 @@ import type {
 } from 'node:http'
 import type { ServerOptions as HttpsServerOptions } from 'node:https'
 import type { Connect } from 'types/connect'
+import colors from 'picocolors'
 import { isObject } from './utils'
 import type { ProxyOptions } from './server/middlewares/proxy'
 import type { Logger } from './logger'
@@ -95,16 +96,16 @@ export async function resolveHttpServer(
   httpsOptions?: HttpsServerOptions
 ): Promise {
   if (!httpsOptions) {
-    const { createServer } = await import('http')
+    const { createServer } = await import('node:http')
     return createServer(app)
   }
 
   // #484 fallback to http1 when proxy is needed.
   if (proxy) {
-    const { createServer } = await import('https')
+    const { createServer } = await import('node:https')
     return createServer(httpsOptions, app)
   } else {
-    const { createSecureServer } = await import('http2')
+    const { createSecureServer } = await import('node:http2')
     return createSecureServer(
       {
         // Manually increase the session memory to prevent 502 ENHANCE_YOUR_CALM
@@ -183,3 +184,19 @@ export async function httpServerStart(
     })
   })
 }
+
+export function setClientErrorHandler(
+  server: HttpServer,
+  logger: Logger
+): void {
+  server.on('clientError', (err, socket) => {
+    if ((err as any).code === 'HPE_HEADER_OVERFLOW') {
+      logger.warn(
+        colors.yellow(
+          'Server responded with status code 431. ' +
+            'See https://vitejs.dev/guide/troubleshooting.html#_431-request-header-fields-too-large.'
+        )
+      )
+    }
+  })
+}
diff --git a/packages/vite/src/node/logger.ts b/packages/vite/src/node/logger.ts
index d0c5d29334c023..326fa0e6dfd778 100644
--- a/packages/vite/src/node/logger.ts
+++ b/packages/vite/src/node/logger.ts
@@ -1,6 +1,6 @@
 /* eslint no-console: 0 */
 
-import readline from 'readline'
+import readline from 'node:readline'
 import colors from 'picocolors'
 import type { RollupError } from 'rollup'
 import type { ResolvedServerUrls } from './server'
diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts
index 20b808b1dc7ec7..57e67c2b47a166 100644
--- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts
+++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts
@@ -29,6 +29,8 @@ const externalTypes = [
   'stylus',
   'pcss',
   'postcss',
+  // wasm
+  'wasm',
   // known SFC types
   'vue',
   'svelte',
diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts
index 4cbd13f8d965a7..b678d983353c8f 100644
--- a/packages/vite/src/node/optimizer/index.ts
+++ b/packages/vite/src/node/optimizer/index.ts
@@ -113,7 +113,7 @@ export interface DepOptimizationConfig {
    * List of file extensions that can be optimized. A corresponding esbuild
    * plugin must exist to handle the specific extension.
    *
-   * By default, Vite can optimize `.mjs`, `.js`, and `.ts` files. This option
+   * By default, Vite can optimize `.mjs`, `.js`, `.ts`, and `.mts` files. This option
    * allows specifying additional extensions.
    *
    * @experimental
@@ -122,8 +122,8 @@ export interface DepOptimizationConfig {
   /**
    * Disables dependencies optimizations, true disables the optimizer during
    * build and dev. Pass 'build' or 'dev' to only disable the optimizer in
-   * one of the modes. Deps optimization is enabled by default in both
-   * @default false
+   * one of the modes. Deps optimization is enabled by default in dev only.
+   * @default 'build'
    * @experimental
    */
   disabled?: boolean | 'build' | 'dev'
@@ -151,7 +151,7 @@ export type DepOptimizationOptions = DepOptimizationConfig & {
 export interface DepOptimizationResult {
   metadata: DepOptimizationMetadata
   /**
-   * When doing a re-run, if there are newly discovered dependendencies
+   * When doing a re-run, if there are newly discovered dependencies
    * the page reload will be delayed until the next rerun so we need
    * to be able to discard the result
    */
@@ -224,7 +224,7 @@ export async function optimizeDeps(
 ): Promise {
   const log = asCommand ? config.logger.info : debug
 
-  const ssr = !!config.build.ssr
+  const ssr = config.command === 'build' && !!config.build.ssr
 
   const cachedMetadata = loadCachedDepOptimizationMetadata(
     config,
@@ -446,7 +446,8 @@ export function depsLogString(qualifiedIds: string[]): string {
 export async function runOptimizeDeps(
   resolvedConfig: ResolvedConfig,
   depsInfo: Record,
-  ssr: boolean = !!resolvedConfig.build.ssr
+  ssr: boolean = resolvedConfig.command === 'build' &&
+    !!resolvedConfig.build.ssr
 ): Promise {
   const isBuild = resolvedConfig.command === 'build'
   const config: ResolvedConfig = {
@@ -748,7 +749,7 @@ export function depsFromOptimizedDepInfo(
 export function getOptimizedDepPath(
   id: string,
   config: ResolvedConfig,
-  ssr: boolean = !!config.build.ssr
+  ssr: boolean
 ): string {
   return normalizePath(
     path.resolve(getDepsCacheDir(config, ssr), flattenId(id) + '.js')
@@ -1008,7 +1009,7 @@ function needsInterop(
   }
 
   if (output) {
-    // if a peer dependency used require() on a ESM dependency, esbuild turns the
+    // if a peer dependency used require() on an ESM dependency, esbuild turns the
     // ESM dependency's entry chunk into a single default export... detect
     // such cases by checking exports mismatch, and force interop.
     const generatedExports: string[] = output.exports
diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts
index e11a713958a727..9bf03aa88005b0 100644
--- a/packages/vite/src/node/optimizer/optimizer.ts
+++ b/packages/vite/src/node/optimizer/optimizer.ts
@@ -55,7 +55,7 @@ export async function initDepsOptimizer(
   server?: ViteDevServer
 ): Promise {
   // Non Dev SSR Optimizer
-  const ssr = !!config.build.ssr
+  const ssr = config.command === 'build' && !!config.build.ssr
   if (!getDepsOptimizer(config, ssr)) {
     await createDepsOptimizer(config, server)
   }
@@ -95,7 +95,7 @@ async function createDepsOptimizer(
 ): Promise {
   const { logger } = config
   const isBuild = config.command === 'build'
-  const ssr = !!config.build.ssr // safe as Dev SSR don't use this optimizer
+  const ssr = isBuild && !!config.build.ssr // safe as Dev SSR don't use this optimizer
 
   const sessionTimestamp = Date.now().toString()
 
@@ -240,12 +240,12 @@ async function createDepsOptimizer(
     depOptimizationProcessingQueue.push(depOptimizationProcessing)
 
     // Create a new promise for the next rerun, discovered missing
-    // dependencies will be asigned this promise from this point
+    // dependencies will be assigned this promise from this point
     depOptimizationProcessing = newDepOptimizationProcessing()
   }
 
   async function optimizeNewDeps() {
-    // a succesful completion of the optimizeDeps rerun will end up
+    // a successful completion of the optimizeDeps rerun will end up
     // creating new bundled version of all current and discovered deps
     // in the cache dir and a new metadata info object assigned
     // to _metadata. A fullReload is only issued if the previous bundled
@@ -391,7 +391,7 @@ async function createDepsOptimizer(
       } else {
         if (newDepsDiscovered) {
           // There are newly discovered deps, and another rerun is about to be
-          // excecuted. Avoid the current full reload discarding this rerun result
+          // executed. Avoid the current full reload discarding this rerun result
           // We don't resolve the processing promise, as they will be resolved
           // once a rerun is committed
           processingResult.cancel()
@@ -528,7 +528,7 @@ async function createDepsOptimizer(
       src: resolved,
       // Assing a browserHash to this missing dependency that is unique to
       // the current state of known + missing deps. If its optimizeDeps run
-      // doesn't alter the bundled files of previous known dependendencies,
+      // doesn't alter the bundled files of previous known dependencies,
       // we don't need a full reload and this browserHash will be kept
       browserHash: getDiscoveredBrowserHash(
         metadata.hash,
diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts
index f1f698a15258a9..a3b799dc91542b 100644
--- a/packages/vite/src/node/optimizer/scan.ts
+++ b/packages/vite/src/node/optimizer/scan.ts
@@ -143,7 +143,8 @@ function globEntries(pattern: string | string[], config: ResolvedConfig) {
         ? []
         : [`**/__tests__/**`, `**/coverage/**`])
     ],
-    absolute: true
+    absolute: true,
+    suppressErrors: true // suppress EACCES errors
   })
 }
 
@@ -379,14 +380,18 @@ function esbuildScanPlugin(
           // avoid matching windows volume
           filter: /^[\w@][^:]/
         },
-        async ({ path: id, importer }) => {
+        async ({ path: id, importer, pluginData }) => {
           if (moduleListContains(exclude, id)) {
             return externalUnlessEntry({ path: id })
           }
           if (depImports[id]) {
             return externalUnlessEntry({ path: id })
           }
-          const resolved = await resolve(id, importer)
+          const resolved = await resolve(id, importer, {
+            custom: {
+              depScan: { loader: pluginData?.htmlType?.loader }
+            }
+          })
           if (resolved) {
             if (shouldExternalizeDep(resolved, id)) {
               return externalUnlessEntry({ path: id })
@@ -419,10 +424,10 @@ function esbuildScanPlugin(
       // they are done after the bare import resolve because a package name
       // may end with these extensions
 
-      // css & json
+      // css & json & wasm
       build.onResolve(
         {
-          filter: /\.(css|less|sass|scss|styl|stylus|pcss|postcss|json)$/
+          filter: /\.(css|less|sass|scss|styl|stylus|pcss|postcss|json|wasm)$/
         },
         externalUnlessEntry
       )
diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts
index 0403009d4b69c4..0db1301a876fdb 100644
--- a/packages/vite/src/node/plugins/asset.ts
+++ b/packages/vite/src/node/plugins/asset.ts
@@ -90,18 +90,10 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
       return `export default ${JSON.stringify(url)}`
     },
 
-    renderChunk(code, chunk) {
+    renderChunk(code, chunk, outputOptions) {
       let match: RegExpExecArray | null
       let s: MagicString | undefined
 
-      const toRelative = (filename: string, importer: string) => {
-        return {
-          runtime: `new URL(${JSON.stringify(
-            path.posix.relative(path.dirname(importer), filename)
-          )},import.meta.url).href`
-        }
-      }
-
       // Urls added with JS using e.g.
       // imgElement.src = "__VITE_ASSET__5aa0ddc0__" are using quotes
 
@@ -124,7 +116,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
           chunk.fileName,
           'js',
           config,
-          toRelative
+          outputOptions.format
         )
         const replacementString =
           typeof replacement === 'string'
@@ -148,7 +140,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
           chunk.fileName,
           'js',
           config,
-          toRelative
+          outputOptions.format
         )
         const replacementString =
           typeof replacement === 'string'
@@ -239,6 +231,13 @@ export function getAssetFilename(
   return assetHashToFilenameMap.get(config)?.get(hash)
 }
 
+export function getPublicAssetFilename(
+  hash: string,
+  config: ResolvedConfig
+): string | undefined {
+  return publicAssetUrlCache.get(config)?.get(hash)
+}
+
 export function resolveAssetFileNames(
   config: ResolvedConfig
 ): string | ((chunkInfo: PreRenderedAsset) => string) {
diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts
index 6d7a657706cf9c..4b52a225a68458 100644
--- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts
+++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts
@@ -55,7 +55,7 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
               s.overwrite(
                 index,
                 index + exp.length,
-                `new URL((import.meta.glob(${pattern}, { eager: true, import: 'default' }))[${rawUrl}], self.location)`,
+                `new URL((import.meta.glob(${pattern}, { eager: true, import: 'default', as: 'url' }))[${rawUrl}], self.location)`,
                 { contentOnly: true }
               )
               continue
diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts
index bfe60ed04dc529..b2df2df9f7f0a5 100644
--- a/packages/vite/src/node/plugins/css.ts
+++ b/packages/vite/src/node/plugins/css.ts
@@ -519,7 +519,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
       }
 
       function ensureFileExt(name: string, ext: string) {
-        return path.format({ ...path.parse(name), base: undefined, ext })
+        return normalizePath(
+          path.format({ ...path.parse(name), base: undefined, ext })
+        )
       }
 
       if (config.build.cssCodeSplit) {
@@ -1249,18 +1251,25 @@ async function minifyCSS(css: string, config: ResolvedConfig) {
 function resolveEsbuildMinifyOptions(
   options: ESBuildOptions
 ): TransformOptions {
+  const base: TransformOptions = {
+    logLevel: options.logLevel,
+    logLimit: options.logLimit,
+    logOverride: options.logOverride
+  }
+
   if (
     options.minifyIdentifiers != null ||
     options.minifySyntax != null ||
     options.minifyWhitespace != null
   ) {
     return {
+      ...base,
       minifyIdentifiers: options.minifyIdentifiers ?? true,
       minifySyntax: options.minifySyntax ?? true,
       minifyWhitespace: options.minifyWhitespace ?? true
     }
   } else {
-    return { minify: true }
+    return { ...base, minify: true }
   }
 }
 
diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts
index 97f605c1758d53..b7d5ed5a5f8792 100644
--- a/packages/vite/src/node/plugins/dynamicImportVars.ts
+++ b/packages/vite/src/node/plugins/dynamicImportVars.ts
@@ -10,6 +10,7 @@ import {
   createFilter,
   normalizePath,
   parseRequest,
+  removeComments,
   requestQuerySplitRE,
   transformStableResult
 } from '../utils'
@@ -176,11 +177,13 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin {
         s ||= new MagicString(source)
         let result
         try {
-          result = await transformDynamicImport(
-            source.slice(start, end),
-            importer,
-            resolve
-          )
+          // When import string is using backticks, es-module-lexer `end` captures
+          // until the closing parenthesis, instead of the closing backtick.
+          // There may be inline comments between the backtick and the closing
+          // parenthesis, so we manually remove them for now.
+          // See https://github.com/guybedford/es-module-lexer/issues/118
+          const importSource = removeComments(source.slice(start, end)).trim()
+          result = await transformDynamicImport(importSource, importer, resolve)
         } catch (error) {
           if (warnOnError) {
             this.warn(error)
diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts
index 42e5bbac76316a..d5d25b861584f6 100644
--- a/packages/vite/src/node/plugins/esbuild.ts
+++ b/packages/vite/src/node/plugins/esbuild.ts
@@ -78,6 +78,8 @@ export async function transformWithEsbuild(
 
     if (ext === 'cjs' || ext === 'mjs') {
       loader = 'js'
+    } else if (ext === 'cts' || ext === 'mts') {
+      loader = 'ts'
     } else {
       loader = ext as Loader
     }
@@ -85,7 +87,7 @@ export async function transformWithEsbuild(
 
   let tsconfigRaw = options?.tsconfigRaw
 
-  // if options provide tsconfigraw in string, it takes highest precedence
+  // if options provide tsconfigRaw in string, it takes highest precedence
   if (typeof tsconfigRaw !== 'string') {
     // these fields would affect the compilation result
     // https://esbuild.github.io/content-types/#tsconfig-json
@@ -170,7 +172,7 @@ export async function transformWithEsbuild(
 
 export function esbuildPlugin(options: ESBuildOptions = {}): Plugin {
   const filter = createFilter(
-    options.include || /\.(tsx?|jsx)$/,
+    options.include || /\.(m?ts|[jt]sx)$/,
     options.exclude || /\.js$/
   )
 
@@ -182,7 +184,11 @@ export function esbuildPlugin(options: ESBuildOptions = {}): Plugin {
     minifyIdentifiers: false,
     minifySyntax: false,
     minifyWhitespace: false,
-    treeShaking: false
+    treeShaking: false,
+    // keepNames is not needed when minify is disabled.
+    // Also transforming multiple times with keepNames enabled breaks
+    // tree-shaking. (#9164)
+    keepNames: false
   }
 
   return {
@@ -298,10 +304,19 @@ export function resolveEsbuildTranspileOptions(
   // pure annotations and break tree-shaking
   // https://github.com/vuejs/core/issues/2860#issuecomment-926882793
   const isEsLibBuild = config.build.lib && format === 'es'
+  const esbuildOptions = config.esbuild || {}
   const options: TransformOptions = {
-    ...config.esbuild,
+    ...esbuildOptions,
     target: target || undefined,
-    format: rollupToEsbuildFormatMap[format]
+    format: rollupToEsbuildFormatMap[format],
+    // the final build should always support dynamic import and import.meta.
+    // if they need to be polyfilled, plugin-legacy should be used.
+    // plugin-legacy detects these two features when checking for modern code.
+    supported: {
+      'dynamic-import': true,
+      'import-meta': true,
+      ...esbuildOptions.supported
+    }
   }
 
   // If no minify, disable all minify options
@@ -428,7 +443,7 @@ function reloadOnTsconfigChange(changedFile: string) {
       tsconfckParseOptions?.cache?.has(changedFile))
   ) {
     server.config.logger.info(
-      `changed tsconfig file detected: ${changedFile} - Clearing cache and forcing full-reload to ensure typescript is compiled with updated config values.`,
+      `changed tsconfig file detected: ${changedFile} - Clearing cache and forcing full-reload to ensure TypeScript is compiled with updated config values.`,
       { clear: server.config.clearScreen, timestamp: true }
     )
 
@@ -437,11 +452,14 @@ function reloadOnTsconfigChange(changedFile: string) {
 
     // reset tsconfck so that recompile works with up2date configs
     initTSConfck(server.config).finally(() => {
-      // force full reload
-      server.ws.send({
-        type: 'full-reload',
-        path: '*'
-      })
+      // server may not be available if vite config is updated at the same time
+      if (server) {
+        // force full reload
+        server.ws.send({
+          type: 'full-reload',
+          path: '*'
+        })
+      }
     })
   }
 }
diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts
index 5287e6e5208ab5..b8cd3713edfeea 100644
--- a/packages/vite/src/node/plugins/html.ts
+++ b/packages/vite/src/node/plugins/html.ts
@@ -34,6 +34,8 @@ import {
   assetUrlRE,
   checkPublicFile,
   getAssetFilename,
+  getPublicAssetFilename,
+  publicAssetUrlRE,
   urlToBuiltUrl
 } from './asset'
 import { isCSSRequest } from './css'
@@ -45,7 +47,7 @@ interface ScriptAssetsUrl {
   url: string
 }
 
-const htmlProxyRE = /\?html-proxy=?[&inline\-css]*&index=(\d+)\.(js|css)$/
+const htmlProxyRE = /\?html-proxy=?(?:&inline-css)?&index=(\d+)\.(js|css)$/
 const inlineCSSRE = /__VITE_INLINE_CSS__([a-z\d]{8}_\d+)__/g
 // Do not allow preceding '.', but do allow preceding '...' for spread operations
 const inlineImportRE =
@@ -354,7 +356,14 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
                 // assetsUrl may be encodeURI
                 const url = decodeURI(p.value.content)
                 if (!isExcludedUrl(url)) {
-                  if (node.tag === 'link' && isCSSRequest(url)) {
+                  if (
+                    node.tag === 'link' &&
+                    isCSSRequest(url) &&
+                    // should not be converted if following attributes are present (#6748)
+                    !node.props.some(
+                      (p) => p.name === 'media' || p.name === 'disabled'
+                    )
+                  ) {
                     // CSS references, convert to import
                     const importExpression = `\nimport ${JSON.stringify(url)}`
                     styleUrls.push({
@@ -606,13 +615,16 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
       for (const [id, html] of processedHtml) {
         const relativeUrlPath = path.posix.relative(config.root, id)
         const assetsBase = getBaseInHTML(relativeUrlPath, config)
-        const toOutputAssetFilePath = (filename: string) => {
+        const toOutputFilePath = (
+          filename: string,
+          type: 'asset' | 'public'
+        ) => {
           if (isExternalUrl(filename)) {
             return filename
           } else {
             return toOutputFilePathInHtml(
               filename,
-              'asset',
+              type,
               relativeUrlPath,
               'html',
               config,
@@ -621,6 +633,12 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
           }
         }
 
+        const toOutputAssetFilePath = (filename: string) =>
+          toOutputFilePath(filename, 'asset')
+
+        const toOutputPublicAssetFilePath = (filename: string) =>
+          toOutputFilePath(filename, 'public')
+
         const isAsync = isAsyncScriptMap.get(config)!.get(id)!
 
         let result = html
@@ -709,12 +727,20 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
           )
         })
 
+        result = result.replace(publicAssetUrlRE, (_, fileHash) => {
+          return normalizePath(
+            toOutputPublicAssetFilePath(
+              getPublicAssetFilename(fileHash, config)!
+            )
+          )
+        })
+
         if (chunk && canInlineEntry) {
           // all imports from entry have been inlined to html, prevent rollup from outputting it
           delete bundle[chunk.fileName]
         }
 
-        const shortEmitName = path.relative(config.root, id)
+        const shortEmitName = normalizePath(path.relative(config.root, id))
         this.emitFile({
           type: 'asset',
           fileName: shortEmitName,
diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts
index f04cb8625f864b..5041812a96f98e 100644
--- a/packages/vite/src/node/plugins/importAnalysis.ts
+++ b/packages/vite/src/node/plugins/importAnalysis.ts
@@ -69,7 +69,7 @@ const debug = createDebugger('vite:import-analysis')
 
 const clientDir = normalizePath(CLIENT_DIR)
 
-const skipRE = /\.(map|json)$/
+const skipRE = /\.(map|json)($|\?)/
 export const canSkipImportAnalysis = (id: string): boolean =>
   skipRE.test(id) || isDirectCSSRequest(id)
 
diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts
index f392cfda538584..dee652387bff3b 100644
--- a/packages/vite/src/node/plugins/importAnalysisBuild.ts
+++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts
@@ -380,7 +380,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
         // dynamic import to constant json may get inlined.
         if (chunk.type === 'chunk' && chunk.code.indexOf(preloadMarker) > -1) {
           const code = chunk.code
-          let imports: ImportSpecifier[]
+          let imports: ImportSpecifier[] = []
           try {
             imports = parseImports(code)[0].filter((i) => i.d > -1)
           } catch (e: any) {
diff --git a/packages/vite/src/node/plugins/importMetaGlob.ts b/packages/vite/src/node/plugins/importMetaGlob.ts
index 7f3695178fdce9..f5b81005e446fa 100644
--- a/packages/vite/src/node/plugins/importMetaGlob.ts
+++ b/packages/vite/src/node/plugins/importMetaGlob.ts
@@ -4,9 +4,13 @@ import { stripLiteral } from 'strip-literal'
 import type {
   ArrayExpression,
   CallExpression,
+  Expression,
   Literal,
+  MemberExpression,
   Node,
-  SequenceExpression
+  SequenceExpression,
+  SpreadElement,
+  TemplateLiteral
 } from 'estree'
 import { parseExpressionAt } from 'acorn'
 import MagicString from 'magic-string'
@@ -70,10 +74,6 @@ export function importGlobPlugin(config: ResolvedConfig): Plugin {
         if (server) {
           const allGlobs = result.matches.map((i) => i.globsResolved)
           server._importGlobMap.set(id, allGlobs)
-          result.files.forEach((file) => {
-            // update watcher
-            server!.watcher.add(dirname(file))
-          })
         }
         return transformStableResult(result.s, id, config)
       }
@@ -118,7 +118,7 @@ export async function parseImportGlob(
       return e
     }
 
-    let ast: CallExpression | SequenceExpression
+    let ast: CallExpression | SequenceExpression | MemberExpression
     let lastTokenPos: number | undefined
 
     try {
@@ -157,35 +157,47 @@ export async function parseImportGlob(
     if (ast.type === 'SequenceExpression')
       ast = ast.expressions[0] as CallExpression
 
+    // immediate property access, call expression is nested
+    // import.meta.glob(...)['prop']
+    if (ast.type === 'MemberExpression') ast = ast.object as CallExpression
+
     if (ast.type !== 'CallExpression')
       throw err(`Expect CallExpression, got ${ast.type}`)
 
     if (ast.arguments.length < 1 || ast.arguments.length > 2)
       throw err(`Expected 1-2 arguments, but got ${ast.arguments.length}`)
 
-    const arg1 = ast.arguments[0] as ArrayExpression | Literal
+    const arg1 = ast.arguments[0] as ArrayExpression | Literal | TemplateLiteral
     const arg2 = ast.arguments[1] as Node | undefined
 
     const globs: string[] = []
-    if (arg1.type === 'ArrayExpression') {
-      for (const element of arg1.elements) {
-        if (!element) continue
-        if (element.type !== 'Literal') throw err('Could only use literals')
+
+    const validateLiteral = (element: Expression | SpreadElement | null) => {
+      if (!element) return
+      if (element.type === 'Literal') {
         if (typeof element.value !== 'string')
           throw err(
             `Expected glob to be a string, but got "${typeof element.value}"`
           )
-
         globs.push(element.value)
+      } else if (element.type === 'TemplateLiteral') {
+        if (element.expressions.length !== 0) {
+          throw err(
+            `Expected glob to be a string, but got dynamic template literal`
+          )
+        }
+        globs.push(element.quasis[0].value.raw)
+      } else {
+        throw err('Could only use literals')
+      }
+    }
+
+    if (arg1.type === 'ArrayExpression') {
+      for (const element of arg1.elements) {
+        validateLiteral(element)
       }
-    } else if (arg1.type === 'Literal') {
-      if (typeof arg1.value !== 'string')
-        throw err(
-          `Expected glob to be a string, but got "${typeof arg1.value}"`
-        )
-      globs.push(arg1.value)
     } else {
-      throw err('Could only use literals')
+      validateLiteral(arg1)
     }
 
     // arg2
@@ -426,7 +438,9 @@ export async function transformGlobImport(
 
           files.forEach((i) => matchedFiles.add(i))
 
-          const replacement = `Object.assign({${objectProps.join(',')}})`
+          const replacement = `/* #__PURE__ */ Object.assign({${objectProps.join(
+            ','
+          )}})`
           s.overwrite(start, end, replacement)
 
           return staticImports
diff --git a/packages/vite/src/node/plugins/index.ts b/packages/vite/src/node/plugins/index.ts
index c58cf8f30a77e5..a2fbebcc75b66e 100644
--- a/packages/vite/src/node/plugins/index.ts
+++ b/packages/vite/src/node/plugins/index.ts
@@ -85,7 +85,7 @@ export async function resolvePlugins(
     wasmFallbackPlugin(),
     definePlugin(config),
     cssPostPlugin(config),
-    config.build.ssr ? ssrRequireHookPlugin(config) : null,
+    isBuild && config.build.ssr ? ssrRequireHookPlugin(config) : null,
     isBuild && buildHtmlPlugin(config),
     workerImportMetaUrlPlugin(config),
     ...buildPlugins.pre,
diff --git a/packages/vite/src/node/plugins/modulePreloadPolyfill.ts b/packages/vite/src/node/plugins/modulePreloadPolyfill.ts
index 4f0b3389fcc2c3..1799db26c8a9d1 100644
--- a/packages/vite/src/node/plugins/modulePreloadPolyfill.ts
+++ b/packages/vite/src/node/plugins/modulePreloadPolyfill.ts
@@ -22,8 +22,7 @@ export function modulePreloadPolyfillPlugin(config: ResolvedConfig): Plugin {
           return ''
         }
         if (!polyfillString) {
-          polyfillString =
-            `const p = ${polyfill.toString()};` + `${isModernFlag}&&p();`
+          polyfillString = `${isModernFlag}&&(${polyfill.toString()}());`
         }
         return polyfillString
       }
diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts
index 1ebe847359384c..f1878e89d17433 100644
--- a/packages/vite/src/node/plugins/resolve.ts
+++ b/packages/vite/src/node/plugins/resolve.ts
@@ -28,6 +28,7 @@ import {
   isObject,
   isPossibleTsOutput,
   isTsRequest,
+  isWindows,
   nestedResolveFrom,
   normalizePath,
   resolveFrom,
@@ -114,11 +115,6 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
         return id
       }
 
-      // fast path for commonjs proxy modules
-      if (/\?commonjs/.test(id) || id === 'commonjsHelpers.js') {
-        return
-      }
-
       const targetWeb = !ssr || ssrTarget === 'webworker'
 
       // this is passed by @rollup/plugin-commonjs
@@ -243,6 +239,17 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
         }
       }
 
+      // drive relative fs paths (only windows)
+      if (isWindows && id.startsWith('/')) {
+        const basedir = importer ? path.dirname(importer) : process.cwd()
+        const fsPath = path.resolve(basedir, id)
+        if ((res = tryFsResolve(fsPath, options))) {
+          isDebug &&
+            debug(`[drive-relative] ${colors.cyan(id)} -> ${colors.dim(res)}`)
+          return res
+        }
+      }
+
       // absolute fs paths
       if (
         isNonDriveRelativeAbsolutePath(id) &&
@@ -544,7 +551,8 @@ export function tryNodeResolve(
   targetWeb: boolean,
   depsOptimizer?: DepsOptimizer,
   ssr?: boolean,
-  externalize?: boolean
+  externalize?: boolean,
+  allowLinkedExternal: boolean = true
 ): PartialResolvedId | undefined {
   const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options
 
@@ -644,14 +652,22 @@ export function tryNodeResolve(
     if (!externalize) {
       return resolved
     }
+    // don't external symlink packages
+    if (!allowLinkedExternal && !resolved.id.includes('node_modules')) {
+      return resolved
+    }
     const resolvedExt = path.extname(resolved.id)
+    // don't external non-js imports
+    if (
+      resolvedExt &&
+      resolvedExt !== '.js' &&
+      resolvedExt !== '.mjs' &&
+      resolvedExt !== '.cjs'
+    ) {
+      return resolved
+    }
     let resolvedId = id
     if (isDeepImport) {
-      // check ext before externalizing - only externalize
-      // extension-less imports and explicit .js imports
-      if (resolvedExt && !resolved.id.match(/(.js|.mjs|.cjs)$/)) {
-        return
-      }
       if (!pkg?.data.exports && path.extname(id) !== resolvedExt) {
         resolvedId += resolvedExt
       }
@@ -851,6 +867,8 @@ export function resolvePackageEntry(
             ) {
               // likely UMD or CJS(!!! e.g. firebase 7.x), prefer module
               entryPoint = data.module
+            } else {
+              entryPoint = browserEntry
             }
           }
         } else {
diff --git a/packages/vite/src/node/plugins/ssrRequireHook.ts b/packages/vite/src/node/plugins/ssrRequireHook.ts
index dc51f9114c5ef2..d1173b211ff836 100644
--- a/packages/vite/src/node/plugins/ssrRequireHook.ts
+++ b/packages/vite/src/node/plugins/ssrRequireHook.ts
@@ -53,7 +53,9 @@ type NodeResolveFilename = (
 /** Respect the `resolve.dedupe` option in production SSR. */
 function dedupeRequire(dedupe: string[]) {
   // eslint-disable-next-line no-restricted-globals
-  const Module = require('module') as { _resolveFilename: NodeResolveFilename }
+  const Module = require('node:module') as {
+    _resolveFilename: NodeResolveFilename
+  }
   const resolveFilename = Module._resolveFilename
   Module._resolveFilename = function (request, parent, isMain, options) {
     if (request[0] !== '.' && request[0] !== '/') {
diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts
index 29c05a880d998c..25aa49d38a966a 100644
--- a/packages/vite/src/node/plugins/worker.ts
+++ b/packages/vite/src/node/plugins/worker.ts
@@ -144,15 +144,6 @@ function emitSourcemapForWorkerEntry(
   return chunk
 }
 
-// TODO:base review why we aren't using import.meta.url here
-function toStaticRelativePath(filename: string, importer: string) {
-  let outputFilepath = path.posix.relative(path.dirname(importer), filename)
-  if (!outputFilepath.startsWith('.')) {
-    outputFilepath = './' + outputFilepath
-  }
-  return outputFilepath
-}
-
 export const workerAssetUrlRE = /__VITE_WORKER_ASSET__([a-z\d]{8})__/g
 
 function encodeWorkerAssetFileName(
@@ -317,7 +308,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
       }
     },
 
-    renderChunk(code, chunk) {
+    renderChunk(code, chunk, outputOptions) {
       let s: MagicString
       const result = () => {
         return (
@@ -344,7 +335,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
             chunk.fileName,
             'js',
             config,
-            toStaticRelativePath
+            outputOptions.format
           )
           const replacementString =
             typeof replacement === 'string'
@@ -359,21 +350,20 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
             }
           )
         }
-
-        // TODO: check if this should be removed
-        if (config.isWorker) {
-          s = s.replace('import.meta.url', 'self.location.href')
-          return result()
-        }
-      }
-      if (!isWorker) {
-        const workerMap = workerCache.get(config)!
-        workerMap.assets.forEach((asset) => {
-          this.emitFile(asset)
-          workerMap.assets.delete(asset.fileName!)
-        })
       }
       return result()
+    },
+
+    generateBundle(opts) {
+      // @ts-ignore asset emits are skipped in legacy bundle
+      if (opts.__vite_skip_asset_emit__ || isWorker) {
+        return
+      }
+      const workerMap = workerCache.get(config)!
+      workerMap.assets.forEach((asset) => {
+        this.emitFile(asset)
+        workerMap.assets.delete(asset.fileName!)
+      })
     }
   }
 }
diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts
index 7b2cc4bb1729b4..2a563575c69ce1 100644
--- a/packages/vite/src/node/preview.ts
+++ b/packages/vite/src/node/preview.ts
@@ -6,7 +6,12 @@ import type { Connect } from 'types/connect'
 import corsMiddleware from 'cors'
 import type { ResolvedServerOptions, ResolvedServerUrls } from './server'
 import type { CommonServerOptions } from './http'
-import { httpServerStart, resolveHttpServer, resolveHttpsConfig } from './http'
+import {
+  httpServerStart,
+  resolveHttpServer,
+  resolveHttpsConfig,
+  setClientErrorHandler
+} from './http'
 import { openBrowser } from './server/openBrowser'
 import compression from './server/middlewares/compression'
 import { proxyMiddleware } from './server/middlewares/proxy'
@@ -48,7 +53,7 @@ export interface PreviewServer {
    */
   httpServer: http.Server
   /**
-   * The resolved urls Vite prints on the
+   * The resolved urls Vite prints on the CLI
    *
    * @experimental
    */
@@ -78,6 +83,7 @@ export async function preview(
     app,
     await resolveHttpsConfig(config.preview?.https, config.cacheDir)
   )
+  setClientErrorHandler(httpServer, config.logger)
 
   // apply server hooks from plugins
   const postHooks: ((() => void) | void)[] = []
diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts
index f96e9353ce0450..a4de1284a7e050 100644
--- a/packages/vite/src/node/server/hmr.ts
+++ b/packages/vite/src/node/server/hmr.ts
@@ -231,6 +231,11 @@ function propagateUpdate(
   // if the imports of `node` have not been analyzed, then `node` has not
   // been loaded in the browser and we should stop propagation.
   if (node.id && node.isSelfAccepting === undefined) {
+    debugHmr(
+      `[propagate update] stop propagation because not analyzed: ${colors.dim(
+        node.id
+      )}`
+    )
     return false
   }
 
diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts
index a8222be65ae7b2..98d7814e587751 100644
--- a/packages/vite/src/node/server/index.ts
+++ b/packages/vite/src/node/server/index.ts
@@ -12,7 +12,12 @@ import type { Connect } from 'types/connect'
 import launchEditorMiddleware from 'launch-editor-middleware'
 import type { SourceMap } from 'rollup'
 import type { CommonServerOptions } from '../http'
-import { httpServerStart, resolveHttpServer, resolveHttpsConfig } from '../http'
+import {
+  httpServerStart,
+  resolveHttpServer,
+  resolveHttpsConfig,
+  setClientErrorHandler
+} from '../http'
 import type { InlineConfig, ResolvedConfig } from '../config'
 import { isDepsOptimizerEnabled, resolveConfig } from '../config'
 import {
@@ -301,6 +306,10 @@ export async function createServer(
     : await resolveHttpServer(serverConfig, middlewares, httpsOptions)
   const ws = createWebSocketServer(httpServer, config, httpsOptions)
 
+  if (httpServer) {
+    setClientErrorHandler(httpServer, config.logger)
+  }
+
   const { ignored = [], ...watchOptions } = serverConfig.watch || {}
   const watcher = chokidar.watch(path.resolve(root), {
     ignored: [
diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts
index 7fc576ba91252c..9f07a3c6e7bc24 100644
--- a/packages/vite/src/node/server/middlewares/proxy.ts
+++ b/packages/vite/src/node/server/middlewares/proxy.ts
@@ -1,4 +1,5 @@
 import type * as http from 'node:http'
+import type * as net from 'node:net'
 import httpProxy from 'http-proxy'
 import type { Connect } from 'types/connect'
 import type { HttpProxy } from 'types/http-proxy'
@@ -43,16 +44,31 @@ export function proxyMiddleware(
     }
     const proxy = httpProxy.createProxyServer(opts) as HttpProxy.Server
 
-    proxy.on('error', (err, req, res) => {
-      config.logger.error(`${colors.red(`http proxy error:`)}\n${err.stack}`, {
-        timestamp: true,
-        error: err
-      })
-      res
-        .writeHead(500, {
-          'Content-Type': 'text/plain'
+    proxy.on('error', (err, req, originalRes) => {
+      // When it is ws proxy, res is net.Socket
+      const res = originalRes as http.ServerResponse | net.Socket
+      if ('req' in res) {
+        config.logger.error(
+          `${colors.red(`http proxy error:`)}\n${err.stack}`,
+          {
+            timestamp: true,
+            error: err
+          }
+        )
+        if (!res.headersSent && !res.writableEnded) {
+          res
+            .writeHead(500, {
+              'Content-Type': 'text/plain'
+            })
+            .end()
+        }
+      } else {
+        config.logger.error(`${colors.red(`ws proxy error:`)}\n${err.stack}`, {
+          timestamp: true,
+          error: err
         })
-        .end()
+        res.end()
+      }
     })
 
     if (opts.configure) {
diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts
index 3b482068bd6138..1c71529ef72e79 100644
--- a/packages/vite/src/node/server/middlewares/static.ts
+++ b/packages/vite/src/node/server/middlewares/static.ts
@@ -80,36 +80,40 @@ export function serveStaticMiddleware(
       return next()
     }
 
-    const url = decodeURIComponent(req.url!)
+    const url = new URL(req.url!, 'http://example.com')
+    const pathname = decodeURIComponent(url.pathname)
 
     // apply aliases to static requests as well
-    let redirected: string | undefined
+    let redirectedPathname: string | undefined
     for (const { find, replacement } of server.config.resolve.alias) {
       const matches =
-        typeof find === 'string' ? url.startsWith(find) : find.test(url)
+        typeof find === 'string'
+          ? pathname.startsWith(find)
+          : find.test(pathname)
       if (matches) {
-        redirected = url.replace(find, replacement)
+        redirectedPathname = pathname.replace(find, replacement)
         break
       }
     }
-    if (redirected) {
+    if (redirectedPathname) {
       // dir is pre-normalized to posix style
-      if (redirected.startsWith(dir)) {
-        redirected = redirected.slice(dir.length)
+      if (redirectedPathname.startsWith(dir)) {
+        redirectedPathname = redirectedPathname.slice(dir.length)
       }
     }
 
-    const resolvedUrl = redirected || url
-    let fileUrl = path.resolve(dir, resolvedUrl.replace(/^\//, ''))
-    if (resolvedUrl.endsWith('/') && !fileUrl.endsWith('/')) {
+    const resolvedPathname = redirectedPathname || pathname
+    let fileUrl = path.resolve(dir, resolvedPathname.replace(/^\//, ''))
+    if (resolvedPathname.endsWith('/') && !fileUrl.endsWith('/')) {
       fileUrl = fileUrl + '/'
     }
     if (!ensureServingAccess(fileUrl, server, res, next)) {
       return
     }
 
-    if (redirected) {
-      req.url = encodeURIComponent(redirected)
+    if (redirectedPathname) {
+      url.pathname = encodeURIComponent(redirectedPathname)
+      req.url = url.href.slice(url.origin.length)
     }
 
     serve(req, res, next)
@@ -123,16 +127,17 @@ export function serveRawFsMiddleware(
 
   // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
   return function viteServeRawFsMiddleware(req, res, next) {
-    let url = decodeURIComponent(req.url!)
+    const url = new URL(req.url!, 'http://example.com')
     // In some cases (e.g. linked monorepos) files outside of root will
     // reference assets that are also out of served root. In such cases
     // the paths are rewritten to `/@fs/` prefixed paths and must be served by
     // searching based from fs root.
-    if (url.startsWith(FS_PREFIX)) {
+    if (url.pathname.startsWith(FS_PREFIX)) {
+      const pathname = decodeURIComponent(url.pathname)
       // restrict files outside of `fs.allow`
       if (
         !ensureServingAccess(
-          slash(path.resolve(fsPathFromId(url))),
+          slash(path.resolve(fsPathFromId(pathname))),
           server,
           res,
           next
@@ -141,10 +146,11 @@ export function serveRawFsMiddleware(
         return
       }
 
-      url = url.slice(FS_PREFIX.length)
-      if (isWindows) url = url.replace(/^[A-Z]:/i, '')
+      let newPathname = pathname.slice(FS_PREFIX.length)
+      if (isWindows) newPathname = newPathname.replace(/^[A-Z]:/i, '')
 
-      req.url = encodeURIComponent(url)
+      url.pathname = encodeURIComponent(newPathname)
+      req.url = url.href.slice(url.origin.length)
       serveFromRoot(req, res, next)
     } else {
       next()
@@ -187,7 +193,7 @@ function ensureServingAccess(
     const hintMessage = `
 ${server.config.server.fs.allow.map((i) => `- ${i}`).join('\n')}
 
-Refer to docs https://vitejs.dev/config/#server-fs-allow for configurations and more details.`
+Refer to docs https://vitejs.dev/config/server-options.html#server-fs-allow for configurations and more details.`
 
     server.config.logger.error(urlMessage)
     server.config.logger.warnOnce(hintMessage + '\n')
diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts
index 8d240df9cda2f1..1bba1711e1b326 100644
--- a/packages/vite/src/node/server/middlewares/transform.ts
+++ b/packages/vite/src/node/server/middlewares/transform.ts
@@ -218,9 +218,9 @@ export function transformMiddleware(
         }
         // We don't need to log an error in this case, the request
         // is outdated because new dependencies were discovered and
-        // the new pre-bundle dependendencies have changed.
+        // the new pre-bundle dependencies have changed.
         // A full-page reload has been issued, and these old requests
-        // can't be properly fullfilled. This isn't an unexpected
+        // can't be properly fulfilled. This isn't an unexpected
         // error but a normal part of the missing deps discovery flow
         return
       }
diff --git a/packages/vite/src/node/server/moduleGraph.ts b/packages/vite/src/node/server/moduleGraph.ts
index 45fea171ddcc1e..4bbd79cd5cc2f6 100644
--- a/packages/vite/src/node/server/moduleGraph.ts
+++ b/packages/vite/src/node/server/moduleGraph.ts
@@ -1,5 +1,4 @@
 import { extname } from 'node:path'
-import { parse as parseUrl } from 'node:url'
 import type { ModuleInfo, PartialResolvedId } from 'rollup'
 import { isDirectCSSRequest } from '../plugins/css'
 import {
@@ -237,10 +236,16 @@ export class ModuleGraph {
     url = removeImportQuery(removeTimestampQuery(url))
     const resolved = await this.resolveId(url, !!ssr)
     const resolvedId = resolved?.id || url
-    const ext = extname(cleanUrl(resolvedId))
-    const { pathname, search, hash } = parseUrl(url)
-    if (ext && !pathname!.endsWith(ext)) {
-      url = pathname + ext + (search || '') + (hash || '')
+    if (
+      url !== resolvedId &&
+      !url.includes('\0') &&
+      !url.startsWith(`virtual:`)
+    ) {
+      const ext = extname(cleanUrl(resolvedId))
+      const { pathname, search, hash } = new URL(url, 'relative://')
+      if (ext && !pathname!.endsWith(ext)) {
+        url = pathname + ext + search + hash
+      }
     }
     return [url, resolvedId, resolved?.meta]
   }
diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
index cc5b19522ef9a5..e70a3e30c948cc 100644
--- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
+++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
@@ -125,6 +125,18 @@ test('export default', async () => {
   ).toMatchInlineSnapshot(`"__vite_ssr_exports__.default = {}"`)
 })
 
+test('export then import minified', async () => {
+  expect(
+    await ssrTransformSimpleCode(
+      `export * from 'vue';import {createApp} from 'vue';`
+    )
+  ).toMatchInlineSnapshot(`
+    "const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\");
+    __vite_ssr_exportAll__(__vite_ssr_import_1__);const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
+    "
+  `)
+})
+
 test('import.meta', async () => {
   expect(
     await ssrTransformSimpleCode(`console.log(import.meta.url)`)
@@ -388,6 +400,30 @@ const a = () => {
     }
     "
   `)
+
+  // #9585
+  expect(
+    await ssrTransformSimpleCode(
+      `
+import { n, m } from 'foo'
+const foo = {}
+
+{
+  const { [n]: m } = foo
+}
+`
+    )
+  ).toMatchInlineSnapshot(`
+    "
+    const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
+
+    const foo = {}
+
+    {
+      const { [__vite_ssr_import_0__.n]: m } = foo
+    }
+    "
+  `)
 })
 
 test('nested object destructure alias', async () => {
@@ -451,6 +487,45 @@ objRest()
   `)
 })
 
+test('object props and methods', async () => {
+  expect(
+    await ssrTransformSimpleCode(
+      `
+import foo from 'foo'
+
+const bar = 'bar'
+
+const obj = {
+  foo() {},
+  [foo]() {},
+  [bar]() {},
+  foo: () => {},
+  [foo]: () => {},
+  [bar]: () => {},
+  bar(foo) {}
+}
+`
+    )
+  ).toMatchInlineSnapshot(`
+    "
+    const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
+
+
+    const bar = 'bar'
+
+    const obj = {
+      foo() {},
+      [__vite_ssr_import_0__.default]() {},
+      [bar]() {},
+      foo: () => {},
+      [__vite_ssr_import_0__.default]: () => {},
+      [bar]: () => {},
+      bar(foo) {}
+    }
+    "
+  `)
+})
+
 test('class props', async () => {
   expect(
     await ssrTransformSimpleCode(
diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts
index c69c117ebde843..d73d17c1d7c3c8 100644
--- a/packages/vite/src/node/ssr/ssrExternal.ts
+++ b/packages/vite/src/node/ssr/ssrExternal.ts
@@ -107,30 +107,83 @@ export function shouldExternalizeForSSR(
 
 export function createIsConfiguredAsSsrExternal(
   config: ResolvedConfig
-): (id: string) => boolean | undefined {
-  const { ssr } = config
+): (id: string) => boolean {
+  const { ssr, root } = config
   const noExternal = ssr?.noExternal
   const noExternalFilter =
     noExternal !== 'undefined' &&
     typeof noExternal !== 'boolean' &&
     createFilter(undefined, noExternal, { resolve: false })
 
+  const resolveOptions: InternalResolveOptions = {
+    root,
+    preserveSymlinks: config.resolve.preserveSymlinks,
+    isProduction: false,
+    isBuild: true
+  }
+
+  const isExternalizable = (
+    id: string,
+    configuredAsExternal?: boolean
+  ): boolean => {
+    if (!bareImportRE.test(id) || id.includes('\0')) {
+      return false
+    }
+    try {
+      return !!tryNodeResolve(
+        id,
+        undefined,
+        resolveOptions,
+        ssr?.target === 'webworker',
+        undefined,
+        true,
+        // try to externalize, will return undefined or an object without
+        // a external flag if it isn't externalizable
+        true,
+        // Allow linked packages to be externalized if they are explicitly
+        // configured as external
+        !!configuredAsExternal
+      )?.external
+    } catch (e) {
+      debug(
+        `Failed to node resolve "${id}". Skipping externalizing it by default.`
+      )
+      // may be an invalid import that's resolved by a plugin
+      return false
+    }
+  }
+
   // Returns true if it is configured as external, false if it is filtered
   // by noExternal and undefined if it isn't affected by the explicit config
   return (id: string) => {
     const { ssr } = config
     if (ssr) {
-      if (ssr.external?.includes(id)) {
+      if (
+        // If this id is defined as external, force it as external
+        // Note that individual package entries are allowed in ssr.external
+        ssr.external?.includes(id)
+      ) {
         return true
       }
+      const pkgName = getNpmPackageName(id)
+      if (!pkgName) {
+        return isExternalizable(id)
+      }
+      if (
+        // A package name in ssr.external externalizes every
+        // externalizable package entry
+        ssr.external?.includes(pkgName)
+      ) {
+        return isExternalizable(id, true)
+      }
       if (typeof noExternal === 'boolean') {
         return !noExternal
       }
-      if (noExternalFilter && !noExternalFilter(id)) {
+      if (noExternalFilter && !noExternalFilter(pkgName)) {
         return false
       }
     }
-    return undefined
+    return isExternalizable(id)
   }
 }
 
@@ -139,40 +192,15 @@ function createIsSsrExternal(
 ): (id: string) => boolean | undefined {
   const processedIds = new Map()
 
-  const { ssr, root } = config
-
   const isConfiguredAsExternal = createIsConfiguredAsSsrExternal(config)
 
-  const resolveOptions: InternalResolveOptions = {
-    root,
-    preserveSymlinks: config.resolve.preserveSymlinks,
-    isProduction: false,
-    isBuild: true
-  }
-
-  const isValidPackageEntry = (id: string) => {
-    if (!bareImportRE.test(id) || id.includes('\0')) {
-      return false
-    }
-    return !!tryNodeResolve(
-      id,
-      undefined,
-      resolveOptions,
-      ssr?.target === 'webworker',
-      undefined,
-      true,
-      true // try to externalize, will return undefined if not possible
-    )
-  }
-
   return (id: string) => {
     if (processedIds.has(id)) {
       return processedIds.get(id)
     }
     let external = false
     if (!id.startsWith('.') && !path.isAbsolute(id)) {
-      external =
-        isBuiltin(id) || (isConfiguredAsExternal(id) ?? isValidPackageEntry(id))
+      external = isBuiltin(id) || isConfiguredAsExternal(id)
     }
     processedIds.set(id, external)
     return external
diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts
index a2e30b2a6ccf5e..8f61125c134d8c 100644
--- a/packages/vite/src/node/ssr/ssrModuleLoader.ts
+++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts
@@ -137,7 +137,8 @@ async function instantiateModule(
     if (dep[0] !== '.' && dep[0] !== '/') {
       return nodeImport(dep, mod.file!, resolveOptions)
     }
-    dep = unwrapId(dep)
+    // convert to rollup URL because `pendingImports`, `moduleGraph.urlToModuleMap` requires that
+    dep = unwrapId(dep).replace(NULL_BYTE_PLACEHOLDER, '\0')
     if (!isCircular(dep) && !pendingImports.get(dep)?.some(isCircular)) {
       pendingDeps.push(dep)
       if (pendingDeps.length === 1) {
@@ -194,7 +195,7 @@ async function instantiateModule(
       ssrImportKey,
       ssrDynamicImportKey,
       ssrExportAllKey,
-      result.code + `\n//# sourceURL=${mod.url}`
+      '"use strict";' + result.code + `\n//# sourceURL=${mod.url}`
     )
     await initModule(
       context.global,
@@ -306,7 +307,7 @@ async function nodeImport(
 
 // rollup-style default import interop for cjs
 function proxyESM(mod: any) {
-  // This is the only sensible option when the exports object is a primitve
+  // This is the only sensible option when the exports object is a primitive
   if (isPrimitive(mod)) return { default: mod }
 
   let defaultExport = 'default' in mod ? mod.default : mod
diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts
index 2c38c53e74714e..0798d674547fb3 100644
--- a/packages/vite/src/node/ssr/ssrTransform.ts
+++ b/packages/vite/src/node/ssr/ssrTransform.ts
@@ -94,7 +94,7 @@ async function ssrTransformScript(
   function defineImport(node: Node, source: string) {
     deps.add(source)
     const importId = `__vite_ssr_import_${uid++}__`
-    s.appendLeft(
+    s.appendRight(
       node.start,
       `const ${importId} = await ${ssrImportKey}(${JSON.stringify(source)});\n`
     )
@@ -115,6 +115,7 @@ async function ssrTransformScript(
     // import { baz } from 'foo' --> baz -> __import_foo__.baz
     // import * as ok from 'foo' --> ok -> __import_foo__
     if (node.type === 'ImportDeclaration') {
+      s.remove(node.start, node.end)
       const importId = defineImport(node, node.source.value as string)
       for (const spec of node.specifiers) {
         if (spec.type === 'ImportSpecifier') {
@@ -129,7 +130,6 @@ async function ssrTransformScript(
           idToImportMap.set(spec.local.name, importId)
         }
       }
-      s.remove(node.start, node.end)
     }
   }
 
@@ -207,13 +207,11 @@ async function ssrTransformScript(
 
     // export * from './foo'
     if (node.type === 'ExportAllDeclaration') {
+      s.remove(node.start, node.end)
+      const importId = defineImport(node, node.source.value as string)
       if (node.exported) {
-        const importId = defineImport(node, node.source.value as string)
-        s.remove(node.start, node.end)
         defineExport(node.end, node.exported.name, `${importId}`)
       } else {
-        const importId = defineImport(node, node.source.value as string)
-        s.remove(node.start, node.end)
         s.appendLeft(node.end, `${ssrExportAllKey}(${importId});`)
       }
     }
@@ -232,7 +230,7 @@ async function ssrTransformScript(
         // { foo } -> { foo: __import_x__.foo }
         // skip for destructuring patterns
         if (
-          !isNodeInPatternWeakMap.get(parent) ||
+          !isNodeInPattern(parent) ||
           isInDestructuringAssignment(parent, parentStack)
         ) {
           s.appendLeft(id.end, `: ${binding}`)
@@ -307,7 +305,10 @@ interface Visitors {
   onDynamicImport: (node: Node) => void
 }
 
-const isNodeInPatternWeakMap = new WeakMap<_Node, boolean>()
+const isNodeInPatternWeakSet = new WeakSet<_Node>()
+const setIsNodeInPattern = (node: Property) => isNodeInPatternWeakSet.add(node)
+const isNodeInPattern = (node: _Node): node is Property =>
+  isNodeInPatternWeakSet.has(node)
 
 /**
  * Same logic from \@vue/compiler-core & \@vue/compiler-sfc
@@ -427,7 +428,7 @@ function walk(
         })
       } else if (node.type === 'Property' && parent!.type === 'ObjectPattern') {
         // mark property in destructuring pattern
-        isNodeInPatternWeakMap.set(node, true)
+        setIsNodeInPattern(node)
       } else if (node.type === 'VariableDeclarator') {
         const parentFunction = findParentFunction(parentStack)
         if (parentFunction) {
@@ -476,8 +477,12 @@ function isRefIdentifier(id: Identifier, parent: _Node, parentStack: _Node[]) {
   }
 
   // property key
-  // this also covers object destructuring pattern
-  if (isStaticPropertyKey(id, parent) || isNodeInPatternWeakMap.get(parent)) {
+  if (isStaticPropertyKey(id, parent)) {
+    return false
+  }
+
+  // object destructuring pattern
+  if (isNodeInPattern(parent) && parent.value === id) {
     return false
   }
 
diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts
index 1d647e366a3be2..85f85adf3cf550 100644
--- a/packages/vite/src/node/utils.ts
+++ b/packages/vite/src/node/utils.ts
@@ -261,7 +261,7 @@ export const isDataUrl = (url: string): boolean => dataUrlRE.test(url)
 export const virtualModuleRE = /^virtual-module:.*/
 export const virtualModulePrefix = 'virtual-module:'
 
-const knownJsSrcRE = /\.((j|t)sx?|mjs|vue|marko|svelte|astro)($|\?)/
+const knownJsSrcRE = /\.((j|t)sx?|m[jt]s|vue|marko|svelte|astro)($|\?)/
 export const isJSRequest = (url: string): boolean => {
   url = cleanUrl(url)
   if (knownJsSrcRE.test(url)) {
@@ -984,6 +984,10 @@ export function emptyCssComments(raw: string): string {
   return raw.replace(multilineCommentsRE, (s) => ' '.repeat(s.length))
 }
 
+export function removeComments(raw: string): string {
+  return raw.replace(multilineCommentsRE, '').replace(singlelineCommentsRE, '')
+}
+
 function mergeConfigRecursively(
   defaults: Record,
   overrides: Record,
@@ -1130,8 +1134,6 @@ export function stripBomTag(content: string): string {
   return content
 }
 
-export const isTS = (filename: string): boolean => /\.[cm]?ts$/.test(filename)
-
 const windowsDrivePathPrefixRE = /^[A-Za-z]:[/\\]/
 
 /**
diff --git a/packages/vite/types/commonjs.d.ts b/packages/vite/types/commonjs.d.ts
index 5891a7573112a5..01948156deb1cd 100644
--- a/packages/vite/types/commonjs.d.ts
+++ b/packages/vite/types/commonjs.d.ts
@@ -7,17 +7,17 @@
  */
 export interface RollupCommonJSOptions {
   /**
-   * A picomatch pattern, or array of patterns, which specifies the files in
+   * A minimatch pattern, or array of patterns, which specifies the files in
    * the build the plugin should operate on. By default, all files with
-   * extension `".cjs"` or those in `extensions` are included, but you can narrow
-   * this list by only including specific files. These files will be analyzed
-   * and transpiled if either the analysis does not find ES module specific
-   * statements or `transformMixedEsModules` is `true`.
+   * extension `".cjs"` or those in `extensions` are included, but you can
+   * narrow this list by only including specific files. These files will be
+   * analyzed and transpiled if either the analysis does not find ES module
+   * specific statements or `transformMixedEsModules` is `true`.
    * @default undefined
    */
   include?: string | RegExp | readonly (string | RegExp)[]
   /**
-   * A picomatch pattern, or array of patterns, which specifies the files in
+   * A minimatch pattern, or array of patterns, which specifies the files in
    * the build the plugin should _ignore_. By default, all files with
    * extensions other than those in `extensions` or `".cjs"` are ignored, but you
    * can exclude additional files. See also the `include` option.
@@ -37,7 +37,8 @@ export interface RollupCommonJSOptions {
    */
   ignoreGlobal?: boolean
   /**
-   * If false, skips source map generation for CommonJS modules. This will improve performance.
+   * If false, skips source map generation for CommonJS modules. This will
+   * improve performance.
    * @default true
    */
   sourceMap?: boolean
@@ -65,6 +66,39 @@ export interface RollupCommonJSOptions {
    * @default false
    */
   transformMixedEsModules?: boolean
+  /**
+   * By default, this plugin will try to hoist `require` statements as imports
+   * to the top of each file. While this works well for many code bases and
+   * allows for very efficient ESM output, it does not perfectly capture
+   * CommonJS semantics as the order of side effects like log statements may
+   * change. But it is especially problematic when there are circular `require`
+   * calls between CommonJS modules as those often rely on the lazy execution of
+   * nested `require` calls.
+   *
+   * Setting this option to `true` will wrap all CommonJS files in functions
+   * which are executed when they are required for the first time, preserving
+   * NodeJS semantics. Note that this can have an impact on the size and
+   * performance of the generated code.
+   *
+   * The default value of `"auto"` will only wrap CommonJS files when they are
+   * part of a CommonJS dependency cycle, e.g. an index file that is required by
+   * many of its dependencies. All other CommonJS files are hoisted. This is the
+   * recommended setting for most code bases.
+   *
+   * `false` will entirely prevent wrapping and hoist all files. This may still
+   * work depending on the nature of cyclic dependencies but will often cause
+   * problems.
+   *
+   * You can also provide a minimatch pattern, or array of patterns, to only
+   * specify a subset of files which should be wrapped in functions for proper
+   * `require` semantics.
+   *
+   * `"debug"` works like `"auto"` but after bundling, it will display a warning
+   * containing a list of ids that have been wrapped which can be used as
+   * minimatch pattern for fine-tuning.
+   * @default "auto"
+   */
+  strictRequires?: boolean | string | RegExp | readonly (string | RegExp)[]
   /**
    * Sometimes you have to leave require statements unconverted. Pass an array
    * containing the IDs or a `id => boolean` function.
@@ -75,14 +109,16 @@ export interface RollupCommonJSOptions {
    * In most cases, where `require` calls are inside a `try-catch` clause,
    * they should be left unconverted as it requires an optional dependency
    * that may or may not be installed beside the rolled up package.
-   * Due to the conversion of `require` to a static `import` - the call is hoisted
-   * to the top of the file, outside of the `try-catch` clause.
+   * Due to the conversion of `require` to a static `import` - the call is
+   * hoisted to the top of the file, outside of the `try-catch` clause.
    *
    * - `true`: All `require` calls inside a `try` will be left unconverted.
-   * - `false`: All `require` calls inside a `try` will be converted as if the `try-catch` clause is not there.
+   * - `false`: All `require` calls inside a `try` will be converted as if the
+   *   `try-catch` clause is not there.
    * - `remove`: Remove all `require` calls from inside any `try` block.
    * - `string[]`: Pass an array containing the IDs to left unconverted.
-   * - `((id: string) => boolean|'remove')`: Pass a function that control individual IDs.
+   * - `((id: string) => boolean|'remove')`: Pass a function that control
+   *   individual IDs.
    *
    * @default false
    */
@@ -165,12 +201,17 @@ export interface RollupCommonJSOptions {
     | 'preferred'
     | 'namespace'
     | ((id: string) => boolean | 'auto' | 'preferred' | 'namespace')
+
+  /**
+   * @default "auto"
+   */
+  defaultIsModuleExports?: boolean | 'auto' | ((id: string) => boolean | 'auto')
   /**
    * Some modules contain dynamic `require` calls, or require modules that
    * contain circular dependencies, which are not handled well by static
    * imports. Including those modules as `dynamicRequireTargets` will simulate a
-   * CommonJS (NodeJS-like)  environment for them with support for dynamic and
-   * circular dependencies.
+   * CommonJS (NodeJS-like)  environment for them with support for dynamic
+   * dependencies. It also enables `strictRequires` for those modules.
    *
    * Note: In extreme cases, this feature may result in some paths being
    * rendered as absolute in the final bundle. The plugin tries to avoid
@@ -179,4 +220,11 @@ export interface RollupCommonJSOptions {
    * replacing strings like `"/Users/John/Desktop/foo-project/"` -\> `"/"`.
    */
   dynamicRequireTargets?: string | ReadonlyArray
+  /**
+   * To avoid long paths when using the `dynamicRequireTargets` option, you can use this option to specify a directory
+   * that is a common parent for all files that use dynamic require statements. Using a directory higher up such as `/`
+   * may lead to unnecessarily long paths in the generated code and may expose directory names on your machine like your
+   * home directory name. By default it uses the current working directory.
+   */
+  dynamicRequireRoot?: string
 }
diff --git a/packages/vite/types/connect.d.ts b/packages/vite/types/connect.d.ts
index 2fb97ebeb494ab..74c559b6a436f5 100644
--- a/packages/vite/types/connect.d.ts
+++ b/packages/vite/types/connect.d.ts
@@ -14,7 +14,7 @@ export namespace Connect {
   export type ServerHandle = HandleFunction | http.Server
 
   export class IncomingMessage extends http.IncomingMessage {
-    originalUrl?: http.IncomingMessage['url']
+    originalUrl?: http.IncomingMessage['url'] | undefined
   }
 
   export type NextFunction = (err?: any) => void
diff --git a/packages/vite/types/http-proxy.d.ts b/packages/vite/types/http-proxy.d.ts
index 81b9226a4db669..5e2717eaa0fcbd 100644
--- a/packages/vite/types/http-proxy.d.ts
+++ b/packages/vite/types/http-proxy.d.ts
@@ -27,16 +27,16 @@ export namespace HttpProxy {
   export interface ProxyTargetDetailed {
     host: string
     port: number
-    protocol?: string
-    hostname?: string
-    socketPath?: string
-    key?: string
-    passphrase?: string
-    pfx?: Buffer | string
-    cert?: string
-    ca?: string
-    ciphers?: string
-    secureProtocol?: string
+    protocol?: string | undefined
+    hostname?: string | undefined
+    socketPath?: string | undefined
+    key?: string | undefined
+    passphrase?: string | undefined
+    pfx?: Buffer | string | undefined
+    cert?: string | undefined
+    ca?: string | undefined
+    ciphers?: string | undefined
+    secureProtocol?: string | undefined
   }
 
   export type ErrorCallback = (
@@ -189,54 +189,62 @@ export namespace HttpProxy {
 
   export interface ServerOptions {
     /** URL string to be parsed with the url module. */
-    target?: ProxyTarget
+    target?: ProxyTarget | undefined
     /** URL string to be parsed with the url module. */
-    forward?: ProxyTargetUrl
+    forward?: ProxyTargetUrl | undefined
     /** Object to be passed to http(s).request. */
     agent?: any
     /** Object to be passed to https.createServer(). */
     ssl?: any
     /** If you want to proxy websockets. */
-    ws?: boolean
+    ws?: boolean | undefined
     /** Adds x- forward headers. */
-    xfwd?: boolean
+    xfwd?: boolean | undefined
     /** Verify SSL certificate. */
-    secure?: boolean
+    secure?: boolean | undefined
     /** Explicitly specify if we are proxying to another proxy. */
-    toProxy?: boolean
+    toProxy?: boolean | undefined
     /** Specify whether you want to prepend the target's path to the proxy path. */
-    prependPath?: boolean
+    prependPath?: boolean | undefined
     /** Specify whether you want to ignore the proxy path of the incoming request. */
-    ignorePath?: boolean
+    ignorePath?: boolean | undefined
     /** Local interface string to bind for outgoing connections. */
-    localAddress?: string
+    localAddress?: string | undefined
     /** Changes the origin of the host header to the target URL. */
-    changeOrigin?: boolean
+    changeOrigin?: boolean | undefined
     /** specify whether you want to keep letter case of response header key */
-    preserveHeaderKeyCase?: boolean
+    preserveHeaderKeyCase?: boolean | undefined
     /** Basic authentication i.e. 'user:password' to compute an Authorization header. */
-    auth?: string
+    auth?: string | undefined
     /** Rewrites the location hostname on (301 / 302 / 307 / 308) redirects, Default: null. */
-    hostRewrite?: string
+    hostRewrite?: string | undefined
     /** Rewrites the location host/ port on (301 / 302 / 307 / 308) redirects based on requested host/ port.Default: false. */
-    autoRewrite?: boolean
+    autoRewrite?: boolean | undefined
     /** Rewrites the location protocol on (301 / 302 / 307 / 308) redirects to 'http' or 'https'.Default: null. */
-    protocolRewrite?: string
+    protocolRewrite?: string | undefined
     /** rewrites domain of set-cookie headers. */
-    cookieDomainRewrite?: false | string | { [oldDomain: string]: string }
+    cookieDomainRewrite?:
+      | false
+      | string
+      | { [oldDomain: string]: string }
+      | undefined
     /** rewrites path of set-cookie headers. Default: false */
-    cookiePathRewrite?: false | string | { [oldPath: string]: string }
+    cookiePathRewrite?:
+      | false
+      | string
+      | { [oldPath: string]: string }
+      | undefined
     /** object with extra headers to be added to target requests. */
-    headers?: { [header: string]: string }
+    headers?: { [header: string]: string } | undefined
     /** Timeout (in milliseconds) when proxy receives no response from target. Default: 120000 (2 minutes) */
-    proxyTimeout?: number
+    proxyTimeout?: number | undefined
     /** Timeout (in milliseconds) for incoming requests */
-    timeout?: number
+    timeout?: number | undefined
     /** Specify whether you want to follow redirects. Default: false */
-    followRedirects?: boolean
+    followRedirects?: boolean | undefined
     /** If set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the proxyRes event */
-    selfHandleResponse?: boolean
+    selfHandleResponse?: boolean | undefined
     /** Buffer */
-    buffer?: stream.Stream
+    buffer?: stream.Stream | undefined
   }
 }
diff --git a/packages/vite/types/terser.d.ts b/packages/vite/types/terser.d.ts
index 5c24660eb98781..a704a20cdc71ae 100644
--- a/packages/vite/types/terser.d.ts
+++ b/packages/vite/types/terser.d.ts
@@ -39,6 +39,7 @@ export namespace Terser {
 
   export interface ParseOptions {
     bare_returns?: boolean
+    /** @deprecated legacy option. Currently, all supported EcmaScript is valid to parse. */
     ecma?: ECMA
     html5_comments?: boolean
     shebang?: boolean
@@ -113,22 +114,59 @@ export namespace Terser {
     keep_classnames?: boolean | RegExp
     keep_fnames?: boolean | RegExp
     module?: boolean
+    nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler
     properties?: boolean | ManglePropertiesOptions
     reserved?: string[]
     safari10?: boolean
     toplevel?: boolean
   }
 
+  /**
+   * An identifier mangler for which the output is invariant with respect to the source code.
+   */
+  export interface SimpleIdentifierMangler {
+    /**
+     * Obtains the nth most favored (usually shortest) identifier to rename a variable to.
+     * The mangler will increment n and retry until the return value is not in use in scope, and is not a reserved word.
+     * This function is expected to be stable; Evaluating get(n) === get(n) should always return true.
+     * @param n - The ordinal of the identifier.
+     */
+    get(n: number): string
+  }
+
+  /**
+   * An identifier mangler that leverages character frequency analysis to determine identifier precedence.
+   */
+  export interface WeightedIdentifierMangler extends SimpleIdentifierMangler {
+    /**
+     * Modifies the internal weighting of the input characters by the specified delta.
+     * Will be invoked on the entire printed AST, and then deduct mangleable identifiers.
+     * @param chars - The characters to modify the weighting of.
+     * @param delta - The numeric weight to add to the characters.
+     */
+    consider(chars: string, delta: number): number
+    /**
+     * Resets character weights.
+     */
+    reset(): void
+    /**
+     * Sorts identifiers by character frequency, in preparation for calls to get(n).
+     */
+    sort(): void
+  }
+
   export interface ManglePropertiesOptions {
     builtins?: boolean
     debug?: boolean
     keep_quoted?: boolean | 'strict'
+    nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler
     regex?: RegExp | string
     reserved?: string[]
   }
 
   export interface FormatOptions {
     ascii_only?: boolean
+    /** @deprecated Not implemented anymore */
     beautify?: boolean
     braces?: boolean
     comments?:
@@ -148,6 +186,7 @@ export namespace Terser {
         ) => boolean)
     ecma?: ECMA
     ie8?: boolean
+    keep_numbers?: boolean
     indent_level?: number
     indent_start?: number
     inline_script?: boolean
@@ -178,6 +217,7 @@ export namespace Terser {
   export interface MinifyOptions {
     compress?: boolean | CompressOptions
     ecma?: ECMA
+    enclose?: boolean | string
     ie8?: boolean
     keep_classnames?: boolean | RegExp
     keep_fnames?: boolean | RegExp
@@ -185,6 +225,8 @@ export namespace Terser {
     module?: boolean
     nameCache?: object
     format?: FormatOptions
+    /** @deprecated deprecated */
+    output?: FormatOptions
     parse?: ParseOptions
     safari10?: boolean
     sourceMap?: boolean | SourceMapOptions
@@ -194,6 +236,7 @@ export namespace Terser {
   export interface MinifyOutput {
     code?: string
     map?: object | string
+    decoded_map?: object | null
   }
 
   export interface SourceMapOptions {
diff --git a/packages/vite/types/ws.d.ts b/packages/vite/types/ws.d.ts
index 4a03058d0eeaa2..a06341fca9eeb9 100644
--- a/packages/vite/types/ws.d.ts
+++ b/packages/vite/types/ws.d.ts
@@ -26,7 +26,7 @@ import type {
 } from 'node:http'
 import type { Server as HTTPSServer } from 'node:https'
 import type { Duplex, DuplexOptions } from 'node:stream'
-import type { SecureContextOptions } from 'tls'
+import type { SecureContextOptions } from 'node:tls'
 import type { URL } from 'node:url'
 import type { ZlibOptions } from 'node:zlib'
 
diff --git a/playground/alias/vite.config.js b/playground/alias/vite.config.js
index 634871877a0f56..16c33dd859aa66 100644
--- a/playground/alias/vite.config.js
+++ b/playground/alias/vite.config.js
@@ -1,4 +1,4 @@
-const path = require('path')
+const path = require('node:path')
 
 /**
  * @type {import('vite').UserConfig}
diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts
index c815714469b63b..ceb259102d4031 100644
--- a/playground/assets/__tests__/assets.spec.ts
+++ b/playground/assets/__tests__/assets.spec.ts
@@ -197,8 +197,8 @@ describe('image', () => {
     srcset.split(', ').forEach((s) => {
       expect(s).toMatch(
         isBuild
-          ? /\/foo\/assets\/asset\.\w{8}\.png \d{1}x/
-          : /\/foo\/nested\/asset\.png \d{1}x/
+          ? /\/foo\/assets\/asset\.\w{8}\.png \dx/
+          : /\/foo\/nested\/asset\.png \dx/
       )
     })
   })
@@ -288,6 +288,9 @@ test('new URL(`${dynamic}`, import.meta.url)', async () => {
   expect(await page.textContent('.dynamic-import-meta-url-2')).toMatch(
     assetMatch
   )
+  expect(await page.textContent('.dynamic-import-meta-url-js')).toMatch(
+    isBuild ? 'data:application/javascript;base64' : '/foo/nested/test.js'
+  )
 })
 
 test('new URL(`non-existent`, import.meta.url)', async () => {
@@ -364,3 +367,14 @@ test('relative path in html asset', async () => {
   expect(await page.textContent('.relative-js')).toMatch('hello')
   expect(await getColor('.relative-css')).toMatch('red')
 })
+
+test('url() contains file in publicDir, in 
+

+ inline style +

+

use style class

@import