diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 555654b9690922..70fbf8dfca8bf7 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -150,6 +150,13 @@ module.exports = defineConfig({
'no-console': ['error'],
},
},
+ {
+ files: ['packages/vite/src/client/**'],
+ excludedFiles: '**/__tests__/**',
+ rules: {
+ 'n/no-unsupported-features/node-builtins': 'off',
+ },
+ },
{
files: [
'packages/vite/src/types/**',
@@ -219,6 +226,9 @@ module.exports = defineConfig({
'error',
{
version: pkg.engines.node,
+ // ideally we would like to allow all experimental features
+ // https://github.com/eslint-community/eslint-plugin-n/issues/199
+ ignores: ['fetch'],
},
],
},
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 52dc9cd290a6a1..2e7b7db4b32655 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -58,7 +58,7 @@ jobs:
- name: Get changed files
id: changed-files
- uses: tj-actions/changed-files@0874344d6ebbaa00a27da73276ae7162fadcaf69 # v44.3.0
+ uses: tj-actions/changed-files@a29e8b565651ce417abb5db7164b4a2ad8b6155c # v44.4.0
with:
files: |
docs/**
@@ -69,7 +69,7 @@ jobs:
- name: Install pnpm
if: steps.changed-files.outputs.only_changed != 'true'
- uses: pnpm/action-setup@v3.0.0
+ uses: pnpm/action-setup@v4.0.0
- name: Set node version to ${{ matrix.node_version }}
if: steps.changed-files.outputs.only_changed != 'true'
@@ -134,7 +134,7 @@ jobs:
- uses: actions/checkout@v4
- name: Install pnpm
- uses: pnpm/action-setup@v3.0.0
+ uses: pnpm/action-setup@v4.0.0
- name: Set node version to 20
uses: actions/setup-node@v4
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index bde621d0d82a6c..37d8c135b458db 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v4
- name: Install pnpm
- uses: pnpm/action-setup@v3.0.0
+ uses: pnpm/action-setup@v4.0.0
- name: Set node version to 20
uses: actions/setup-node@v4
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index fbb842bfa2a801..a58aed971e0fc0 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -78,6 +78,7 @@ export default defineConfig({
['meta', { property: 'og:image', content: ogImage }],
['meta', { property: 'og:url', content: ogUrl }],
['meta', { property: 'og:description', content: ogDescription }],
+ ['meta', { property: 'og:site_name', content: 'vitejs' }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { name: 'twitter:site', content: '@vite_js' }],
['meta', { name: 'theme-color', content: '#646cff' }],
@@ -341,10 +342,10 @@ export default defineConfig({
.replace(/\/index\.md$/, '/')
.replace(/\.md$/, '/')
pageData.frontmatter.head ??= []
- pageData.frontmatter.head.unshift([
- 'link',
- { rel: 'canonical', href: canonicalUrl },
- ])
+ pageData.frontmatter.head.unshift(
+ ['link', { rel: 'canonical', href: canonicalUrl }],
+ ['meta', { property: 'og:title', content: pageData.title }],
+ )
return pageData
},
markdown: {
diff --git a/docs/blog/announcing-vite5-1.md b/docs/blog/announcing-vite5-1.md
index bb0fb3d7ce80e2..5b22abe800aacd 100644
--- a/docs/blog/announcing-vite5-1.md
+++ b/docs/blog/announcing-vite5-1.md
@@ -64,7 +64,7 @@ Import CSS files as URLs now works reliably and correctly. This was the last rem
### `build.assetsInlineLimit` now supports a callback
-Users can now [provide a callback](/config/build-options.html#build-assetsinlinelimit) that returns a boolean to opt-in or opt-out of inlining for specific assets. If `undefined` is returned, the defalt logic applies. See ([#15366](https://github.com/vitejs/vite/issues/15366)).
+Users can now [provide a callback](/config/build-options.html#build-assetsinlinelimit) that returns a boolean to opt-in or opt-out of inlining for specific assets. If `undefined` is returned, the default logic applies. See ([#15366](https://github.com/vitejs/vite/issues/15366)).
### Improved HMR for circular import
@@ -80,7 +80,7 @@ The preview server now exposes a `close` method, which will properly teardown th
## Performance improvements
-Vite keeps getting faster with each release, and Vite 5.1 is packed with performance improvements. We measured the loading time for 10K modules (25 level deep tree) using [vite-dev-server-perf](https://github.com/yyx990803/vite-dev-server-perf) for all minor versions from Vite 4.0. This is a good benchmark to meassure the effect of Vite's bundle-less approach. Each module is a small TypeScript file with a counter and imports to other files in the tree, so this mostly meassuring the time it takes to do the requests a separate modules. In Vite 4.0, loading 10K modules took 8 seconds on a M1 MAX. We had a breakthrough in [Vite 4.3 were we focused on performance](./announcing-vite4-3.md), and we were able to load them in 6.35 seconds. In Vite 5.1, we managed to do another performance leap. Vite is now serving the 10K modules in 5.35 seconds.
+Vite keeps getting faster with each release, and Vite 5.1 is packed with performance improvements. We measured the loading time for 10K modules (25 level deep tree) using [vite-dev-server-perf](https://github.com/yyx990803/vite-dev-server-perf) for all minor versions from Vite 4.0. This is a good benchmark to measure the effect of Vite's bundle-less approach. Each module is a small TypeScript file with a counter and imports to other files in the tree, so this mostly measuring the time it takes to do the requests a separate modules. In Vite 4.0, loading 10K modules took 8 seconds on a M1 MAX. We had a breakthrough in [Vite 4.3 were we focused on performance](./announcing-vite4-3.md), and we were able to load them in 6.35 seconds. In Vite 5.1, we managed to do another performance leap. Vite is now serving the 10K modules in 5.35 seconds.
![Vite 10K Modules Loading time progression](/vite5-1-10K-modules-loading-time.png)
@@ -111,7 +111,7 @@ The dev server had several incremental performance gains. A new middleware to sh
## Deprecations
-We continue to reduce Vite's API surface where possible to make the project manintainable long term.
+We continue to reduce Vite's API surface where possible to make the project maintainable long term.
### Deprecated `as` option in `import.meta.glob`
@@ -127,4 +127,4 @@ We are grateful to the [900 contributors to Vite Core](https://github.com/vitejs
## Acknowledgments
-Vite 5.1 is possible thanks to our community of contributors, maintainers in the ecosystem, and the [Vite Team](/team). A shoutout the individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) for hiring Vite team members. And also to the sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803).
+Vite 5.1 is possible thanks to our community of contributors, maintainers in the ecosystem, and the [Vite Team](/team). A shout out to the individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) for hiring Vite team members. And also to the sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803).
diff --git a/docs/blog/announcing-vite5.md b/docs/blog/announcing-vite5.md
index 1ce435792d2c1b..dd4c1d46a275b0 100644
--- a/docs/blog/announcing-vite5.md
+++ b/docs/blog/announcing-vite5.md
@@ -33,7 +33,7 @@ _November 16, 2023_
Vite 4 [was released](./announcing-vite4.md) almost a year ago, and it served as a solid base for the ecosystem. npm downloads per week jumped from 2.5 million to 7.5 million, as projects keep building on a shared infrastructure. Frameworks continued to innovate, and on top of [Astro](https://astro.build/), [Nuxt](https://nuxt.com/), [SvelteKit](https://kit.svelte.dev/), [Solid Start](https://www.solidjs.com/blog/introducing-solidstart), [Qwik City](https://qwik.builder.io/qwikcity/overview/), between others, we saw new frameworks joining and making the ecosystem stronger. [RedwoodJS](https://redwoodjs.com/) and [Remix](https://remix.run/) switching to Vite paves the way for further adoption in the React ecosystem. [Vitest](https://vitest.dev) kept growing at an even faster pace than Vite. Its team has been hard at work and will soon [release Vitest 1.0](https://github.com/vitest-dev/vitest/issues/3596). The story of Vite when used with other tools such as [Storybook](https://storybook.js.org), [Nx](https://nx.dev), and [Playwright](https://playwright.dev) kept improving, and the same goes for environments, with Vite dev working both in [Deno](https://deno.com) and [Bun](https://bun.sh).
-We had the second edition of [ViteConf](https://viteconf.org/23/replay) a month ago, hosted by [StackBlitz](https://stackblitz.com). Like last year, most of the projects in the ecosystem got together to share ideas and connect to keep expanding the commons. We're also seeing new pieces complement the meta-framework toolbelt like [Volar](https://volarjs.dev/) and [Nitro](https://nitro.unjs.io/). The Rollup team released [Rollup 4](https://rollupjs.org) that same day, a tradition Lukas started last year.
+We had the second edition of [ViteConf](https://viteconf.org/23/replay) a month ago, hosted by [StackBlitz](https://stackblitz.com). Like last year, most of the projects in the ecosystem got together to share ideas and connect to keep expanding the commons. We're also seeing new pieces complement the meta-framework tool belt like [Volar](https://volarjs.dev/) and [Nitro](https://nitro.unjs.io/). The Rollup team released [Rollup 4](https://rollupjs.org) that same day, a tradition Lukas started last year.
Six months ago, Vite 4.3 [was released](./announcing-vite4.md). This release significantly improved the dev server performance. However, there is still ample room for improvement. At ViteConf, [Evan You unveiled Vite's long-term plan to work on Rolldown](https://www.youtube.com/watch?v=hrdwQHoAp0M), a Rust-port of Rollup with compatible APIs. Once it is ready, we intend to use it in Vite Core to take on the tasks of both Rollup and esbuild. This will mean a boost in build performance (and later on in dev performance too as we move perf-sensitive parts of Vite itself to Rust), and a big reduction of inconsistencies between dev and build. Rolldown is currently in early stages and the team is preparing to open source the codebase before the end of the year. Stay tuned!
@@ -105,6 +105,6 @@ A low level breakdown with the full list of changes to Vite core can be found at
## Acknowledgments
-Vite 5 is the result of long hours of work by our community of contributors, downstream maintainers, plugins authors, and the [Vite Team](/team). A big shoutout to [Bjorn Lu](https://twitter.com/bluwyoo) for leading the release process for this major.
+Vite 5 is the result of long hours of work by our community of contributors, downstream maintainers, plugins authors, and the [Vite Team](/team). A big shout out to [Bjorn Lu](https://twitter.com/bluwyoo) for leading the release process for this major.
-We're also thankful to individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) continue to invest in Vite by hiring Vite team members. A shoutout to sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803). A special mention to [Remix](https://remix.run/) for becoming a Gold sponsor and contributing back after switching to Vite.
+We're also thankful to individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) continue to invest in Vite by hiring Vite team members. A shout out to sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803). A special mention to [Remix](https://remix.run/) for becoming a Gold sponsor and contributing back after switching to Vite.
diff --git a/docs/config/build-options.md b/docs/config/build-options.md
index 1c7d9c526e615c..02df0202b8319e 100644
--- a/docs/config/build-options.md
+++ b/docs/config/build-options.md
@@ -48,10 +48,10 @@ type ResolveModulePreloadDependenciesFn = (
The `resolveDependencies` function will be called for each dynamic import with a list of the chunks it depends on, and it will also be called for each chunk imported in entry HTML files. A new dependencies array can be returned with these filtered or more dependencies injected, and their paths modified. The `deps` paths are relative to the `build.outDir`. Returning a relative path to the `hostId` for `hostType === 'js'` is allowed, in which case `new URL(dep, import.meta.url)` is used to get an absolute path when injecting this module preload in the HTML head.
-
```js twoslash
/** @type {import('vite').UserConfig} */
const config = {
+ // prettier-ignore
build: {
// ---cut-before---
modulePreload: {
@@ -63,7 +63,6 @@ modulePreload: {
},
}
```
-
The resolved dependency paths can be further modified using [`experimental.renderBuiltUrl`](../guide/build.md#advanced-base-options).
diff --git a/docs/guide/api-hmr.md b/docs/guide/api-hmr.md
index 189fe693cf02f0..e9a44eb0aaca88 100644
--- a/docs/guide/api-hmr.md
+++ b/docs/guide/api-hmr.md
@@ -220,7 +220,7 @@ Send custom events back to Vite's dev server.
If called before connected, the data will be buffered and sent once the connection is established.
-See [Client-server Communication](/guide/api-plugin.html#client-server-communication) for more details.
+See [Client-server Communication](/guide/api-plugin.html#client-server-communication) for more details, including a section on [Typing Custom Events](/guide/api-plugin.html#typescript-for-custom-events).
## Further Reading
diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md
index 7f77b7b0464506..b06982b4b89fc2 100644
--- a/docs/guide/api-plugin.md
+++ b/docs/guide/api-plugin.md
@@ -625,16 +625,40 @@ export default defineConfig({
### TypeScript for Custom Events
-It is possible to type custom events by extending the `CustomEventMap` interface:
+Internally, vite infers the type of a payload from the `CustomEventMap` interface, it is possible to type custom events by extending the interface:
+
+:::tip Note
+Make sure to include the `.d.ts` extension when specifying TypeScript declaration files. Otherwise, Typescript may not know which file the module is trying to extend.
+:::
```ts
// events.d.ts
-import 'vite/types/customEvent'
+import 'vite/types/customEvent.d.ts'
-declare module 'vite/types/customEvent' {
+declare module 'vite/types/customEvent.d.ts' {
interface CustomEventMap {
'custom:foo': { msg: string }
// 'event-key': payload
}
}
```
+
+This interface extension is utilized by `InferCustomEventPayload
- Install - Volar - in your IDE for a better DX + Learn more about IDE Support for Vue in the + Vue Docs Scaling up Guide.
Click on the Vite and Vue logos to learn more
diff --git a/packages/create-vite/template-vue/package.json b/packages/create-vite/template-vue/package.json index 51e983bb180ac9..3662c122d0cd59 100644 --- a/packages/create-vite/template-vue/package.json +++ b/packages/create-vite/template-vue/package.json @@ -9,10 +9,10 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.4.26" + "vue": "^3.4.27" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.4", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-vue/src/components/HelloWorld.vue b/packages/create-vite/template-vue/src/components/HelloWorld.vue index f5e4f53b7d9dd0..546ebbc624b0e3 100644 --- a/packages/create-vite/template-vue/src/components/HelloWorld.vue +++ b/packages/create-vite/template-vue/src/components/HelloWorld.vue @@ -26,9 +26,12 @@ const count = ref(0) >, the official Vue + Vite starter- Install - Volar - in your IDE for a better DX + Learn more about IDE Support for Vue in the + Vue Docs Scaling up Guide.
Click on the Vite and Vue logos to learn more
diff --git a/packages/plugin-legacy/CHANGELOG.md b/packages/plugin-legacy/CHANGELOG.md index 9e90c6bd06742b..1e6988077ad53a 100644 --- a/packages/plugin-legacy/CHANGELOG.md +++ b/packages/plugin-legacy/CHANGELOG.md @@ -1,3 +1,16 @@ +## 5.4.0 (2024-05-08) + +* fix(deps): update all non-major dependencies (#16258) ([7caef42](https://github.com/vitejs/vite/commit/7caef42)), closes [#16258](https://github.com/vitejs/vite/issues/16258) +* fix(deps): update all non-major dependencies (#16376) ([58a2938](https://github.com/vitejs/vite/commit/58a2938)), closes [#16376](https://github.com/vitejs/vite/issues/16376) +* fix(deps): update all non-major dependencies (#16488) ([2d50be2](https://github.com/vitejs/vite/commit/2d50be2)), closes [#16488](https://github.com/vitejs/vite/issues/16488) +* fix(deps): update all non-major dependencies (#16549) ([2d6a13b](https://github.com/vitejs/vite/commit/2d6a13b)), closes [#16549](https://github.com/vitejs/vite/issues/16549) +* fix(legacy): modern polyfill autodetection was not injecting enough polyfills (#16367) ([4af9f97](https://github.com/vitejs/vite/commit/4af9f97)), closes [#16367](https://github.com/vitejs/vite/issues/16367) +* feat(plugin-legacy): support `additionalModernPolyfills` (#16514) ([2322657](https://github.com/vitejs/vite/commit/2322657)), closes [#16514](https://github.com/vitejs/vite/issues/16514) +* docs(legacy): update `modernTargets` option default value description (#16491) ([7171837](https://github.com/vitejs/vite/commit/7171837)), closes [#16491](https://github.com/vitejs/vite/issues/16491) +* chore(deps): update all non-major dependencies (#16131) ([a862ecb](https://github.com/vitejs/vite/commit/a862ecb)), closes [#16131](https://github.com/vitejs/vite/issues/16131) + + + ## 5.3.2 (2024-03-08) * fix(plugin-legacy): dynamic import browserslist-to-esbuild (#16011) ([42fd11c](https://github.com/vitejs/vite/commit/42fd11c)), closes [#16011](https://github.com/vitejs/vite/issues/16011) diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json index 9041ad980031b9..37148afdb7434b 100644 --- a/packages/plugin-legacy/package.json +++ b/packages/plugin-legacy/package.json @@ -1,6 +1,6 @@ { "name": "@vitejs/plugin-legacy", - "version": "5.3.2", + "version": "5.4.0", "license": "MIT", "author": "Evan You", "files": [ @@ -45,7 +45,7 @@ "@babel/preset-env": "^7.24.5", "browserslist": "^4.23.0", "browserslist-to-esbuild": "^2.1.1", - "core-js": "^3.37.0", + "core-js": "^3.37.1", "magic-string": "^0.30.10", "regenerator-runtime": "^0.14.1", "systemjs": "^6.15.1" @@ -56,7 +56,7 @@ }, "devDependencies": { "acorn": "^8.11.3", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "vite": "workspace:*" } } diff --git a/packages/vite/package.json b/packages/vite/package.json index 6cc9bca455b08e..3141a6472e9cdf 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -108,7 +108,7 @@ "@types/pnpapi": "^0.0.5", "acorn": "^8.11.3", "acorn-walk": "^8.3.2", - "artichokie": "^0.2.0", + "artichokie": "^0.2.1", "cac": "^6.7.14", "chokidar": "^3.6.0", "connect": "^3.7.0", @@ -119,32 +119,32 @@ "dep-types": "link:./src/types", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", - "es-module-lexer": "^1.5.2", + "es-module-lexer": "^1.5.3", "escape-html": "^1.0.3", "estree-walker": "^3.0.3", "etag": "^1.8.1", "fast-glob": "^3.3.2", "http-proxy": "^1.18.1", "launch-editor-middleware": "^2.6.1", - "lightningcss": "^1.24.1", + "lightningcss": "^1.25.0", "magic-string": "^0.30.10", "micromatch": "^4.0.5", - "mlly": "^1.6.1", + "mlly": "^1.7.0", "mrmime": "^2.0.0", "open": "^8.4.2", "parse5": "^7.1.2", "pathe": "^1.1.2", "periscopic": "^4.0.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "picomatch": "^2.3.1", "postcss-import": "^16.1.0", "postcss-load-config": "^4.0.2", "postcss-modules": "^6.0.0", "resolve.exports": "^2.0.2", - "rollup-plugin-dts": "^6.1.0", + "rollup-plugin-dts": "^6.1.1", "rollup-plugin-esbuild": "^6.1.1", - "rollup-plugin-license": "^3.3.1", - "sass": "^1.76.0", + "rollup-plugin-license": "^3.4.0", + "sass": "^1.77.2", "sirv": "^2.0.4", "source-map-support": "^0.5.21", "strip-ansi": "^7.1.0", diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 6c310528a3e4e7..8f83c3ce3ea132 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -628,7 +628,39 @@ export async function buildEnvironment( }, } - const mergeRollupError = (e: RollupError) => { + /** + * The stack string usually contains a copy of the message at the start of the stack. + * If the stack starts with the message, we remove it and just return the stack trace + * portion. Otherwise the original stack trace is used. + */ + function extractStack(e: RollupError) { + const { stack, name = 'Error', message } = e + + // If we don't have a stack, not much we can do. + if (!stack) { + return stack + } + + const expectedPrefix = `${name}: ${message}\n` + if (stack.startsWith(expectedPrefix)) { + return stack.slice(expectedPrefix.length) + } + + return stack + } + + /** + * Esbuild code frames have newlines at the start and end of the frame, rollup doesn't + * This function normalizes the frame to match the esbuild format which has more pleasing padding + */ + const normalizeCodeFrame = (frame: string) => { + const trimmedPadding = frame.replace(/^\n|\n$/g, '') + return `\n${trimmedPadding}\n` + } + + const enhanceRollupError = (e: RollupError) => { + const stackOnly = extractStack(e) + let msg = colors.red((e.plugin ? `[${e.plugin}] ` : '') + e.message) if (e.id) { msg += `\nfile: ${colors.cyan( @@ -636,15 +668,24 @@ export async function buildEnvironment( )}` } if (e.frame) { - msg += `\n` + colors.yellow(e.frame) + msg += `\n` + colors.yellow(normalizeCodeFrame(e.frame)) + } + + e.message = msg + + // We are rebuilding the stack trace to include the more detailed message at the top. + // Previously this code was relying on mutating e.message changing the generated stack + // when it was accessed, but we don't have any guarantees that the error we are working + // with hasn't already had its stack accessed before we get here. + if (stackOnly !== undefined) { + e.stack = `${e.message}\n${stackOnly}` } - return msg } const outputBuildError = (e: RollupError) => { - const msg = mergeRollupError(e) + enhanceRollupError(e) clearLine() - logger.error(msg, { error: e }) + logger.error(e.message, { error: e }) } let bundle: RollupBuild | undefined @@ -811,7 +852,7 @@ export async function buildEnvironment( ) return Array.isArray(outputs) ? res : res[0] } catch (e) { - e.message = mergeRollupError(e) + enhanceRollupError(e) clearLine() if (startTime) { logger.error( diff --git a/packages/vite/src/node/http.ts b/packages/vite/src/node/http.ts index 2039a6c9f75e22..51a063ba800ccf 100644 --- a/packages/vite/src/node/http.ts +++ b/packages/vite/src/node/http.ts @@ -43,8 +43,8 @@ export interface CommonServerOptions { * ``` js * module.exports = { * proxy: { - * // string shorthand - * '/foo': 'http://localhost:4567/foo', + * // string shorthand: /foo -> http://localhost:4567/foo + * '/foo': 'http://localhost:4567', * // with options * '/api': { * target: 'http://jsonplaceholder.typicode.com', diff --git a/packages/vite/src/node/logger.ts b/packages/vite/src/node/logger.ts index b41ad8f4d6cca9..d75b7cc6b016ee 100644 --- a/packages/vite/src/node/logger.ts +++ b/packages/vite/src/node/logger.ts @@ -4,6 +4,7 @@ import readline from 'node:readline' import colors from 'picocolors' import type { RollupError } from 'rollup' import type { ResolvedServerUrls } from './server' +import { splitRE } from './utils' export type LogType = 'error' | 'warn' | 'info' export type LogLevel = LogType | 'silent' @@ -64,6 +65,8 @@ function getTimeFormatter() { return timeFormatter } +const MAX_LOG_CHAR = 5000 + export function createLogger( level: LogLevel = 'info', options: LoggerOptions = {}, @@ -79,7 +82,22 @@ export function createLogger( allowClearScreen && process.stdout.isTTY && !process.env.CI const clear = canClearScreen ? clearScreen : () => {} - function format(type: LogType, msg: string, options: LogErrorOptions = {}) { + function preventOverflow(msg: string) { + if (msg.length > MAX_LOG_CHAR) { + const shorten = msg.slice(0, MAX_LOG_CHAR) + const lines = msg.slice(MAX_LOG_CHAR).match(splitRE)?.length || 0 + + return `${shorten}\n... and ${lines} lines more` + } + return msg + } + + function format( + type: LogType, + rawMsg: string, + options: LogErrorOptions = {}, + ) { + const msg = preventOverflow(rawMsg) if (options.timestamp) { const color = type === 'info' diff --git a/packages/vite/src/node/plugins/completeSystemWrap.ts b/packages/vite/src/node/plugins/completeSystemWrap.ts index 700a4202c0a4e4..8244fe80c046a0 100644 --- a/packages/vite/src/node/plugins/completeSystemWrap.ts +++ b/packages/vite/src/node/plugins/completeSystemWrap.ts @@ -4,7 +4,7 @@ import type { Plugin } from '../plugin' * make sure systemjs register wrap to had complete parameters in system format */ export function completeSystemWrapPlugin(): Plugin { - const SystemJSWrapRE = /System.register\(.*(\(exports\)|\(\))/g + const SystemJSWrapRE = /System.register\(.*?(\(exports\)|\(\))/g return { name: 'vite:force-systemjs-wrap-complete', diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 114cc9f092f083..3234f1929e7c0f 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -560,6 +560,8 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { const generatedAssets = generatedAssetsMap.get(this.environment)! let chunkCSS = '' + // the chunk is empty if it's a dynamic entry chunk that only contains a CSS import + const isJsChunkEmpty = code === '' && !chunk.isEntry let isPureCssChunk = true const ids = Object.keys(chunk.modules) for (const id of ids) { @@ -572,7 +574,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { isPureCssChunk = false } } - } else { + } else if (!isJsChunkEmpty) { // if the module does not have a style, then it's not a pure css chunk. // this is true because in the `transform` hook above, only modules // that are css gets added to the `styles` map. @@ -732,13 +734,13 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { } if (chunkCSS) { + if (isPureCssChunk && (opts.format === 'es' || opts.format === 'cjs')) { + // this is a shared CSS-only chunk that is empty. + pureCssChunks.add(chunk) + } + if (config.build.cssCodeSplit) { if (opts.format === 'es' || opts.format === 'cjs') { - if (isPureCssChunk) { - // this is a shared CSS-only chunk that is empty. - pureCssChunks.add(chunk) - } - const isEntry = chunk.isEntry && isPureCssChunk const cssFullAssetName = ensureFileExt(chunk.name, '.css') // if facadeModuleId doesn't exist or doesn't have a CSS extension, @@ -842,6 +844,40 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { return } + function extractCss() { + let css = '' + const collected = new SetThis should be green
+This should be blue
This should not be yellow
This should be yellow
diff --git a/playground/css-codesplit/main.js b/playground/css-codesplit/main.js index e548142add8786..ec266fa003156d 100644 --- a/playground/css-codesplit/main.js +++ b/playground/css-codesplit/main.js @@ -9,6 +9,7 @@ import chunkCssUrl from './chunk.css?url' globalThis.__test_chunkCssUrl = chunkCssUrl import('./async.css') +import('./async-js') import('./inline.css?inline').then((css) => { document.querySelector('.dynamic-inline').textContent = css.default diff --git a/playground/css-lightningcss-proxy/package.json b/playground/css-lightningcss-proxy/package.json index 06946b9a1f0756..575b4b04862532 100644 --- a/playground/css-lightningcss-proxy/package.json +++ b/playground/css-lightningcss-proxy/package.json @@ -9,7 +9,7 @@ "preview": "vite preview" }, "devDependencies": { - "lightningcss": "^1.24.1", + "lightningcss": "^1.25.0", "express": "^4.19.2" } } diff --git a/playground/css-lightningcss/package.json b/playground/css-lightningcss/package.json index 8a73fd408dcccc..9110820b6b2d71 100644 --- a/playground/css-lightningcss/package.json +++ b/playground/css-lightningcss/package.json @@ -9,6 +9,6 @@ "preview": "vite preview" }, "devDependencies": { - "lightningcss": "^1.24.1" + "lightningcss": "^1.25.0" } } diff --git a/playground/css-no-codesplit/__tests__/css-no-codesplit.spec.ts b/playground/css-no-codesplit/__tests__/css-no-codesplit.spec.ts new file mode 100644 index 00000000000000..5110ef3a77ff7b --- /dev/null +++ b/playground/css-no-codesplit/__tests__/css-no-codesplit.spec.ts @@ -0,0 +1,17 @@ +import { describe, expect, test } from 'vitest' +import { expectWithRetry, getColor, isBuild, listAssets } from '~utils' + +test('should load all stylesheets', async () => { + expect(await getColor('.shared-linked')).toBe('blue') + await expectWithRetry(() => getColor('.async-js')).toBe('blue') +}) + +describe.runIf(isBuild)('build', () => { + test('should remove empty chunk', async () => { + const assets = listAssets() + expect(assets).not.toContainEqual( + expect.stringMatching(/shared-linked-.*\.js$/), + ) + expect(assets).not.toContainEqual(expect.stringMatching(/async-js-.*\.js$/)) + }) +}) diff --git a/playground/css-no-codesplit/async-js.css b/playground/css-no-codesplit/async-js.css new file mode 100644 index 00000000000000..ed61a7f513c277 --- /dev/null +++ b/playground/css-no-codesplit/async-js.css @@ -0,0 +1,3 @@ +.async-js { + color: blue; +} diff --git a/playground/css-no-codesplit/async-js.js b/playground/css-no-codesplit/async-js.js new file mode 100644 index 00000000000000..2ce31a1e741d2d --- /dev/null +++ b/playground/css-no-codesplit/async-js.js @@ -0,0 +1,2 @@ +// a JS file that becomes an empty file but imports CSS files +import './async-js.css' diff --git a/playground/css-no-codesplit/index.html b/playground/css-no-codesplit/index.html new file mode 100644 index 00000000000000..e7673c84e45933 --- /dev/null +++ b/playground/css-no-codesplit/index.html @@ -0,0 +1,5 @@ + + + + +async JS importing CSS: this should be blue
diff --git a/playground/css-no-codesplit/index.js b/playground/css-no-codesplit/index.js new file mode 100644 index 00000000000000..44b33fda36a9cd --- /dev/null +++ b/playground/css-no-codesplit/index.js @@ -0,0 +1 @@ +import('./async-js') diff --git a/playground/css-no-codesplit/package.json b/playground/css-no-codesplit/package.json new file mode 100644 index 00000000000000..61d806d3d264fa --- /dev/null +++ b/playground/css-no-codesplit/package.json @@ -0,0 +1,12 @@ +{ + "name": "@vitejs/test-css-no-codesplit", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../packages/vite/bin/vite", + "preview": "vite preview" + } +} diff --git a/playground/css-no-codesplit/shared-linked.css b/playground/css-no-codesplit/shared-linked.css new file mode 100644 index 00000000000000..51857a50efca1f --- /dev/null +++ b/playground/css-no-codesplit/shared-linked.css @@ -0,0 +1,3 @@ +.shared-linked { + color: blue; +} diff --git a/playground/css-no-codesplit/sub.html b/playground/css-no-codesplit/sub.html new file mode 100644 index 00000000000000..f535a771d06482 --- /dev/null +++ b/playground/css-no-codesplit/sub.html @@ -0,0 +1 @@ + diff --git a/playground/css-no-codesplit/vite.config.js b/playground/css-no-codesplit/vite.config.js new file mode 100644 index 00000000000000..f48d875832b928 --- /dev/null +++ b/playground/css-no-codesplit/vite.config.js @@ -0,0 +1,14 @@ +import { resolve } from 'node:path' +import { defineConfig } from 'vite' + +export default defineConfig({ + build: { + cssCodeSplit: false, + rollupOptions: { + input: { + index: resolve(__dirname, './index.html'), + sub: resolve(__dirname, './sub.html'), + }, + }, + }, +}) diff --git a/playground/css-sourcemap/package.json b/playground/css-sourcemap/package.json index ea2339b12694ba..11c26f182ae79d 100644 --- a/playground/css-sourcemap/package.json +++ b/playground/css-sourcemap/package.json @@ -12,7 +12,7 @@ "devDependencies": { "less": "^4.2.0", "magic-string": "^0.30.10", - "sass": "^1.76.0", + "sass": "^1.77.2", "stylus": "^0.63.0", "sugarss": "^4.0.1" } diff --git a/playground/css/__tests__/css.spec.ts b/playground/css/__tests__/css.spec.ts index c0efb130bf00f9..cb7af939bbd152 100644 --- a/playground/css/__tests__/css.spec.ts +++ b/playground/css/__tests__/css.spec.ts @@ -448,6 +448,16 @@ test('?raw', async () => { expect(await rawImportCss.textContent()).toBe( readFileSync(require.resolve('../raw-imported.css'), 'utf-8'), ) + + if (!isBuild) { + editFile('raw-imported.css', (code) => + code.replace('color: yellow', 'color: blue'), + ) + await untilUpdated( + () => page.textContent('.raw-imported-css'), + 'color: blue', + ) + } }) test('import css in less', async () => { diff --git a/playground/css/package.json b/playground/css/package.json index 3ac1f1dce0851c..ef7a2eb0688474 100644 --- a/playground/css/package.json +++ b/playground/css/package.json @@ -24,7 +24,7 @@ "fast-glob": "^3.3.2", "less": "^4.2.0", "postcss-nested": "^6.0.1", - "sass": "^1.76.0", + "sass": "^1.77.2", "stylus": "^0.63.0", "sugarss": "^4.0.1" }, diff --git a/playground/extensions/package.json b/playground/extensions/package.json index 389d7687c2732e..68cb75360d3840 100644 --- a/playground/extensions/package.json +++ b/playground/extensions/package.json @@ -10,6 +10,6 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.4.26" + "vue": "^3.4.27" } } diff --git a/playground/external/dep-that-imports/package.json b/playground/external/dep-that-imports/package.json index 9f7d742dae0653..bae6b993a48c61 100644 --- a/playground/external/dep-that-imports/package.json +++ b/playground/external/dep-that-imports/package.json @@ -5,6 +5,6 @@ "dependencies": { "slash3": "npm:slash@^3.0.0", "slash5": "npm:slash@^5.1.0", - "vue": "^3.4.26" + "vue": "^3.4.27" } } diff --git a/playground/external/dep-that-requires/package.json b/playground/external/dep-that-requires/package.json index a066f80d568aba..7c56ad60573d2e 100644 --- a/playground/external/dep-that-requires/package.json +++ b/playground/external/dep-that-requires/package.json @@ -5,6 +5,6 @@ "dependencies": { "slash3": "npm:slash@^3.0.0", "slash5": "npm:slash@^5.1.0", - "vue": "^3.4.26" + "vue": "^3.4.27" } } diff --git a/playground/external/package.json b/playground/external/package.json index cb20a8e129fb65..934e0dc6ca0202 100644 --- a/playground/external/package.json +++ b/playground/external/package.json @@ -17,7 +17,7 @@ "slash3": "npm:slash@^3.0.0", "slash5": "npm:slash@^5.1.0", "vite": "workspace:*", - "vue": "^3.4.26", + "vue": "^3.4.27", "vue32": "npm:vue@~3.2.0" } } diff --git a/playground/hasWindowsUnicodeFsBug.js b/playground/hasWindowsUnicodeFsBug.js deleted file mode 100644 index c46dd2a5545392..00000000000000 --- a/playground/hasWindowsUnicodeFsBug.js +++ /dev/null @@ -1,10 +0,0 @@ -import os from 'node:os' - -const isWindows = os.platform() === 'win32' -const nodeVersionArray = process.versions.node.split('.') -// ignore some files due to https://github.com/nodejs/node/issues/48673 -// node <=21.0.0 and ^20.4.0 has the bug -export const hasWindowsUnicodeFsBug = - isWindows && - (+nodeVersionArray[0] > 20 || - (+nodeVersionArray[0] === 20 && +nodeVersionArray[1] >= 4)) diff --git a/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts b/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts index 1f6c3385d1702b..c3b3f4410c8ae8 100644 --- a/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts +++ b/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts @@ -253,7 +253,7 @@ describe('hmr works correctly', () => { }) // TODO - // test.skipIf(hasWindowsUnicodeFsBug)('full-reload encodeURI path', async () => { + // test('full-reload encodeURI path', async () => { // await page.goto( // viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', // ) diff --git a/playground/hmr/__tests__/hmr.spec.ts b/playground/hmr/__tests__/hmr.spec.ts index 27590bd6022bd0..d4281ec1bbe5ae 100644 --- a/playground/hmr/__tests__/hmr.spec.ts +++ b/playground/hmr/__tests__/hmr.spec.ts @@ -1,6 +1,5 @@ import { beforeAll, describe, expect, it, test } from 'vitest' import type { Page } from 'playwright-chromium' -import { hasWindowsUnicodeFsBug } from '../../hasWindowsUnicodeFsBug' import { addFile, browser, @@ -155,7 +154,7 @@ if (!isBuild) { }) test('invalidate', async () => { - const el = await page.$('.invalidation') + const el = await page.$('.invalidation-parent') await untilBrowserLogAfter( () => editFile('invalidation/child.js', (code) => @@ -183,7 +182,7 @@ if (!isBuild) { page2 = await browser.newPage() await page2.goto(viteTestUrl) - const el = await page.$('.invalidation') + const el = await page.$('.invalidation-parent') await untilBrowserLogAfter( () => editFile('invalidation/child.js', (code) => @@ -209,6 +208,15 @@ if (!isBuild) { } }) + test('invalidate on root triggers page reload', async () => { + editFile('invalidation/root.js', (code) => code.replace('Init', 'Updated')) + await page.waitForEvent('load') + await untilUpdated( + async () => (await page.$('.invalidation-root')).textContent(), + 'Updated', + ) + }) + test('soft invalidate', async () => { const el = await page.$('.soft-invalidation') expect(await el.textContent()).toBe( @@ -253,24 +261,21 @@ if (!isBuild) { await untilUpdated(() => el.textContent(), '3') }) - test.skipIf(hasWindowsUnicodeFsBug)( - 'full-reload encodeURI path', - async () => { - await page.goto( - viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', - ) - const el = await page.$('#app') - expect(await el.textContent()).toBe('title') - editFile('unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', (code) => - code.replace('title', 'title2'), - ) - await page.waitForEvent('load') - await untilUpdated( - async () => (await page.$('#app')).textContent(), - 'title2', - ) - }, - ) + test('full-reload encodeURI path', async () => { + await page.goto( + viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', + ) + const el = await page.$('#app') + expect(await el.textContent()).toBe('title') + editFile('unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', (code) => + code.replace('title', 'title2'), + ) + await page.waitForEvent('load') + await untilUpdated( + async () => (await page.$('#app')).textContent(), + 'title2', + ) + }) test('CSS update preserves query params', async () => { await page.goto(viteTestUrl) @@ -833,13 +838,17 @@ if (!isBuild) { 'parent:not-child', ) - addFile(childFile, originalChildFileCode) - editFile(parentFile, (code) => - code.replace( - "export const childValue = 'not-child'", - "export { value as childValue } from './child'", - ), - ) + await untilBrowserLogAfter(async () => { + const loadPromise = page.waitForEvent('load') + addFile(childFile, originalChildFileCode) + editFile(parentFile, (code) => + code.replace( + "export const childValue = 'not-child'", + "export { value as childValue } from './child'", + ), + ) + await loadPromise + }, [/connected/]) await untilUpdated( () => page.textContent('.file-delete-restore'), 'parent:child', diff --git a/playground/hmr/hmr.ts b/playground/hmr/hmr.ts index 5e572f83b703aa..1f764da0861d6f 100644 --- a/playground/hmr/hmr.ts +++ b/playground/hmr/hmr.ts @@ -1,7 +1,6 @@ import { virtual } from 'virtual:file' import { foo as depFoo, nestedFoo } from './hmrDep' import './importing-updated' -import './invalidation/parent' import './file-delete-restore' import './optional-chaining/parent' import './intermediate-file-delete' diff --git a/playground/hmr/index.html b/playground/hmr/index.html index 221a3bf39e1705..d5adaab6bd5629 100644 --- a/playground/hmr/index.html +++ b/playground/hmr/index.html @@ -7,6 +7,7 @@ +