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` to infer the payload type for event `T`. For more information on how this interface is utilized, refer to the [HMR API Documentation](./api-hmr#hmr-api). + +```ts twoslash +import 'vite/client' +import type { InferCustomEventPayload } from 'vite/types/customEvent.d.ts' +declare module 'vite/types/customEvent.d.ts' { + interface CustomEventMap { + 'custom:foo': { msg: string } + } +} +// ---cut--- +type CustomFooPayload = InferCustomEventPayload<'custom:foo'> +import.meta.hot?.on('custom:foo', (payload) => { + // The type of payload will be { msg: string } +}) +import.meta.hot?.on('unknown:event', (payload) => { + // The type of payload will be any +}) +``` diff --git a/docs/guide/backend-integration.md b/docs/guide/backend-integration.md index 4f6de439afeae9..8509082bbdf2ea 100644 --- a/docs/guide/backend-integration.md +++ b/docs/guide/backend-integration.md @@ -62,24 +62,36 @@ If you need a custom integration, you can follow the steps in this guide to conf ```json { - "main.js": { - "file": "assets/main.4889e940.js", - "src": "main.js", + "_shared-!~{003}~.js": { + "file": "assets/shared-ChJ_j-JJ.css", + "src": "_shared-!~{003}~.js" + }, + "_shared-B7PI925R.js": { + "file": "assets/shared-B7PI925R.js", + "name": "shared", + "css": ["assets/shared-ChJ_j-JJ.css"] + }, + "baz.js": { + "file": "assets/baz-B2H3sXNv.js", + "name": "baz", + "src": "baz.js", + "isDynamicEntry": true + }, + "views/bar.js": { + "file": "assets/bar-gkvgaI9m.js", + "name": "bar", + "src": "views/bar.js", "isEntry": true, - "dynamicImports": ["views/foo.js"], - "css": ["assets/main.b82dbe22.css"], - "assets": ["assets/asset.0ab0f9cd.png"], - "imports": ["_shared.83069a53.js"] + "imports": ["_shared-B7PI925R.js"], + "dynamicImports": ["baz.js"] }, "views/foo.js": { - "file": "assets/foo.869aea0d.js", + "file": "assets/foo-BRBmoGS9.js", + "name": "foo", "src": "views/foo.js", - "isDynamicEntry": true, - "imports": ["_shared.83069a53.js"] - }, - "_shared.83069a53.js": { - "file": "assets/shared.83069a53.js", - "css": ["assets/shared.a834bfc3.css"] + "isEntry": true, + "imports": ["_shared-B7PI925R.js"], + "css": ["assets/foo-5UjPuW-k.css"] } } ``` @@ -122,21 +134,21 @@ If you need a custom integration, you can follow the steps in this guide to conf - Optionally, `` tag for the `file` of each imported JavaScript chunk, again recursively following the imports starting from the entry point chunk. - Following the above example manifest, for the entry point `main.js` the following tags should be included in production: + Following the above example manifest, for the entry point `views/foo.js` the following tags should be included in production: ```html - - - + + + - + ``` - While the following should be included for the entry point `views/foo.js`: + While the following should be included for the entry point `views/bar.js`: ```html - - + + - + ``` diff --git a/docs/guide/build.md b/docs/guide/build.md index cb4a8eef6cd583..50abd7c91cea56 100644 --- a/docs/guide/build.md +++ b/docs/guide/build.md @@ -238,9 +238,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`. - ```ts twoslash import type { UserConfig } from 'vite' +// prettier-ignore const config: UserConfig = { // ---cut-before--- experimental: { @@ -255,14 +255,13 @@ experimental: { // ---cut-after--- } ``` - 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. - ```ts twoslash import type { UserConfig } from 'vite' import path from 'node:path' +// prettier-ignore const config: UserConfig = { // ---cut-before--- experimental: { @@ -279,6 +278,5 @@ experimental: { // ---cut-after--- } ``` - Note that the `filename` passed is a decoded URL, and if the function returns a URL string, it should also be decoded. Vite will handle the encoding automatically when rendering the URLs. If an object with `runtime` is returned, encoding should be handled yourself where needed as the runtime code will be rendered as is. diff --git a/docs/package.json b/docs/package.json index d4b078ee99d5c3..8af0297a7b4061 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,9 +8,9 @@ "docs-serve": "vitepress serve" }, "devDependencies": { - "@shikijs/vitepress-twoslash": "^1.4.0", + "@shikijs/vitepress-twoslash": "^1.6.0", "@types/express": "^4.17.21", - "vitepress": "1.1.4", - "vue": "^3.4.26" + "vitepress": "1.2.0", + "vue": "^3.4.27" } } diff --git a/package.json b/package.json index 03c76f9052012a..d9095b142e8f50 100644 --- a/package.json +++ b/package.json @@ -53,38 +53,38 @@ "@types/fs-extra": "^11.0.4", "@types/less": "^3.0.6", "@types/micromatch": "^4.0.7", - "@types/node": "^20.12.7", + "@types/node": "^20.12.12", "@types/picomatch": "^2.3.3", "@types/semver": "^7.5.8", "@types/stylus": "^0.48.42", "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", + "@typescript-eslint/eslint-plugin": "^7.9.0", + "@typescript-eslint/parser": "^7.9.0", "@vitejs/release-scripts": "^1.3.1", - "conventional-changelog-cli": "^4.1.0", + "conventional-changelog-cli": "^5.0.0", "eslint": "^8.57.0", "eslint-define-config": "^2.1.0", "eslint-plugin-i": "^2.29.1", - "eslint-plugin-n": "^17.4.0", + "eslint-plugin-n": "^17.7.0", "eslint-plugin-regexp": "^2.5.0", - "execa": "^8.0.1", + "execa": "^9.1.0", "feed": "^4.2.2", "fs-extra": "^11.2.0", "lint-staged": "^15.2.2", - "npm-run-all2": "^6.1.2", - "picocolors": "^1.0.0", - "playwright-chromium": "^1.43.1", + "npm-run-all2": "^6.2.0", + "picocolors": "^1.0.1", + "playwright-chromium": "^1.44.0", "prettier": "3.2.5", - "rimraf": "^5.0.5", + "rimraf": "^5.0.7", "rollup": "^4.13.0", - "semver": "^7.6.0", + "semver": "^7.6.2", "simple-git-hooks": "^2.11.1", "tslib": "^2.6.2", - "tsx": "^4.8.0", + "tsx": "^4.10.5", "typescript": "^5.2.2", "unbuild": "^2.0.0", "vite": "workspace:*", - "vitest": "^1.5.3" + "vitest": "^1.6.0" }, "simple-git-hooks": { "pre-commit": "pnpm exec lint-staged --concurrent false" @@ -122,7 +122,8 @@ }, "patchedDependencies": { "chokidar@3.6.0": "patches/chokidar@3.6.0.patch", - "sirv@2.0.4": "patches/sirv@2.0.4.patch" + "sirv@2.0.4": "patches/sirv@2.0.4.patch", + "http-proxy@1.18.1": "patches/http-proxy@1.18.1.patch" }, "peerDependencyRules": { "allowedVersions": { diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index e34d4e14f6e4cf..4f297032834fcf 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -1,5 +1,5 @@ import { join } from 'node:path' -import type { ExecaSyncReturnValue, SyncOptions } from 'execa' +import type { SyncOptions, SyncResult } from 'execa' import { execaCommandSync } from 'execa' import fs from 'fs-extra' import { afterEach, beforeAll, expect, test } from 'vitest' @@ -9,10 +9,10 @@ const CLI_PATH = join(__dirname, '..') const projectName = 'test-app' const genPath = join(__dirname, projectName) -const run = ( +const run = ( args: string[], - options: SyncOptions = {}, -): ExecaSyncReturnValue => { + options?: SO, +): SyncResult => { return execaCommandSync(`node ${CLI_PATH} ${args.join(' ')}`, options) } diff --git a/packages/create-vite/template-lit-ts/package.json b/packages/create-vite/template-lit-ts/package.json index 19747ca4389ed8..742f963ad98273 100644 --- a/packages/create-vite/template-lit-ts/package.json +++ b/packages/create-vite/template-lit-ts/package.json @@ -13,6 +13,6 @@ }, "devDependencies": { "typescript": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-lit/package.json b/packages/create-vite/template-lit/package.json index ca35b84f62a94d..b34c893b53a7e1 100644 --- a/packages/create-vite/template-lit/package.json +++ b/packages/create-vite/template-lit/package.json @@ -12,6 +12,6 @@ "lit": "^3.1.3" }, "devDependencies": { - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-preact-ts/package.json b/packages/create-vite/template-preact-ts/package.json index a6f5676f3a72bb..1504fe9f117963 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.21.0" + "preact": "^10.22.0" }, "devDependencies": { "@preact/preset-vite": "^2.8.2", "typescript": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-preact/package.json b/packages/create-vite/template-preact/package.json index 02d85c1059f2d2..bffd5f9ced7c9b 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.21.0" + "preact": "^10.22.0" }, "devDependencies": { "@preact/preset-vite": "^2.8.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-qwik-ts/package.json b/packages/create-vite/template-qwik-ts/package.json index b123e7cb52d779..f626c4539c4ed1 100644 --- a/packages/create-vite/template-qwik-ts/package.json +++ b/packages/create-vite/template-qwik-ts/package.json @@ -11,9 +11,9 @@ "devDependencies": { "serve": "^14.2.3", "typescript": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" }, "dependencies": { - "@builder.io/qwik": "^1.5.2" + "@builder.io/qwik": "^1.5.4" } } diff --git a/packages/create-vite/template-qwik/package.json b/packages/create-vite/template-qwik/package.json index d0044eaf162664..9dcad097acfe70 100644 --- a/packages/create-vite/template-qwik/package.json +++ b/packages/create-vite/template-qwik/package.json @@ -10,9 +10,9 @@ }, "devDependencies": { "serve": "^14.2.3", - "vite": "^5.2.10" + "vite": "^5.2.11" }, "dependencies": { - "@builder.io/qwik": "^1.5.2" + "@builder.io/qwik": "^1.5.4" } } diff --git a/packages/create-vite/template-react-ts/package.json b/packages/create-vite/template-react-ts/package.json index 956c8302b2d151..44a1d92a680513 100644 --- a/packages/create-vite/template-react-ts/package.json +++ b/packages/create-vite/template-react-ts/package.json @@ -14,15 +14,15 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@types/react": "^18.3.1", + "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", + "@typescript-eslint/eslint-plugin": "^7.9.0", + "@typescript-eslint/parser": "^7.9.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.6", + "eslint-plugin-react-refresh": "^0.4.7", "typescript": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-react/package.json b/packages/create-vite/template-react/package.json index f55f64c815ff7c..85f4371de10709 100644 --- a/packages/create-vite/template-react/package.json +++ b/packages/create-vite/template-react/package.json @@ -14,13 +14,13 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@types/react": "^18.3.1", + "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.57.0", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.6", - "vite": "^5.2.10" + "eslint-plugin-react-refresh": "^0.4.7", + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-solid-ts/package.json b/packages/create-vite/template-solid-ts/package.json index c725d61ea9fa7e..e77b944d91791c 100644 --- a/packages/create-vite/template-solid-ts/package.json +++ b/packages/create-vite/template-solid-ts/package.json @@ -13,7 +13,7 @@ }, "devDependencies": { "typescript": "^5.2.2", - "vite": "^5.2.10", + "vite": "^5.2.11", "vite-plugin-solid": "^2.10.2" } } diff --git a/packages/create-vite/template-solid/package.json b/packages/create-vite/template-solid/package.json index 5a198703b74b8f..7f907499422cc5 100644 --- a/packages/create-vite/template-solid/package.json +++ b/packages/create-vite/template-solid/package.json @@ -12,7 +12,7 @@ "solid-js": "^1.8.17" }, "devDependencies": { - "vite": "^5.2.10", + "vite": "^5.2.11", "vite-plugin-solid": "^2.10.2" } } diff --git a/packages/create-vite/template-svelte-ts/package.json b/packages/create-vite/template-svelte-ts/package.json index 23b9fd1174ca51..4735ebc10b0b12 100644 --- a/packages/create-vite/template-svelte-ts/package.json +++ b/packages/create-vite/template-svelte-ts/package.json @@ -12,10 +12,10 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.0", "@tsconfig/svelte": "^5.0.4", - "svelte": "^4.2.15", - "svelte-check": "^3.7.0", + "svelte": "^4.2.17", + "svelte-check": "^3.7.1", "tslib": "^2.6.2", "typescript": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-svelte/package.json b/packages/create-vite/template-svelte/package.json index caca02634b9a7f..ea88ea72a28e09 100644 --- a/packages/create-vite/template-svelte/package.json +++ b/packages/create-vite/template-svelte/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.1.0", - "svelte": "^4.2.15", - "vite": "^5.2.10" + "svelte": "^4.2.17", + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-vanilla-ts/package.json b/packages/create-vite/template-vanilla-ts/package.json index 845f7d6ae11045..8b534d057c0b25 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": "^5.2.2", - "vite": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-vanilla/package.json b/packages/create-vite/template-vanilla/package.json index 24c5f0253b7357..40b1479981b3e7 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": "^5.2.10" + "vite": "^5.2.11" } } diff --git a/packages/create-vite/template-vue-ts/package.json b/packages/create-vite/template-vue-ts/package.json index b3704bcc5d64a8..85bab7eb2ea033 100644 --- a/packages/create-vite/template-vue-ts/package.json +++ b/packages/create-vite/template-vue-ts/package.json @@ -9,12 +9,12 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.4.26" + "vue": "^3.4.27" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.4", "typescript": "^5.2.2", - "vite": "^5.2.10", - "vue-tsc": "^2.0.16" + "vite": "^5.2.11", + "vue-tsc": "^2.0.19" } } diff --git a/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue b/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue index 7b25f3f2b6aac3..b58e52b965f6f9 100644 --- a/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue +++ b/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue @@ -24,9 +24,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/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 Set() + const prelimaryNameToChunkMap = new Map( + Object.values(bundle) + .filter((chunk): chunk is OutputChunk => chunk.type === 'chunk') + .map((chunk) => [chunk.preliminaryFileName, chunk]), + ) + + function collect(fileName: string) { + const chunk = bundle[fileName] + if (!chunk || chunk.type !== 'chunk' || collected.has(chunk)) return + collected.add(chunk) + + chunk.imports.forEach(collect) + css += chunkCSSMap.get(chunk.preliminaryFileName) ?? '' + } + + for (const chunkName of chunkCSSMap.keys()) + collect(prelimaryNameToChunkMap.get(chunkName)?.fileName ?? '') + + return css + } + let extractedCss = !hasEmitted && extractCss() + if (extractedCss) { + hasEmitted = true + extractedCss = await finalizeCss(extractedCss, true, config) + this.emitFile({ + name: cssBundleName, + type: 'asset', + source: extractedCss, + }) + } + // remove empty css chunks and their imports if (pureCssChunks.size) { // map each pure css chunk (rendered chunk) to it's corresponding bundle @@ -898,40 +934,6 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { delete bundle[`${fileName}.map`] }) } - - function extractCss() { - let css = '' - const collected = new Set() - const prelimaryNameToChunkMap = new Map( - Object.values(bundle) - .filter((chunk): chunk is OutputChunk => chunk.type === 'chunk') - .map((chunk) => [chunk.preliminaryFileName, chunk]), - ) - - function collect(fileName: string) { - const chunk = bundle[fileName] - if (!chunk || chunk.type !== 'chunk' || collected.has(chunk)) return - collected.add(chunk) - - chunk.imports.forEach(collect) - css += chunkCSSMap.get(chunk.preliminaryFileName) ?? '' - } - - for (const chunkName of chunkCSSMap.keys()) - collect(prelimaryNameToChunkMap.get(chunkName)?.fileName ?? '') - - return css - } - let extractedCss = !hasEmitted && extractCss() - if (extractedCss) { - hasEmitted = true - extractedCss = await finalizeCss(extractedCss, true, config) - this.emitFile({ - name: cssBundleName, - type: 'asset', - source: extractedCss, - }) - } }, } } diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index e65b240940ca21..ff27fce4ca41bd 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -17,6 +17,7 @@ import { CLIENT_PUBLIC_PATH, DEP_VERSION_RE, FS_PREFIX, + SPECIAL_QUERY_RE, } from '../constants' import { debugHmr, @@ -728,7 +729,8 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // update the module graph for HMR analysis. // node CSS imports does its own graph update in the css-analysis plugin so we // only handle js graph updates here. - if (!isCSSRequest(importer)) { + // note that we want to handle .css?raw and .css?url here + if (!isCSSRequest(importer) || SPECIAL_QUERY_RE.test(importer)) { // attached by pluginContainer.addWatchFile const pluginImports = (this as any)._addedImports as | Set diff --git a/packages/vite/src/node/plugins/splitVendorChunk.ts b/packages/vite/src/node/plugins/splitVendorChunk.ts index f75512e9c986c0..39a50a02dbf28f 100644 --- a/packages/vite/src/node/plugins/splitVendorChunk.ts +++ b/packages/vite/src/node/plugins/splitVendorChunk.ts @@ -27,7 +27,7 @@ export const isCSSRequest = (request: string): boolean => // Don't use this manualChunks strategy for ssr, lib mode, and 'umd' or 'iife' /** - * @deprecated use build.rollupOutput.manualChunks or framework specific configuration + * @deprecated use build.rollupOptions.output.manualChunks or framework specific configuration */ export class SplitVendorChunkCache { cache: Map @@ -40,7 +40,7 @@ export class SplitVendorChunkCache { } /** - * @deprecated use build.rollupOutput.manualChunks or framework specific configuration + * @deprecated use build.rollupOptions.output.manualChunks or framework specific configuration */ export function splitVendorChunk( options: { cache?: SplitVendorChunkCache } = {}, @@ -94,7 +94,7 @@ function staticImportedByEntry( } /** - * @deprecated use build.rollupOutput.manualChunks or framework specific configuration + * @deprecated use build.rollupOptions.output.manualChunks or framework specific configuration */ export function splitVendorChunkPlugin(): Plugin { const caches: SplitVendorChunkCache[] = [] diff --git a/packages/vite/src/node/plugins/wasm.ts b/packages/vite/src/node/plugins/wasm.ts index 22ab2ab00eade4..d3e9c272c89b50 100644 --- a/packages/vite/src/node/plugins/wasm.ts +++ b/packages/vite/src/node/plugins/wasm.ts @@ -29,6 +29,7 @@ const wasmHelper = async (opts = {}, url: string) => { // correct MIME type for .wasm files, which unfortunately doesn't work for // a lot of static file servers, so we just work around it by getting the // raw buffer. + // eslint-disable-next-line n/no-unsupported-features/node-builtins -- this function runs in browsers const response = await fetch(url) const contentType = response.headers.get('Content-Type') || '' if ( diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index 4b0d7246493282..7c6a64e87769a8 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -355,7 +355,8 @@ export function updateModules( const updates: Update[] = [] const invalidatedModules = new Set() const traversedModules = new Set() - let needFullReload: HasDeadEnd = false + // Modules could be empty if a root module is invalidated via import.meta.hot.invalidate() + let needFullReload: HasDeadEnd = modules.length === 0 for (const mod of modules) { const boundaries: PropagationBoundary[] = [] diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index 741ae4331ade22..684dff128e597d 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -4,6 +4,7 @@ import convertSourceMap from 'convert-source-map' import type { ExistingRawSourceMap, SourceMap } from 'rollup' import type { Logger } from '../logger' import { blankReplacer, createDebugger } from '../utils' +import { cleanUrl } from '../../shared/utils' const debug = createDebugger('vite:sourcemap', { onlyWhenFocused: true, @@ -53,7 +54,7 @@ export async function injectSourcesContent( // inject content from source file when sourcesContent is null sourceRootPromise ??= computeSourceRoute(map, file) const sourceRoot = await sourceRootPromise - let resolvedSourcePath = decodeURI(sourcePath) + let resolvedSourcePath = cleanUrl(decodeURI(sourcePath)) if (sourceRoot) { resolvedSourcePath = path.resolve(sourceRoot, resolvedSourcePath) } diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 3c16b01a1fcba8..b398ee9d74e969 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -434,7 +434,7 @@ export function isFilePathESM( } } -const splitRE = /\r?\n/ +export const splitRE = /\r?\n/g const range: number = 2 diff --git a/patches/http-proxy@1.18.1.patch b/patches/http-proxy@1.18.1.patch new file mode 100644 index 00000000000000..04e179137026a3 --- /dev/null +++ b/patches/http-proxy@1.18.1.patch @@ -0,0 +1,46 @@ +diff --git a/lib/http-proxy/common.js b/lib/http-proxy/common.js +index 6513e81d80d5250ea249ea833f819ece67897c7e..486d4c896d65a3bb7cf63307af68facb3ddb886b 100644 +--- a/lib/http-proxy/common.js ++++ b/lib/http-proxy/common.js +@@ -1,6 +1,5 @@ + var common = exports, + url = require('url'), +- extend = require('util')._extend, + required = require('requires-port'); + + var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, +@@ -40,10 +39,10 @@ common.setupOutgoing = function(outgoing, options, req, forward) { + ); + + outgoing.method = options.method || req.method; +- outgoing.headers = extend({}, req.headers); ++ outgoing.headers = Object.assign({}, req.headers); + + if (options.headers){ +- extend(outgoing.headers, options.headers); ++ Object.assign(outgoing.headers, options.headers); + } + + if (options.auth) { +diff --git a/lib/http-proxy/index.js b/lib/http-proxy/index.js +index 977a4b3622b9eaac27689f06347ea4c5173a96cd..88b2d0fcfa03c3aafa47c7e6d38e64412c45a7cc 100644 +--- a/lib/http-proxy/index.js ++++ b/lib/http-proxy/index.js +@@ -1,5 +1,4 @@ + var httpProxy = module.exports, +- extend = require('util')._extend, + parse_url = require('url').parse, + EE3 = require('eventemitter3'), + http = require('http'), +@@ -47,9 +46,9 @@ function createRightProxy(type) { + args[cntr] !== res + ) { + //Copy global options +- requestOptions = extend({}, options); ++ requestOptions = Object.assign({}, options); + //Overwrite with request options +- extend(requestOptions, args[cntr]); ++ Object.assign(requestOptions, args[cntr]); + + cntr--; + } diff --git a/playground/alias/package.json b/playground/alias/package.json index 847af2a4fe8938..692d2a3af3ea44 100644 --- a/playground/alias/package.json +++ b/playground/alias/package.json @@ -11,8 +11,8 @@ }, "dependencies": { "aliased-module": "file:./dir/module", - "vue": "^3.4.26", - "@vue/shared": "^3.4.26" + "vue": "^3.4.27", + "@vue/shared": "^3.4.27" }, "devDependencies": { "@vitejs/test-resolve-linked": "workspace:*" diff --git a/playground/backend-integration/package.json b/playground/backend-integration/package.json index 57c24fba596bb2..34231efc1f63f1 100644 --- a/playground/backend-integration/package.json +++ b/playground/backend-integration/package.json @@ -10,7 +10,7 @@ "preview": "vite preview" }, "devDependencies": { - "sass": "^1.76.0", + "sass": "^1.77.2", "tailwindcss": "^3.4.3", "fast-glob": "^3.3.2" } diff --git a/playground/cli-module/__tests__/serve.ts b/playground/cli-module/__tests__/serve.ts index 4a76a6f810b3a9..b19bdb62701a7d 100644 --- a/playground/cli-module/__tests__/serve.ts +++ b/playground/cli-module/__tests__/serve.ts @@ -70,6 +70,7 @@ export async function serve() { const serverProcess = execaCommand(serverCommand, { cwd: rootDir, stdio: 'pipe', + forceKillAfterDelay: 3000, }) collectStreams('server', serverProcess) diff --git a/playground/cli/__tests__/serve.ts b/playground/cli/__tests__/serve.ts index 7cf2eca021ef1d..5da61aec991109 100644 --- a/playground/cli/__tests__/serve.ts +++ b/playground/cli/__tests__/serve.ts @@ -73,6 +73,7 @@ export async function serve() { const serverProcess = execaCommand(serverCommand, { cwd: rootDir, stdio: 'pipe', + forceKillAfterDelay: 3000, }) collectStreams('server', serverProcess) diff --git a/playground/config/packages/siblings/package.json b/playground/config/packages/siblings/package.json index 049019bd1abfd7..ecba583cc41808 100644 --- a/playground/config/packages/siblings/package.json +++ b/playground/config/packages/siblings/package.json @@ -2,7 +2,7 @@ "name": "@vite/test-config-sibling", "type": "module", "devDependencies": { - "@types/lodash": "^4.17.0", + "@types/lodash": "^4.17.4", "lodash": "^4.17.21" } } diff --git a/playground/css-codesplit/__tests__/css-codesplit.spec.ts b/playground/css-codesplit/__tests__/css-codesplit.spec.ts index 2f7d5ab5fc5fba..cc54d865a6795e 100644 --- a/playground/css-codesplit/__tests__/css-codesplit.spec.ts +++ b/playground/css-codesplit/__tests__/css-codesplit.spec.ts @@ -3,6 +3,7 @@ import { findAssetFile, getColor, isBuild, + listAssets, page, readManifest, untilUpdated, @@ -12,6 +13,7 @@ test('should load all stylesheets', async () => { expect(await getColor('h1')).toBe('red') expect(await getColor('h2')).toBe('blue') expect(await getColor('.dynamic')).toBe('green') + expect(await getColor('.async-js')).toBe('blue') expect(await getColor('.chunk')).toBe('magenta') }) @@ -40,7 +42,12 @@ describe.runIf(isBuild)('build', () => { expect(findAssetFile(/style-.*\.js$/)).toBe('') expect(findAssetFile('main.*.js$')).toMatch(`/* empty css`) expect(findAssetFile('other.*.js$')).toMatch(`/* empty css`) - expect(findAssetFile(/async.*\.js$/)).toBe('') + expect(findAssetFile(/async-[-\w]{8}\.js$/)).toBe('') + + const assets = listAssets() + expect(assets).not.toContainEqual( + expect.stringMatching(/async-js-[-\w]{8}\.js$/), + ) }) test('should remove empty chunk, HTML without JS', async () => { diff --git a/playground/css-codesplit/async-js.css b/playground/css-codesplit/async-js.css new file mode 100644 index 00000000000000..ed61a7f513c277 --- /dev/null +++ b/playground/css-codesplit/async-js.css @@ -0,0 +1,3 @@ +.async-js { + color: blue; +} diff --git a/playground/css-codesplit/async-js.js b/playground/css-codesplit/async-js.js new file mode 100644 index 00000000000000..2ce31a1e741d2d --- /dev/null +++ b/playground/css-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-codesplit/index.html b/playground/css-codesplit/index.html index 7d2a4991f20e0a..38885fa7ccb5ed 100644 --- a/playground/css-codesplit/index.html +++ b/playground/css-codesplit/index.html @@ -2,6 +2,7 @@

This should be red

This should be blue

This 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 @@ + + + +

shared linked: this should be blue

+

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 @@ +