diff --git a/docs/config/build-options.md b/docs/config/build-options.md index 9bff0380a6a02c..891b2e958a9db6 100644 --- a/docs/config/build-options.md +++ b/docs/config/build-options.md @@ -130,7 +130,7 @@ In this case, you need to set `build.cssTarget` to `chrome61` to prevent vite fr ## build.cssMinify - **Type:** `boolean | 'esbuild' | 'lightningcss'` -- **Default:** the same as [`build.minify`](#build-minify) +- **Default:** the same as [`build.minify`](#build-minify) for client, `'esbuild'` for SSR This option allows users to override CSS minification specifically instead of defaulting to `build.minify`, so you can configure minification for JS and CSS separately. Vite uses `esbuild` by default to minify CSS. Set the option to `'lightningcss'` to use [Lightning CSS](https://lightningcss.dev/minification.html) instead. If selected, it can be configured using [`css.lightningcss`](./shared-options.md#css-lightningcss). diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index 3502d31a26ffb2..0ea4aeeb63bcd9 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -217,7 +217,7 @@ Inline PostCSS config or a custom directory to search PostCSS config from (defau For inline PostCSS config, it expects the same format as `postcss.config.js`. But for `plugins` property, only [array format](https://github.com/postcss/postcss-load-config/blob/main/README.md#array) can be used. -The search is done using [postcss-load-config](https://github.com/postcss/postcss-load-config) and only the supported config file names are loaded. +The search is done using [postcss-load-config](https://github.com/postcss/postcss-load-config) and only the supported config file names are loaded. Config files outside the workspace root (or the [project root](/guide/#index-html-and-project-root) if no workspace is found) are not searched by default. You can specify a custom path outside of the root to load the specific config file instead if needed. Note if an inline config is provided, Vite will not search for other PostCSS config sources. @@ -345,12 +345,12 @@ Whether to support named imports from `.json` files. ## json.stringify -- **Type:** `boolean` -- **Default:** `false` +- **Type:** `boolean | 'auto'` +- **Default:** `'auto'` If set to `true`, imported JSON will be transformed into `export default JSON.parse("...")` which is significantly more performant than Object literals, especially when the JSON file is large. -Enabling this disables named imports. +If set to `'auto'`, the data will be stringified only if [the data is bigger than 10kB](https://v8.dev/blog/cost-of-javascript-2019#json:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger). ## esbuild diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index 5a883c75e274cf..c0a7a3d508fa33 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -128,8 +128,8 @@ interface ViteDevServer { */ moduleGraph: ModuleGraph /** - * The resolved urls Vite prints on the CLI. null in middleware mode or - * before `server.listen` is called. + * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null` + * in middleware mode or if the server is not listening on any port. */ resolvedUrls: ResolvedServerUrls | null /** @@ -274,8 +274,8 @@ interface PreviewServer { */ httpServer: http.Server /** - * The resolved urls Vite prints on the CLI. - * null before server is listening. + * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null` + * if the server is not listening on any port. */ resolvedUrls: ResolvedServerUrls | null /** diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 003b31f4b4cd3b..f4c11d580c9164 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -10,6 +10,27 @@ Some internal APIs have been removed due to changes in Vite's implementation. If The experimental Vite Runtime API evolved into the Module Runner API, released in Vite 6 as part of the new experimental [Environment API](/guide/api-environment). Given that the feature was experimental the removal of the previous API introduced in Vite 5.1 isn't a breaking change, but users will need to update their use to the Module Runner equivalent as part of migrating to Vite 6. +## General Changes + +### JSON stringify + +In Vite 5, when [`json.stringify: true`](/config/shared-options#json-stringify) is set, [`json.namedExports`](/config/shared-options#json-namedexports) was disabled. + +From Vite 6, even when `json.stringify: true` is set, `json.namedExports` is not disabled and the value is respected. If you wish to achieve the previous behavior, you can set `json.namedExports: false`. + +Vite 6 also introduces a new default value for `json.stringify` which is `'auto'`, which will only stringify large JSON files. To disable this behavior, set `json.stringify: false`. + +## Advanced + +There are other breaking changes which only affect few users. + +- [[#15637] fix!: default `build.cssMinify` to `'esbuild'` for SSR](https://github.com/vitejs/vite/pull/15637) + - [`build.cssMinify`](/config/build-options#build-cssminify) is now enabled by default even for SSR builds. +- [[#18209] refactor!: bump minimal terser version to 5.16.0](https://github.com/vitejs/vite/pull/18209) + - Minimal supported terser version for [`build.minify: 'terser'`](/config/build-options#build-minify) was bumped to 5.16.0 from 5.4.0. +- [[#18243] chore(deps)!: migrate `fast-glob` to `tinyglobby`](https://github.com/vitejs/vite/pull/18243) + - Range braces (`{01..03}` ⇒ `['01', '02', '03']`) and incremental braces (`{2..8..2}` ⇒ `['2', '4', '6', '8']`) are no longer supported in globs. + ## Migration from v4 Check the [Migration from v4 Guide](https://v5.vite.dev/guide/migration.html) in the Vite v5 docs first to see the needed changes to port your app to Vite 5, and then proceed with the changes on this page. diff --git a/package.json b/package.json index a48ecc09c66669..921cf3d0aa0fc9 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "playwright-chromium": "^1.48.1", "prettier": "3.3.3", "rimraf": "^5.0.10", - "rollup": "^4.22.5", + "rollup": "^4.23.0", "rollup-plugin-esbuild": "^6.1.1", "simple-git-hooks": "^2.11.1", "tslib": "^2.8.0", diff --git a/packages/create-vite/template-preact-ts/tsconfig.app.json b/packages/create-vite/template-preact-ts/tsconfig.app.json index 634dfa3cfcf6de..00a7cc1e9e6de0 100644 --- a/packages/create-vite/template-preact-ts/tsconfig.app.json +++ b/packages/create-vite/template-preact-ts/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", diff --git a/packages/create-vite/template-preact-ts/tsconfig.node.json b/packages/create-vite/template-preact-ts/tsconfig.node.json index 9dad70185e2dda..abcd7f0dacddc7 100644 --- a/packages/create-vite/template-preact-ts/tsconfig.node.json +++ b/packages/create-vite/template-preact-ts/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", diff --git a/packages/create-vite/template-qwik-ts/tsconfig.app.json b/packages/create-vite/template-qwik-ts/tsconfig.app.json index 0052c0d84a6c61..0d65579a463d96 100644 --- a/packages/create-vite/template-qwik-ts/tsconfig.app.json +++ b/packages/create-vite/template-qwik-ts/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", diff --git a/packages/create-vite/template-qwik-ts/tsconfig.node.json b/packages/create-vite/template-qwik-ts/tsconfig.node.json index 9dad70185e2dda..abcd7f0dacddc7 100644 --- a/packages/create-vite/template-qwik-ts/tsconfig.node.json +++ b/packages/create-vite/template-qwik-ts/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", diff --git a/packages/create-vite/template-react-ts/tsconfig.app.json b/packages/create-vite/template-react-ts/tsconfig.app.json index 5a2def4b7a3dd0..f867de0dd1a838 100644 --- a/packages/create-vite/template-react-ts/tsconfig.app.json +++ b/packages/create-vite/template-react-ts/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], diff --git a/packages/create-vite/template-react-ts/tsconfig.node.json b/packages/create-vite/template-react-ts/tsconfig.node.json index 9dad70185e2dda..abcd7f0dacddc7 100644 --- a/packages/create-vite/template-react-ts/tsconfig.node.json +++ b/packages/create-vite/template-react-ts/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", diff --git a/packages/create-vite/template-solid-ts/tsconfig.app.json b/packages/create-vite/template-solid-ts/tsconfig.app.json index c6ab232ad54098..c811fcbb39008c 100644 --- a/packages/create-vite/template-solid-ts/tsconfig.app.json +++ b/packages/create-vite/template-solid-ts/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", diff --git a/packages/create-vite/template-solid-ts/tsconfig.node.json b/packages/create-vite/template-solid-ts/tsconfig.node.json index 9dad70185e2dda..abcd7f0dacddc7 100644 --- a/packages/create-vite/template-solid-ts/tsconfig.node.json +++ b/packages/create-vite/template-solid-ts/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", diff --git a/packages/create-vite/template-vue-ts/tsconfig.app.json b/packages/create-vite/template-vue-ts/tsconfig.app.json index 909eec5c6cf9c4..cb88a5a6c26b25 100644 --- a/packages/create-vite/template-vue-ts/tsconfig.app.json +++ b/packages/create-vite/template-vue-ts/tsconfig.app.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", diff --git a/packages/create-vite/template-vue-ts/tsconfig.node.json b/packages/create-vite/template-vue-ts/tsconfig.node.json index 9dad70185e2dda..abcd7f0dacddc7 100644 --- a/packages/create-vite/template-vue-ts/tsconfig.node.json +++ b/packages/create-vite/template-vue-ts/tsconfig.node.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index ea6d5e972ddfec..c3b64519f5e956 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,19 @@ +## 6.0.0-beta.5 (2024-10-24) + +* fix: add typing to `CSSOptions.preprocessorOptions` (#18001) ([7eeb6f2](https://github.com/vitejs/vite/commit/7eeb6f2f97abf5dfc71c225b9cff9779baf2ed2f)), closes [#18001](https://github.com/vitejs/vite/issues/18001) +* fix(dev): prevent double URL encoding in server.open on macOS (#18443) ([56b7176](https://github.com/vitejs/vite/commit/56b71768f3ee498962fba898804086299382bb59)), closes [#18443](https://github.com/vitejs/vite/issues/18443) +* fix(preview): set resolvedUrls null after close (#18445) ([65014a3](https://github.com/vitejs/vite/commit/65014a32ef618619c5a34b729d67340d9253bdd5)), closes [#18445](https://github.com/vitejs/vite/issues/18445) +* fix(ssr): inject identity function at the top (#18449) ([0ab20a3](https://github.com/vitejs/vite/commit/0ab20a3ee26eacf302415b3087732497d0a2f358)), closes [#18449](https://github.com/vitejs/vite/issues/18449) +* fix(ssr): preserve source maps for hoisted imports (fix #16355) (#16356) ([8e382a6](https://github.com/vitejs/vite/commit/8e382a6a1fed2cd41051b81f9cd9c94b484352a5)), closes [#16355](https://github.com/vitejs/vite/issues/16355) [#16356](https://github.com/vitejs/vite/issues/16356) +* feat(css)!: load postcss config within workspace root only (#18440) ([d23a493](https://github.com/vitejs/vite/commit/d23a493cc4b54a2e2b2c1337b3b1f0c9b1be311e)), closes [#18440](https://github.com/vitejs/vite/issues/18440) +* feat(json)!: add `json.stringify: 'auto'` and make that the default (#18303) ([b80daa7](https://github.com/vitejs/vite/commit/b80daa7c0970645dca569d572892648f66c6799c)), closes [#18303](https://github.com/vitejs/vite/issues/18303) +* fix!: default `build.cssMinify` to `'esbuild'` for SSR (#15637) ([f1d3bf7](https://github.com/vitejs/vite/commit/f1d3bf74cc7f12e759442fd7111d07e2c0262a67)), closes [#15637](https://github.com/vitejs/vite/issues/15637) +* refactor: use `originalFileNames`/`names` (#18240) ([f2957c8](https://github.com/vitejs/vite/commit/f2957c84f69c14c882809889fbd0fc66b97ca3e9)), closes [#18240](https://github.com/vitejs/vite/issues/18240) +* test: fix test conflict (#18446) ([94cd1e6](https://github.com/vitejs/vite/commit/94cd1e6f95e2434d2b52b5c16d50fe0472214634)), closes [#18446](https://github.com/vitejs/vite/issues/18446) +* chore(deps): update dependency picomatch to v4 (#15876) ([3774881](https://github.com/vitejs/vite/commit/377488178a7ef372d9b76526bb01fd60b97f51df)), closes [#15876](https://github.com/vitejs/vite/issues/15876) + + + ## 6.0.0-beta.4 (2024-10-23) * refactor: use builder in `build` (#18432) ([cc61d16](https://github.com/vitejs/vite/commit/cc61d169a4826996f7b2289618c383f8c5c6d470)), closes [#18432](https://github.com/vitejs/vite/issues/18432) diff --git a/packages/vite/package.json b/packages/vite/package.json index 9a05f9f843b5bd..0b4d6d8958ee38 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "6.0.0-beta.4", + "version": "6.0.0-beta.5", "type": "module", "license": "MIT", "author": "Evan You", @@ -87,7 +87,7 @@ "dependencies": { "esbuild": "^0.24.0", "postcss": "^8.4.47", - "rollup": "^4.22.5" + "rollup": "^4.23.0" }, "optionalDependencies": { "fsevents": "~2.3.3" @@ -133,7 +133,7 @@ "pathe": "^1.1.2", "periscopic": "^4.0.2", "picocolors": "^1.1.1", - "picomatch": "^2.3.1", + "picomatch": "^4.0.2", "postcss-import": "^16.1.0", "postcss-load-config": "^4.0.2", "postcss-modules": "^6.0.0", diff --git a/packages/vite/src/node/__tests__/plugins/json.spec.ts b/packages/vite/src/node/__tests__/plugins/json.spec.ts index b95d31eefa4942..18438a007f2bec 100644 --- a/packages/vite/src/node/__tests__/plugins/json.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/json.spec.ts @@ -1,5 +1,9 @@ -import { expect, test } from 'vitest' -import { extractJsonErrorPosition } from '../../plugins/json' +import { describe, expect, test } from 'vitest' +import { + type JsonOptions, + extractJsonErrorPosition, + jsonPlugin, +} from '../../plugins/json' const getErrorMessage = (input: string) => { try { @@ -24,3 +28,109 @@ test('can extract json error position', () => { ) } }) + +describe('transform', () => { + const transform = (input: string, opts: JsonOptions, isBuild: boolean) => { + const plugin = jsonPlugin(opts, isBuild) + return (plugin.transform! as Function)(input, 'test.json').code + } + + test('namedExports: true, stringify: false', () => { + const actual = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: true, stringify: false }, + false, + ) + expect(actual).toMatchInlineSnapshot(` + "export const a = 1; + export default { + a: a, + "🫠": "", + "const": false + }; + " + `) + }) + + test('namedExports: false, stringify: false', () => { + const actual = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: false, stringify: false }, + false, + ) + expect(actual).toMatchInlineSnapshot(` + "export default { + a: 1, + "🫠": "", + "const": false + };" + `) + }) + + test('namedExports: true, stringify: true', () => { + const actual = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: true, stringify: true }, + false, + ) + expect(actual).toMatchInlineSnapshot(` + "export const a = 1; + export default { + a, + "🫠": "", + "const": false, + }; + " + `) + }) + + test('namedExports: false, stringify: true', () => { + const actualDev = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: false, stringify: true }, + false, + ) + expect(actualDev).toMatchInlineSnapshot( + `"export default JSON.parse("{\\"a\\":1,\\n\\"🫠\\": \\"\\",\\n\\"const\\": false}")"`, + ) + + const actualBuild = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: false, stringify: true }, + true, + ) + expect(actualBuild).toMatchInlineSnapshot( + `"export default JSON.parse("{\\"a\\":1,\\"🫠\\":\\"\\",\\"const\\":false}")"`, + ) + }) + + test("namedExports: true, stringify: 'auto'", () => { + const actualSmall = transform( + '{"a":1,\n"🫠": "",\n"const": false}', + { namedExports: true, stringify: 'auto' }, + false, + ) + expect(actualSmall).toMatchInlineSnapshot(` + "export const a = 1; + export default { + a, + "🫠": "", + "const": false, + }; + " + `) + const actualLargeNonObject = transform( + `{"a":1,\n"🫠": "${'vite'.repeat(3000)}",\n"const": false}`, + { namedExports: true, stringify: 'auto' }, + false, + ) + expect(actualLargeNonObject).not.toContain('JSON.parse(') + + const actualLarge = transform( + `{"a":1,\n"🫠": {\n"foo": "${'vite'.repeat(3000)}"\n},\n"const": false}`, + { namedExports: true, stringify: 'auto' }, + false, + ) + expect(actualLarge).toContain('JSON.parse(') + }) +}) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index e3f170a4b5358d..2f5c51a963dce8 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -369,7 +369,7 @@ export function resolveBuildEnvironmentOptions( cssCodeSplit: !raw.lib, sourcemap: false, rollupOptions: {}, - minify: raw.ssr ? false : 'esbuild', + minify: consumer === 'server' ? false : 'esbuild', terserOptions: {}, write: true, emptyOutDir: null, @@ -434,7 +434,7 @@ export function resolveBuildEnvironmentOptions( } if (resolved.cssMinify == null) { - resolved.cssMinify = !!resolved.minify + resolved.cssMinify = consumer === 'server' ? 'esbuild' : !!resolved.minify } return resolved diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 2b13308645a0d3..2eaec3d8042320 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -38,17 +38,8 @@ const jsSourceMapRE = /\.[cm]?js\.map$/ const assetCache = new WeakMap>() -// chunk.name is the basename for the asset ignoring the directory structure -// For the manifest, we need to preserve the original file path and isEntry -// for CSS assets. We keep a map from referenceId to this information. -export interface GeneratedAssetMeta { - originalFileName: string - isEntry?: boolean -} -export const generatedAssetsMap = new WeakMap< - Environment, - Map ->() +/** a set of referenceId for entry CSS assets for each environment */ +export const cssEntriesMap = new WeakMap>() // add own dictionary entry by directly assigning mrmime export function registerCustomMime(): void { @@ -146,7 +137,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin { buildStart() { assetCache.set(this.environment, new Map()) - generatedAssetsMap.set(this.environment, new Map()) + cssEntriesMap.set(this.environment, new Set()) }, resolveId(id) { @@ -384,8 +375,6 @@ async function fileToBuiltUrl( originalFileName, source: content, }) - generatedAssetsMap.get(environment)!.set(referenceId, { originalFileName }) - url = `__VITE_ASSET__${referenceId}__${postfix ? `$_${postfix}__` : ``}` } diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 2dddeb710d1864..958c923e146831 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -27,6 +27,12 @@ import { formatMessages, transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import { WorkerWithFallback } from 'artichokie' import { globSync } from 'tinyglobby' +import type { + LessPreprocessorBaseOptions, + SassLegacyPreprocessBaseOptions, + SassModernPreprocessBaseOptions, + StylusPreprocessorBaseOptions, +} from 'types/cssPreprocessorOptions' import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap' import type { EnvironmentModuleNode } from '../server/moduleGraph' import { @@ -73,13 +79,14 @@ import { createBackCompatIdResolver } from '../idResolver' import type { ResolveIdFn } from '../idResolver' import { PartialEnvironment } from '../baseEnvironment' import type { TransformPluginContext } from '../server/pluginContainer' -import type { DevEnvironment } from '..' +import { searchForWorkspaceRoot } from '../server/searchRoot' +import { type DevEnvironment } from '..' import { addToHTMLProxyTransformResult } from './html' import { assetUrlRE, + cssEntriesMap, fileToDevUrl, fileToUrl, - generatedAssetsMap, publicAssetUrlCache, publicAssetUrlRE, publicFileToBuiltUrl, @@ -111,7 +118,14 @@ export interface CSSOptions { * In addition to options specific to each processors, Vite supports `additionalData` option. * The `additionalData` option can be used to inject extra code for each style content. */ - preprocessorOptions?: Record + preprocessorOptions?: { + scss?: SassPreprocessorOptions + sass?: SassPreprocessorOptions + less?: LessPreprocessorOptions + styl?: StylusPreprocessorOptions + stylus?: StylusPreprocessorOptions + } + /** * If this option is set, preprocessors will run in workers when possible. * `true` means the number of CPUs minus 1. @@ -434,7 +448,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { assetFileNames({ type: 'asset', name: cssAssetName, + names: [cssAssetName], originalFileName: null, + originalFileNames: [], source: '/* vite internal call, ignore */', }), ) @@ -563,8 +579,6 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { }, async renderChunk(code, chunk, opts) { - 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 @@ -723,7 +737,6 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { originalFileName, source: content, }) - generatedAssets.set(referenceId, { originalFileName }) const filename = this.getFileName(referenceId) chunk.viteMetadata!.importedAssets.add(cleanUrl(filename)) @@ -781,7 +794,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { originalFileName, source: chunkCSS, }) - generatedAssets.set(referenceId, { originalFileName, isEntry }) + if (isEntry) { + cssEntriesMap.get(this.environment)!.add(referenceId) + } chunk.viteMetadata!.importedCss.add(this.getFileName(referenceId)) } else if (this.environment.config.consumer === 'client') { // legacy build and inline css @@ -1135,32 +1150,15 @@ async function compileCSSPreprocessors( const atImportResolvers = getAtImportResolvers( environment.getTopLevelConfig(), ) - - const preProcessor = workerController[lang] - let opts = (preprocessorOptions && preprocessorOptions[lang]) || {} - // support @import from node dependencies by default - switch (lang) { - case PreprocessLang.scss: - case PreprocessLang.sass: - opts = { - includePaths: ['node_modules'], - alias: config.resolve.alias, - ...opts, - } - break - case PreprocessLang.less: - case PreprocessLang.styl: - case PreprocessLang.stylus: - opts = { - paths: ['node_modules'], - alias: config.resolve.alias, - ...opts, - } + const opts = { + ...((preprocessorOptions && preprocessorOptions[lang]) || {}), + alias: config.resolve.alias, + // important: set this for relative import resolving + filename: cleanUrl(id), + enableSourcemap: devSourcemap ?? false, } - // important: set this for relative import resolving - opts.filename = cleanUrl(id) - opts.enableSourcemap = devSourcemap ?? false + const preProcessor = workerController[lang] const preprocessResult = await preProcessor( environment, code, @@ -1640,7 +1638,8 @@ async function resolvePostcssConfig( } else { const searchPath = typeof inlineOptions === 'string' ? inlineOptions : config.root - result = postcssrc({}, searchPath).catch((e) => { + const stopDir = searchForWorkspaceRoot(config.root) + result = postcssrc({}, searchPath, { stopDir }).catch((e) => { if (!e.message.includes('No PostCSS Config found')) { if (e instanceof Error) { const { name, message, stack } = e @@ -1977,52 +1976,43 @@ type PreprocessorAdditionalData = | PreprocessorAdditionalDataResult | Promise) -type StylePreprocessorOptions = { - [key: string]: any +type SassPreprocessorOptions = { + additionalData?: PreprocessorAdditionalData +} & ( + | ({ api?: 'legacy' } & SassLegacyPreprocessBaseOptions) + | ({ api: 'modern' | 'modern-compiler' } & SassModernPreprocessBaseOptions) +) + +type LessPreprocessorOptions = { + additionalData?: PreprocessorAdditionalData +} & LessPreprocessorBaseOptions + +type StylusPreprocessorOptions = { additionalData?: PreprocessorAdditionalData +} & StylusPreprocessorBaseOptions + +type StylePreprocessorInternalOptions = { maxWorkers?: number | true filename: string alias: Alias[] enableSourcemap: boolean } -type SassStylePreprocessorOptions = StylePreprocessorOptions & - Omit, 'data' | 'file' | 'outFile'> & { - api?: 'legacy' | 'modern' | 'modern-compiler' - } +type SassStylePreprocessorInternalOptions = StylePreprocessorInternalOptions & + SassPreprocessorOptions -type StylusStylePreprocessorOptions = StylePreprocessorOptions & { - define?: Record -} +type LessStylePreprocessorInternalOptions = StylePreprocessorInternalOptions & + LessPreprocessorOptions -type StylePreprocessor = { - process: ( - environment: PartialEnvironment, - source: string, - root: string, - options: StylePreprocessorOptions, - resolvers: CSSAtImportResolvers, - ) => StylePreprocessorResults | Promise - close: () => void -} +type StylusStylePreprocessorInternalOptions = StylePreprocessorInternalOptions & + StylusPreprocessorOptions -type SassStylePreprocessor = { +type StylePreprocessor = { process: ( environment: PartialEnvironment, source: string, root: string, - options: SassStylePreprocessorOptions, - resolvers: CSSAtImportResolvers, - ) => StylePreprocessorResults | Promise - close: () => void -} - -type StylusStylePreprocessor = { - process: ( - environment: PartialEnvironment, - source: string, - root: string, - options: StylusStylePreprocessorOptions, + options: Options, resolvers: CSSAtImportResolvers, ) => StylePreprocessorResults | Promise close: () => void @@ -2176,7 +2166,10 @@ const makeScssWorker = ( sassPath: string, data: string, // additionalData can a function that is not cloneable but it won't be used - options: SassStylePreprocessorOptions & { additionalData: undefined }, + options: SassStylePreprocessorInternalOptions & { + api: 'legacy' + additionalData: undefined + }, ) => { // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker const sass: typeof Sass = require(sassPath) @@ -2204,6 +2197,8 @@ const makeScssWorker = ( } const finalOptions: Sass.LegacyOptions<'async'> = { + // support @import from node dependencies by default + includePaths: ['node_modules'], ...options, data, file: options.filename, @@ -2287,7 +2282,10 @@ const makeModernScssWorker = ( sassPath: string, data: string, // additionalData can a function that is not cloneable but it won't be used - options: SassStylePreprocessorOptions & { additionalData: undefined }, + options: SassStylePreprocessorInternalOptions & { + api: 'modern' + additionalData: undefined + }, ) => { // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker const sass: typeof Sass = require(sassPath) @@ -2453,8 +2451,15 @@ type ScssWorkerResult = { const scssProcessor = ( maxWorkers: number | undefined, -): SassStylePreprocessor => { - const workerMap = new Map>() +): StylePreprocessor => { + const workerMap = new Map< + unknown, + ReturnType< + | typeof makeScssWorker + | typeof makeModernScssWorker + | typeof makeModernCompilerScssWorker + > + >() return { close() { @@ -2511,6 +2516,7 @@ const scssProcessor = ( const result = await worker.run( sassPackage.path, data, + // @ts-expect-error the correct worker is selected for `options.type` optionsWithoutAdditionalData, ) const deps = result.stats.includedFiles.map((f) => cleanScssBugUrl(f)) @@ -2706,7 +2712,9 @@ const makeLessWorker = ( lessPath: string, content: string, // additionalData can a function that is not cloneable but it won't be used - options: StylePreprocessorOptions & { additionalData: undefined }, + options: LessStylePreprocessorInternalOptions & { + additionalData: undefined + }, ) => { // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker const nodeLess: typeof Less = require(lessPath) @@ -2715,6 +2723,8 @@ const makeLessWorker = ( options.filename, ) const result = await nodeLess.render(content, { + // support @import from node dependencies by default + paths: ['node_modules'], ...options, plugins: [viteResolverPlugin, ...(options.plugins || [])], ...(options.enableSourcemap @@ -2734,7 +2744,7 @@ const makeLessWorker = ( shouldUseFake(_lessPath, _content, options) { // plugins are a function and is not serializable // in that case, fallback to running in main thread - return options.plugins?.length > 0 + return !!options.plugins && options.plugins.length > 0 }, max: maxWorkers, }, @@ -2742,7 +2752,9 @@ const makeLessWorker = ( return worker } -const lessProcessor = (maxWorkers: number | undefined): StylePreprocessor => { +const lessProcessor = ( + maxWorkers: number | undefined, +): StylePreprocessor => { const workerMap = new Map>() return { @@ -2820,12 +2832,18 @@ const makeStylWorker = (maxWorkers: number | undefined) => { content: string, root: string, // additionalData can a function that is not cloneable but it won't be used - options: StylusStylePreprocessorOptions & { additionalData: undefined }, + options: StylusStylePreprocessorInternalOptions & { + additionalData: undefined + }, ) => { // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker const nodeStylus: typeof Stylus = require(stylusPath) - const ref = nodeStylus(content, options) + const ref = nodeStylus(content, { + // support @import from node dependencies by default + paths: ['node_modules'], + ...options, + }) if (options.define) { for (const key in options.define) { ref.define(key, options.define[key]) @@ -2864,7 +2882,7 @@ const makeStylWorker = (maxWorkers: number | undefined) => { const stylProcessor = ( maxWorkers: number | undefined, -): StylusStylePreprocessor => { +): StylePreprocessor => { const workerMap = new Map>() return { @@ -2981,21 +2999,23 @@ const createPreprocessorWorkerController = (maxWorkers: number | undefined) => { const less = lessProcessor(maxWorkers) const styl = stylProcessor(maxWorkers) - const sassProcess: StylePreprocessor['process'] = ( - environment, - source, - root, - options, - resolvers, - ) => { - return scss.process( - environment, - source, - root, - { ...options, indentedSyntax: true, syntax: 'indented' }, - resolvers, - ) - } + const sassProcess: StylePreprocessor['process'] = + (environment, source, root, options, resolvers) => { + let opts: SassStylePreprocessorInternalOptions + if (options.api === 'modern' || options.api === 'modern-compiler') { + opts = { ...options, syntax: 'indented' as const } + } else { + const narrowedOptions = + options as SassStylePreprocessorInternalOptions & { + api?: 'legacy' + } + opts = { + ...narrowedOptions, + indentedSyntax: true, + } + } + return scss.process(environment, source, root, opts, resolvers) + } const close = () => { less.close() diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 6616c0f35ead41..f660ed1d00d9b3 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -869,7 +869,8 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { // inject css link when cssCodeSplit is false if (!this.environment.config.build.cssCodeSplit) { const cssChunk = Object.values(bundle).find( - (chunk) => chunk.type === 'asset' && chunk.name === 'style.css', + (chunk) => + chunk.type === 'asset' && chunk.names.includes('style.css'), ) as OutputAsset | undefined if (cssChunk) { result = injectToHead(result, [ diff --git a/packages/vite/src/node/plugins/index.ts b/packages/vite/src/node/plugins/index.ts index 7d4efd6a024b61..01e0c140f0bf3e 100644 --- a/packages/vite/src/node/plugins/index.ts +++ b/packages/vite/src/node/plugins/index.ts @@ -77,6 +77,7 @@ export async function resolvePlugins( jsonPlugin( { namedExports: true, + stringify: 'auto', ...config.json, }, isBuild, diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 5de486cf59cbcd..261250ba0227f5 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -6,7 +6,7 @@ * https://github.com/rollup/plugins/blob/master/LICENSE */ -import { dataToEsm } from '@rollup/pluginutils' +import { dataToEsm, makeLegalIdentifier } from '@rollup/pluginutils' import { SPECIAL_QUERY_RE } from '../constants' import type { Plugin } from '../plugin' import { stripBomTag } from '../utils' @@ -19,10 +19,11 @@ export interface JsonOptions { namedExports?: boolean /** * Generate performant output as JSON.parse("stringified"). - * Enabling this will disable namedExports. - * @default false + * + * When set to 'auto', the data will be stringified only if the data is bigger than 10kB. + * @default 'auto' */ - stringify?: boolean + stringify?: boolean | 'auto' } // Custom json filter for vite @@ -47,24 +48,53 @@ export function jsonPlugin( json = stripBomTag(json) try { - if (options.stringify) { - if (isBuild) { + if (options.stringify !== false) { + if (options.namedExports) { + const parsed = JSON.parse(json) + if (typeof parsed === 'object' && parsed != null) { + const keys = Object.keys(parsed) + + let code = '' + let defaultObjectCode = '{\n' + for (const key of keys) { + if (key === makeLegalIdentifier(key)) { + code += `export const ${key} = ${serializeValue(parsed[key])};\n` + defaultObjectCode += ` ${key},\n` + } else { + defaultObjectCode += ` ${JSON.stringify(key)}: ${serializeValue(parsed[key])},\n` + } + } + defaultObjectCode += '}' + + code += `export default ${defaultObjectCode};\n` + return { + code, + map: { mappings: '' }, + } + } + } + + if ( + options.stringify === true || + // use 10kB as a threshold + // https://v8.dev/blog/cost-of-javascript-2019#:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger + (options.stringify === 'auto' && json.length > 10 * 1000) + ) { + // during build, parse then double-stringify to remove all + // unnecessary whitespaces to reduce bundle size. + if (isBuild) { + json = JSON.stringify(JSON.parse(json)) + } + return { - // during build, parse then double-stringify to remove all - // unnecessary whitespaces to reduce bundle size. - code: `export default JSON.parse(${JSON.stringify( - JSON.stringify(JSON.parse(json)), - )})`, + code: `export default JSON.parse(${JSON.stringify(json)})`, map: { mappings: '' }, } - } else { - return `export default JSON.parse(${JSON.stringify(json)})` } } - const parsed = JSON.parse(json) return { - code: dataToEsm(parsed, { + code: dataToEsm(JSON.parse(json), { preferConst: true, namedExports: options.namedExports, }), @@ -81,6 +111,20 @@ export function jsonPlugin( } } +function serializeValue(value: unknown): string { + const valueAsString = JSON.stringify(value) + // use 10kB as a threshold + // https://v8.dev/blog/cost-of-javascript-2019#:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger + if ( + typeof value === 'object' && + value != null && + valueAsString.length > 10 * 1000 + ) { + return `JSON.parse(${JSON.stringify(valueAsString)})` + } + return valueAsString +} + export function extractJsonErrorPosition( errorMessage: string, inputLength: number, diff --git a/packages/vite/src/node/plugins/manifest.ts b/packages/vite/src/node/plugins/manifest.ts index 5ea9779633df37..69538f3704829c 100644 --- a/packages/vite/src/node/plugins/manifest.ts +++ b/packages/vite/src/node/plugins/manifest.ts @@ -8,7 +8,7 @@ import type { import type { Plugin } from '../plugin' import { normalizePath, sortObjectKeys } from '../utils' import { usePerEnvironmentState } from '../environment' -import { generatedAssetsMap } from './asset' +import { cssEntriesMap } from './asset' const endsWithJSRE = /\.[cm]?js$/ @@ -127,18 +127,15 @@ export function manifestPlugin(): Plugin { return manifestChunk } - const assets = generatedAssetsMap.get(this.environment)! - const entryCssAssetFileNames = new Set() - for (const [id, asset] of assets.entries()) { - if (asset.isEntry) { - try { - const fileName = this.getFileName(id) - entryCssAssetFileNames.add(fileName) - } catch { - // The asset was generated as part of a different output option. - // It was already handled during the previous run of this plugin. - assets.delete(id) - } + const entryCssReferenceIds = cssEntriesMap.get(this.environment)! + const entryCssAssetFileNames = new Set(entryCssReferenceIds) + for (const id of entryCssReferenceIds) { + try { + const fileName = this.getFileName(id) + entryCssAssetFileNames.add(fileName) + } catch { + // The asset was generated as part of a different output option. + // It was already handled during the previous run of this plugin. } } @@ -148,28 +145,24 @@ export function manifestPlugin(): Plugin { const chunk = bundle[file] if (chunk.type === 'chunk') { manifest[getChunkName(chunk)] = createChunk(chunk) - } else if (chunk.type === 'asset' && typeof chunk.name === 'string') { + } else if (chunk.type === 'asset' && chunk.names.length > 0) { // Add every unique asset to the manifest, keyed by its original name - const src = chunk.originalFileName ?? chunk.name + const src = + chunk.originalFileNames.length > 0 + ? chunk.originalFileNames[0] + : chunk.names[0] const isEntry = entryCssAssetFileNames.has(chunk.fileName) const asset = createAsset(chunk, src, isEntry) // If JS chunk and asset chunk are both generated from the same source file, // prioritize JS chunk as it contains more information const file = manifest[src]?.file - if (file && endsWithJSRE.test(file)) continue - - manifest[src] = asset - fileNameToAsset.set(chunk.fileName, asset) - } - } + if (!(file && endsWithJSRE.test(file))) { + manifest[src] = asset + fileNameToAsset.set(chunk.fileName, asset) + } - // Add deduplicated assets to the manifest - for (const [referenceId, { originalFileName }] of assets.entries()) { - if (!manifest[originalFileName]) { - const fileName = this.getFileName(referenceId) - const asset = fileNameToAsset.get(fileName) - if (asset) { + for (const originalFileName of chunk.originalFileNames.slice(1)) { manifest[originalFileName] = asset } } diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index a480752e3f7451..b20defb42bbac6 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -23,7 +23,9 @@ import { fileToUrl } from './asset' type WorkerBundleAsset = { fileName: string + /** @deprecated */ originalFileName: string | null + originalFileNames: string[] source: string | Uint8Array } @@ -122,6 +124,7 @@ async function bundleWorkerEntry( saveEmitWorkerAsset(config, { fileName: outputChunk.fileName, originalFileName: null, + originalFileNames: [], source: outputChunk.code, }) } @@ -159,6 +162,7 @@ function emitSourcemapForWorkerEntry( saveEmitWorkerAsset(config, { fileName: mapFileName, originalFileName: null, + originalFileNames: [], source: data, }) } @@ -193,6 +197,7 @@ export async function workerFileToUrl( saveEmitWorkerAsset(config, { fileName, originalFileName: null, + originalFileNames: [], source: outputChunk.code, }) workerMap.bundle.set(id, fileName) @@ -468,8 +473,9 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin { this.emitFile({ type: 'asset', fileName: asset.fileName, - originalFileName: asset.originalFileName, source: asset.source, + // NOTE: fileName is already generated when bundling the worker + // so no need to pass originalFileNames/names }) }) workerMap.assets.clear() diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index 8ea36ab2df2369..a341f5948b72ec 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -84,8 +84,8 @@ export interface PreviewServer { */ httpServer: HttpServer /** - * The resolved urls Vite prints on the CLI. - * null before server is listening. + * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null` + * if the server is not listening on any port. */ resolvedUrls: ResolvedServerUrls | null /** @@ -154,6 +154,7 @@ export async function preview( async close() { teardownSIGTERMListener(closeServerAndExit) await closeHttpServer() + server.resolvedUrls = null }, resolvedUrls: null, printUrls() { diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 29244d0b54b8df..1ecc1e1743f91d 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -284,8 +284,8 @@ export interface ViteDevServer { */ moduleGraph: ModuleGraph /** - * The resolved urls Vite prints on the CLI. null in middleware mode or - * before `server.listen` is called. + * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null` + * in middleware mode or if the server is not listening on any port. */ resolvedUrls: ResolvedServerUrls | null /** @@ -542,7 +542,13 @@ export async function _createServer( url: string, originalCode = code, ) { - return ssrTransform(code, inMap, url, originalCode, server.config) + return ssrTransform(code, inMap, url, originalCode, { + json: { + stringify: + config.json?.stringify === true && + config.json.namedExports !== true, + }, + }) }, // environment.transformRequest and .warmupRequest don't take an options param for now, // so the logic and error handling needs to be duplicated here. diff --git a/packages/vite/src/node/server/openBrowser.ts b/packages/vite/src/node/server/openBrowser.ts index 101cd567ad14c4..eebf4b0ad350fe 100644 --- a/packages/vite/src/node/server/openBrowser.ts +++ b/packages/vite/src/node/server/openBrowser.ts @@ -96,9 +96,7 @@ async function startBrowserProcess( if (openedBrowser) { // Try our best to reuse existing tab with AppleScript await execAsync( - `osascript openChrome.applescript "${encodeURI( - url, - )}" "${openedBrowser}"`, + `osascript openChrome.applescript "${url}" "${openedBrowser}"`, { cwd: join(VITE_PACKAGE_DIR, 'bin'), }, diff --git a/packages/vite/src/node/server/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 666521867a1149..66e81559bf4aca 100644 --- a/packages/vite/src/node/server/transformRequest.ts +++ b/packages/vite/src/node/server/transformRequest.ts @@ -408,14 +408,15 @@ async function loadAndTransform( if (environment._closing && environment.config.dev.recoverable) throwClosedServerError() + const topLevelConfig = environment.getTopLevelConfig() const result = environment.config.dev.moduleRunnerTransform - ? await ssrTransform( - code, - normalizedMap, - url, - originalCode, - environment.getTopLevelConfig(), - ) + ? await ssrTransform(code, normalizedMap, url, originalCode, { + json: { + stringify: + topLevelConfig.json?.stringify === true && + topLevelConfig.json.namedExports !== true, + }, + }) : ({ code, map: normalizedMap, diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 2caffa58693f37..fa8bd6e52a302c 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -2,6 +2,7 @@ import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { assert, expect, test } from 'vitest' import type { SourceMap } from 'rollup' +import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping' import { transformWithEsbuild } from '../../plugins/esbuild' import { ssrTransform } from '../ssrTransform' @@ -445,6 +446,37 @@ test('sourcemap source', async () => { expect(map?.sourcesContent).toStrictEqual(['export const a = 1 /* */']) }) +test('sourcemap is correct for hoisted imports', async () => { + const code = `\n\n\nconsole.log(foo, bar);\nimport { foo } from 'vue';\nimport { bar } from 'vue2';` + const result = (await ssrTransform(code, null, 'input.js', code))! + + expect(result.code).toMatchInlineSnapshot(` + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["foo"]}); + const __vite_ssr_import_1__ = await __vite_ssr_import__("vue2", {"importedNames":["bar"]}); + + + + console.log(__vite_ssr_identity__(__vite_ssr_import_0__.foo), __vite_ssr_identity__(__vite_ssr_import_1__.bar)); + + " + `) + + const traceMap = new TraceMap(result.map as any) + expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({ + source: 'input.js', + line: 5, + column: 0, + name: null, + }) + expect(originalPositionFor(traceMap, { line: 3, column: 0 })).toStrictEqual({ + source: 'input.js', + line: 6, + column: 0, + name: null, + }) +}) + test('sourcemap with multiple sources', async () => { const code = readFixture('bundle.js') const map = readFixture('bundle.js.map') @@ -1151,3 +1183,25 @@ console.log(foo + 2) " `) }) + +test('identity function is declared before used', async () => { + expect( + await ssrTransformSimpleCode(` +import { foo } from './foo' +export default foo() +export * as bar from './bar' +console.log(bar) + `), + ).toMatchInlineSnapshot(` + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); + + + __vite_ssr_exports__.default = __vite_ssr_identity__(__vite_ssr_import_0__.foo)() + const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar"); + + Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }}); + console.log(bar) + " + `) +}) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 0cd4979ae737ed..a93b2c9d8a73ba 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -1,6 +1,6 @@ import path from 'node:path' import MagicString from 'magic-string' -import type { SourceMap } from 'rollup' +import type { RollupAstNode, SourceMap } from 'rollup' import type { ExportAllDeclaration, ExportDefaultDeclaration, @@ -99,13 +99,22 @@ async function ssrTransformScript( const declaredConst = new Set() // hoist at the start of the file, after the hashbang - const hoistIndex = hashbangRE.exec(code)?.[0].length ?? 0 + const fileStartIndex = hashbangRE.exec(code)?.[0].length ?? 0 + let hoistIndex = fileStartIndex function defineImport( index: number, - source: string, + importNode: ( + | ImportDeclaration + | (ExportNamedDeclaration & { source: Literal }) + | ExportAllDeclaration + ) & { + start: number + end: number + }, metadata?: DefineImportMetadata, ) { + const source = importNode.source.value as string deps.add(source) const importId = `__vite_ssr_import_${uid++}__` @@ -118,14 +127,23 @@ async function ssrTransformScript( } const metadataStr = metadata ? `, ${JSON.stringify(metadata)}` : '' - // There will be an error if the module is called before it is imported, - // so the module import statement is hoisted to the top - s.appendLeft( - index, + s.update( + importNode.start, + importNode.end, `const ${importId} = await ${ssrImportKey}(${JSON.stringify( source, )}${metadataStr});\n`, ) + + if (importNode.start === index) { + // no need to hoist, but update hoistIndex to keep the order + hoistIndex = importNode.end + } else { + // There will be an error if the module is called before it is imported, + // so the module import statement is hoisted to the top + s.move(importNode.start, importNode.end, index) + } + return importId } @@ -137,12 +155,12 @@ async function ssrTransformScript( ) } - const imports: (ImportDeclaration & { start: number; end: number })[] = [] - const exports: (( - | ExportNamedDeclaration - | ExportDefaultDeclaration - | ExportAllDeclaration - ) & { start: number; end: number })[] = [] + const imports: RollupAstNode[] = [] + const exports: ( + | RollupAstNode + | RollupAstNode + | RollupAstNode + )[] = [] for (const node of ast.body as Node[]) { if (node.type === 'ImportDeclaration') { @@ -161,7 +179,7 @@ async function ssrTransformScript( // import foo from 'foo' --> foo -> __import_foo__.default // import { baz } from 'foo' --> baz -> __import_foo__.baz // import * as ok from 'foo' --> ok -> __import_foo__ - const importId = defineImport(hoistIndex, node.source.value as string, { + const importId = defineImport(hoistIndex, node, { importedNames: node.specifiers .map((s) => { if (s.type === 'ImportSpecifier') @@ -170,7 +188,6 @@ async function ssrTransformScript( }) .filter(isDefined), }) - s.remove(node.start, node.end) for (const spec of node.specifiers) { if (spec.type === 'ImportSpecifier') { if (spec.imported.type === 'Identifier') { @@ -220,7 +237,7 @@ async function ssrTransformScript( // export { foo, bar } from './foo' const importId = defineImport( node.start, - node.source.value as string, + node as RollupAstNode, { importedNames: node.specifiers.map( (s) => getIdentifierNameOrLiteralValue(s.local) as string, @@ -234,13 +251,13 @@ async function ssrTransformScript( if (spec.local.type === 'Identifier') { defineExport( - node.start, + node.end, exportedAs, `${importId}.${spec.local.name}`, ) } else { defineExport( - node.start, + node.end, exportedAs, `${importId}[${JSON.stringify(spec.local.value as string)}]`, ) @@ -291,15 +308,14 @@ async function ssrTransformScript( // export * from './foo' if (node.type === 'ExportAllDeclaration') { - s.remove(node.start, node.end) - const importId = defineImport(node.start, node.source.value as string) + const importId = defineImport(node.start, node) if (node.exported) { const exportedAs = getIdentifierNameOrLiteralValue( node.exported, ) as string - defineExport(node.start, exportedAs, `${importId}`) + defineExport(node.end, exportedAs, `${importId}`) } else { - s.appendLeft(node.start, `${ssrExportAllKey}(${importId});\n`) + s.appendLeft(node.end, `${ssrExportAllKey}(${importId});\n`) } } } @@ -360,7 +376,7 @@ async function ssrTransformScript( }) if (injectIdentityFunction) { - s.prependLeft(hoistIndex, `const ${ssrIdentityFunction} = v => v;\n`) + s.prependLeft(fileStartIndex, `const ${ssrIdentityFunction} = v => v;\n`) } let map = s.generateMap({ hires: 'boundary' }) diff --git a/packages/vite/src/types/shims.d.ts b/packages/vite/src/types/shims.d.ts index 3a8c070e3ee5f0..00123f17d682d2 100644 --- a/packages/vite/src/types/shims.d.ts +++ b/packages/vite/src/types/shims.d.ts @@ -32,11 +32,6 @@ declare module 'postcss-import' { export = plugin } -// LESS' types somewhat references this which doesn't make sense in Node, -// so we have to shim it -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -declare interface HTMLLinkElement {} - // eslint-disable-next-line no-var declare var __vite_profile_session: import('node:inspector').Session | undefined // eslint-disable-next-line no-var diff --git a/packages/vite/types/cssPreprocessorOptions.d.ts b/packages/vite/types/cssPreprocessorOptions.d.ts new file mode 100644 index 00000000000000..5064ac18f02a63 --- /dev/null +++ b/packages/vite/types/cssPreprocessorOptions.d.ts @@ -0,0 +1,43 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +// @ts-ignore `sass` may not be installed +import type Sass from 'sass' +// @ts-ignore `less` may not be installed +import type Less from 'less' +// @ts-ignore `less` may not be installed +import type Stylus from 'stylus' + +/* eslint-enable @typescript-eslint/ban-ts-comment */ + +export type SassLegacyPreprocessBaseOptions = Omit< + Sass.LegacyStringOptions<'async'>, + | 'data' + | 'file' + | 'outFile' + | 'sourceMap' + | 'omitSourceMapUrl' + | 'sourceMapEmbed' + | 'sourceMapRoot' +> + +export type SassModernPreprocessBaseOptions = Omit< + Sass.StringOptions<'async'>, + 'url' | 'sourceMap' +> + +export type LessPreprocessorBaseOptions = Omit< + Less.Options, + 'sourceMap' | 'filename' +> + +export type StylusPreprocessorBaseOptions = Omit< + Stylus.RenderOptions, + 'filename' +> & { define?: Record } + +declare global { + // LESS' types somewhat references this which doesn't make sense in Node, + // so we have to shim it + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface HTMLLinkElement {} +} diff --git a/playground/json/__tests__/ssr/json-ssr.spec.ts b/playground/json/__tests__/ssr/json-ssr.spec.ts index 5efbeac7da12d6..374e7ca027c6fe 100644 --- a/playground/json/__tests__/ssr/json-ssr.spec.ts +++ b/playground/json/__tests__/ssr/json-ssr.spec.ts @@ -11,7 +11,10 @@ beforeEach(async () => { test('load json module', async () => { await untilUpdated( () => page.textContent('.fetch-json-module pre'), - 'export default JSON.parse("{\\n \\"hello\\": \\"hi\\"\\n}\\n")', + 'export const hello = "hi";\n' + + 'export default {\n' + + ' hello,\n' + + '};\n', ) }) diff --git a/playground/vitestSetup.ts b/playground/vitestSetup.ts index 2b2385209b0e32..a1a986d9883554 100644 --- a/playground/vitestSetup.ts +++ b/playground/vitestSetup.ts @@ -21,7 +21,7 @@ import { } from 'vite' import type { Browser, Page } from 'playwright-chromium' import type { RollupError, RollupWatcher, RollupWatcherEvent } from 'rollup' -import type { File } from 'vitest' +import type { RunnerTestFile } from 'vitest' import { beforeAll, inject } from 'vitest' // #region env @@ -81,7 +81,7 @@ export function setViteUrl(url: string): void { // #endregion beforeAll(async (s) => { - const suite = s as File + const suite = s as RunnerTestFile testPath = suite.filepath! testName = slash(testPath).match(/playground\/([\w-]+)\//)?.[1] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31e590d93219a5..0365cbc5686d6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -113,11 +113,11 @@ importers: specifier: ^5.0.10 version: 5.0.10 rollup: - specifier: ^4.22.5 - version: 4.22.5 + specifier: ^4.23.0 + version: 4.23.0 rollup-plugin-esbuild: specifier: ^6.1.1 - version: 6.1.1(esbuild@0.24.0)(rollup@4.22.5) + version: 6.1.1(esbuild@0.24.0)(rollup@4.23.0) simple-git-hooks: specifier: ^2.11.1 version: 2.11.1 @@ -234,8 +234,8 @@ importers: specifier: ^8.4.47 version: 8.4.47 rollup: - specifier: ^4.22.5 - version: 4.22.5 + specifier: ^4.23.0 + version: 4.23.0 optionalDependencies: fsevents: specifier: ~2.3.3 @@ -255,22 +255,22 @@ importers: version: 1.0.0-next.25 '@rollup/plugin-alias': specifier: ^5.1.1 - version: 5.1.1(rollup@4.22.5) + version: 5.1.1(rollup@4.23.0) '@rollup/plugin-commonjs': specifier: ^28.0.1 - version: 28.0.1(rollup@4.22.5) + version: 28.0.1(rollup@4.23.0) '@rollup/plugin-dynamic-import-vars': specifier: ^2.1.4 - version: 2.1.4(rollup@4.22.5) + version: 2.1.4(rollup@4.23.0) '@rollup/plugin-json': specifier: ^6.1.0 - version: 6.1.0(rollup@4.22.5) + version: 6.1.0(rollup@4.23.0) '@rollup/plugin-node-resolve': specifier: 15.3.0 - version: 15.3.0(rollup@4.22.5) + version: 15.3.0(rollup@4.23.0) '@rollup/pluginutils': specifier: ^5.1.2 - version: 5.1.2(rollup@4.22.5) + version: 5.1.3(rollup@4.23.0) '@types/escape-html': specifier: ^1.0.4 version: 1.0.4 @@ -362,8 +362,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 picomatch: - specifier: ^2.3.1 - version: 2.3.1 + specifier: ^4.0.2 + version: 4.0.2 postcss-import: specifier: ^16.1.0 version: 16.1.0(postcss@8.4.47) @@ -378,13 +378,13 @@ importers: version: 2.0.2 rollup-plugin-dts: specifier: ^6.1.1 - version: 6.1.1(rollup@4.22.5)(typescript@5.6.2) + version: 6.1.1(rollup@4.23.0)(typescript@5.6.2) rollup-plugin-esbuild: specifier: ^6.1.1 - version: 6.1.1(esbuild@0.24.0)(rollup@4.22.5) + version: 6.1.1(esbuild@0.24.0)(rollup@4.23.0) rollup-plugin-license: specifier: ^3.5.3 - version: 3.5.3(picomatch@2.3.1)(rollup@4.22.5) + version: 3.5.3(picomatch@4.0.2)(rollup@4.23.0) sass: specifier: ^1.80.3 version: 1.80.3 @@ -3037,6 +3037,15 @@ packages: '@polka/url@1.0.0-next.24': resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} + '@rollup/plugin-alias@5.1.0': + resolution: {integrity: sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} engines: {node: '>=14.0.0'} @@ -3082,6 +3091,15 @@ packages: rollup: optional: true + '@rollup/plugin-node-resolve@15.2.3': + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/plugin-node-resolve@15.3.0': resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==} engines: {node: '>=14.0.0'} @@ -3109,83 +3127,92 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.22.5': - resolution: {integrity: sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==} + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.23.0': + resolution: {integrity: sha512-8OR+Ok3SGEMsAZispLx8jruuXw0HVF16k+ub2eNXKHDmdxL4cf9NlNpAzhlOhNyXzKDEJuFeq0nZm+XlNb1IFw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.22.5': - resolution: {integrity: sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==} + '@rollup/rollup-android-arm64@4.23.0': + resolution: {integrity: sha512-rEFtX1nP8gqmLmPZsXRMoLVNB5JBwOzIAk/XAcEPuKrPa2nPJ+DuGGpfQUR0XjRm8KjHfTZLpWbKXkA5BoFL3w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.22.5': - resolution: {integrity: sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==} + '@rollup/rollup-darwin-arm64@4.23.0': + resolution: {integrity: sha512-ZbqlMkJRMMPeapfaU4drYHns7Q5MIxjM/QeOO62qQZGPh9XWziap+NF9fsqPHT0KzEL6HaPspC7sOwpgyA3J9g==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.22.5': - resolution: {integrity: sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==} + '@rollup/rollup-darwin-x64@4.23.0': + resolution: {integrity: sha512-PfmgQp78xx5rBCgn2oYPQ1rQTtOaQCna0kRaBlc5w7RlA3TDGGo7m3XaptgitUZ54US9915i7KeVPHoy3/W8tA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.22.5': - resolution: {integrity: sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==} + '@rollup/rollup-linux-arm-gnueabihf@4.23.0': + resolution: {integrity: sha512-WAeZfAAPus56eQgBioezXRRzArAjWJGjNo/M+BHZygUcs9EePIuGI1Wfc6U/Ki+tMW17FFGvhCfYnfcKPh18SA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.22.5': - resolution: {integrity: sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==} + '@rollup/rollup-linux-arm-musleabihf@4.23.0': + resolution: {integrity: sha512-v7PGcp1O5XKZxKX8phTXtmJDVpE20Ub1eF6w9iMmI3qrrPak6yR9/5eeq7ziLMrMTjppkkskXyxnmm00HdtXjA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.22.5': - resolution: {integrity: sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==} + '@rollup/rollup-linux-arm64-gnu@4.23.0': + resolution: {integrity: sha512-nAbWsDZ9UkU6xQiXEyXBNHAKbzSAi95H3gTStJq9UGiS1v+YVXwRHcQOQEF/3CHuhX5BVhShKoeOf6Q/1M+Zhg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.22.5': - resolution: {integrity: sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==} + '@rollup/rollup-linux-arm64-musl@4.23.0': + resolution: {integrity: sha512-5QT/Di5FbGNPaVw8hHO1wETunwkPuZBIu6W+5GNArlKHD9fkMHy7vS8zGHJk38oObXfWdsuLMogD4sBySLJ54g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.22.5': - resolution: {integrity: sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==} + '@rollup/rollup-linux-powerpc64le-gnu@4.23.0': + resolution: {integrity: sha512-Sefl6vPyn5axzCsO13r1sHLcmPuiSOrKIImnq34CBurntcJ+lkQgAaTt/9JkgGmaZJ+OkaHmAJl4Bfd0DmdtOQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.22.5': - resolution: {integrity: sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==} + '@rollup/rollup-linux-riscv64-gnu@4.23.0': + resolution: {integrity: sha512-o4QI2KU/QbP7ZExMse6ULotdV3oJUYMrdx3rBZCgUF3ur3gJPfe8Fuasn6tia16c5kZBBw0aTmaUygad6VB/hQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.22.5': - resolution: {integrity: sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==} + '@rollup/rollup-linux-s390x-gnu@4.23.0': + resolution: {integrity: sha512-+bxqx+V/D4FGrpXzPGKp/SEZIZ8cIW3K7wOtcJAoCrmXvzRtmdUhYNbgd+RztLzfDEfA2WtKj5F4tcbNPuqgeg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.22.5': - resolution: {integrity: sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==} + '@rollup/rollup-linux-x64-gnu@4.23.0': + resolution: {integrity: sha512-I/eXsdVoCKtSgK9OwyQKPAfricWKUMNCwJKtatRYMmDo5N859tbO3UsBw5kT3dU1n6ZcM1JDzPRSGhAUkxfLxw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.22.5': - resolution: {integrity: sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==} + '@rollup/rollup-linux-x64-musl@4.23.0': + resolution: {integrity: sha512-4ZoDZy5ShLbbe1KPSafbFh1vbl0asTVfkABC7eWqIs01+66ncM82YJxV2VtV3YVJTqq2P8HMx3DCoRSWB/N3rw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.22.5': - resolution: {integrity: sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==} + '@rollup/rollup-win32-arm64-msvc@4.23.0': + resolution: {integrity: sha512-+5Ky8dhft4STaOEbZu3/NU4QIyYssKO+r1cD3FzuusA0vO5gso15on7qGzKdNXnc1gOrsgCqZjRw1w+zL4y4hQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.22.5': - resolution: {integrity: sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==} + '@rollup/rollup-win32-ia32-msvc@4.23.0': + resolution: {integrity: sha512-0SPJk4cPZQhq9qA1UhIRumSE3+JJIBBjtlGl5PNC///BoaByckNZd53rOYD0glpTkYFBQSt7AkMeLVPfx65+BQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.22.5': - resolution: {integrity: sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==} + '@rollup/rollup-win32-x64-msvc@4.23.0': + resolution: {integrity: sha512-lqCK5GQC8fNo0+JvTSxcG7YB1UKYp8yrNLhsArlvPWN+16ovSZgoehlVHg6X0sSWPUkpjRBR5TuR12ZugowZ4g==} cpu: [x64] os: [win32] @@ -4055,6 +4082,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -5086,6 +5117,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + is-core-module@2.14.0: resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} engines: {node: '>= 0.4'} @@ -6225,13 +6260,13 @@ packages: peerDependencies: rollup: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup@3.29.4: - resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + rollup@3.29.5: + resolution: {integrity: sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true - rollup@4.22.5: - resolution: {integrity: sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==} + rollup@4.23.0: + resolution: {integrity: sha512-vXB4IT9/KLDrS2WRXmY22sVB2wTsTwkpxjB8Q3mnakTENcYw3FRmfdYDy/acNmls+lHmDazgrRjK/yQ6hQAtwA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -8447,28 +8482,30 @@ snapshots: '@polka/url@1.0.0-next.24': {} - '@rollup/plugin-alias@5.1.1(rollup@3.29.4)': + '@rollup/plugin-alias@5.1.0(rollup@3.29.5)': + dependencies: + slash: 4.0.0 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/plugin-alias@5.1.1(rollup@4.22.5)': + '@rollup/plugin-alias@5.1.1(rollup@4.23.0)': optionalDependencies: - rollup: 4.22.5 + rollup: 4.23.0 - '@rollup/plugin-commonjs@25.0.4(rollup@3.29.4)': + '@rollup/plugin-commonjs@25.0.4(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.5) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.1.0 is-reference: 1.2.1 magic-string: 0.27.0 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/plugin-commonjs@28.0.1(rollup@4.22.5)': + '@rollup/plugin-commonjs@28.0.1(rollup@4.23.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.23.0) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.4.0(picomatch@4.0.2) @@ -8476,119 +8513,128 @@ snapshots: magic-string: 0.30.12 picomatch: 4.0.2 optionalDependencies: - rollup: 4.22.5 + rollup: 4.23.0 - '@rollup/plugin-dynamic-import-vars@2.1.4(rollup@4.22.5)': + '@rollup/plugin-dynamic-import-vars@2.1.4(rollup@4.23.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.23.0) astring: 1.8.6 estree-walker: 2.0.2 magic-string: 0.30.12 tinyglobby: 0.2.9 optionalDependencies: - rollup: 4.22.5 + rollup: 4.23.0 - '@rollup/plugin-json@6.1.0(rollup@3.29.4)': + '@rollup/plugin-json@6.1.0(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.5) optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/plugin-json@6.1.0(rollup@4.22.5)': + '@rollup/plugin-json@6.1.0(rollup@4.23.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.23.0) optionalDependencies: - rollup: 4.22.5 + rollup: 4.23.0 - '@rollup/plugin-node-resolve@15.3.0(rollup@3.29.4)': + '@rollup/plugin-node-resolve@15.2.3(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.5) '@types/resolve': 1.20.2 deepmerge: 4.2.2 + is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.8 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/plugin-node-resolve@15.3.0(rollup@4.22.5)': + '@rollup/plugin-node-resolve@15.3.0(rollup@4.23.0)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.23.0) '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-module: 1.0.0 resolve: 1.22.8 optionalDependencies: - rollup: 4.22.5 + rollup: 4.23.0 - '@rollup/plugin-replace@5.0.2(rollup@3.29.4)': + '@rollup/plugin-replace@5.0.2(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.5) magic-string: 0.27.0 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/pluginutils@5.1.2(rollup@3.29.4)': + '@rollup/pluginutils@5.1.2(rollup@3.29.5)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/pluginutils@5.1.2(rollup@4.22.5)': + '@rollup/pluginutils@5.1.3(rollup@3.29.5)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 4.0.2 optionalDependencies: - rollup: 4.22.5 + rollup: 3.29.5 - '@rollup/rollup-android-arm-eabi@4.22.5': + '@rollup/pluginutils@5.1.3(rollup@4.23.0)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.23.0 + + '@rollup/rollup-android-arm-eabi@4.23.0': optional: true - '@rollup/rollup-android-arm64@4.22.5': + '@rollup/rollup-android-arm64@4.23.0': optional: true - '@rollup/rollup-darwin-arm64@4.22.5': + '@rollup/rollup-darwin-arm64@4.23.0': optional: true - '@rollup/rollup-darwin-x64@4.22.5': + '@rollup/rollup-darwin-x64@4.23.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.22.5': + '@rollup/rollup-linux-arm-gnueabihf@4.23.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.22.5': + '@rollup/rollup-linux-arm-musleabihf@4.23.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.22.5': + '@rollup/rollup-linux-arm64-gnu@4.23.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.22.5': + '@rollup/rollup-linux-arm64-musl@4.23.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.22.5': + '@rollup/rollup-linux-powerpc64le-gnu@4.23.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.22.5': + '@rollup/rollup-linux-riscv64-gnu@4.23.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.22.5': + '@rollup/rollup-linux-s390x-gnu@4.23.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.22.5': + '@rollup/rollup-linux-x64-gnu@4.23.0': optional: true - '@rollup/rollup-linux-x64-musl@4.22.5': + '@rollup/rollup-linux-x64-musl@4.23.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.22.5': + '@rollup/rollup-win32-arm64-msvc@4.23.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.22.5': + '@rollup/rollup-win32-ia32-msvc@4.23.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.22.5': + '@rollup/rollup-win32-x64-msvc@4.23.0': optional: true '@sec-ant/readable-stream@0.4.1': {} @@ -9533,6 +9579,8 @@ snapshots: buffer-from@1.1.2: {} + builtin-modules@3.3.0: {} + bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 @@ -10335,9 +10383,9 @@ snapshots: dependencies: reusify: 1.0.4 - fdir@6.3.0(picomatch@2.3.1): + fdir@6.3.0(picomatch@4.0.2): optionalDependencies: - picomatch: 2.3.1 + picomatch: 4.0.2 fdir@6.4.0(picomatch@4.0.2): optionalDependencies: @@ -10723,6 +10771,10 @@ snapshots: dependencies: binary-extensions: 2.2.0 + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + is-core-module@2.14.0: dependencies: hasown: 2.0.2 @@ -11925,71 +11977,71 @@ snapshots: dependencies: glob: 10.4.5 - rollup-plugin-dts@6.1.1(rollup@3.29.4)(typescript@5.6.2): + rollup-plugin-dts@6.1.1(rollup@3.29.5)(typescript@5.6.2): dependencies: magic-string: 0.30.12 - rollup: 3.29.4 + rollup: 3.29.5 typescript: 5.6.2 optionalDependencies: '@babel/code-frame': 7.25.7 - rollup-plugin-dts@6.1.1(rollup@4.22.5)(typescript@5.6.2): + rollup-plugin-dts@6.1.1(rollup@4.23.0)(typescript@5.6.2): dependencies: magic-string: 0.30.12 - rollup: 4.22.5 + rollup: 4.23.0 typescript: 5.6.2 optionalDependencies: '@babel/code-frame': 7.25.7 - rollup-plugin-esbuild@6.1.1(esbuild@0.24.0)(rollup@4.22.5): + rollup-plugin-esbuild@6.1.1(esbuild@0.24.0)(rollup@4.23.0): dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.23.0) debug: 4.3.7 es-module-lexer: 1.5.4 esbuild: 0.24.0 get-tsconfig: 4.7.5 - rollup: 4.22.5 + rollup: 4.23.0 transitivePeerDependencies: - supports-color - rollup-plugin-license@3.5.3(picomatch@2.3.1)(rollup@4.22.5): + rollup-plugin-license@3.5.3(picomatch@4.0.2)(rollup@4.23.0): dependencies: commenting: 1.1.0 - fdir: 6.3.0(picomatch@2.3.1) + fdir: 6.3.0(picomatch@4.0.2) lodash: 4.17.21 magic-string: 0.30.12 moment: 2.30.1 package-name-regex: 2.0.6 - rollup: 4.22.5 + rollup: 4.23.0 spdx-expression-validate: 2.0.0 spdx-satisfies: 5.0.1 transitivePeerDependencies: - picomatch - rollup@3.29.4: + rollup@3.29.5: optionalDependencies: fsevents: 2.3.3 - rollup@4.22.5: + rollup@4.23.0: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.22.5 - '@rollup/rollup-android-arm64': 4.22.5 - '@rollup/rollup-darwin-arm64': 4.22.5 - '@rollup/rollup-darwin-x64': 4.22.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.22.5 - '@rollup/rollup-linux-arm-musleabihf': 4.22.5 - '@rollup/rollup-linux-arm64-gnu': 4.22.5 - '@rollup/rollup-linux-arm64-musl': 4.22.5 - '@rollup/rollup-linux-powerpc64le-gnu': 4.22.5 - '@rollup/rollup-linux-riscv64-gnu': 4.22.5 - '@rollup/rollup-linux-s390x-gnu': 4.22.5 - '@rollup/rollup-linux-x64-gnu': 4.22.5 - '@rollup/rollup-linux-x64-musl': 4.22.5 - '@rollup/rollup-win32-arm64-msvc': 4.22.5 - '@rollup/rollup-win32-ia32-msvc': 4.22.5 - '@rollup/rollup-win32-x64-msvc': 4.22.5 + '@rollup/rollup-android-arm-eabi': 4.23.0 + '@rollup/rollup-android-arm64': 4.23.0 + '@rollup/rollup-darwin-arm64': 4.23.0 + '@rollup/rollup-darwin-x64': 4.23.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.23.0 + '@rollup/rollup-linux-arm-musleabihf': 4.23.0 + '@rollup/rollup-linux-arm64-gnu': 4.23.0 + '@rollup/rollup-linux-arm64-musl': 4.23.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.23.0 + '@rollup/rollup-linux-riscv64-gnu': 4.23.0 + '@rollup/rollup-linux-s390x-gnu': 4.23.0 + '@rollup/rollup-linux-x64-gnu': 4.23.0 + '@rollup/rollup-linux-x64-musl': 4.23.0 + '@rollup/rollup-win32-arm64-msvc': 4.23.0 + '@rollup/rollup-win32-ia32-msvc': 4.23.0 + '@rollup/rollup-win32-x64-msvc': 4.23.0 fsevents: 2.3.3 run-applescript@7.0.0: {} @@ -12575,12 +12627,12 @@ snapshots: unbuild@2.0.0(sass@1.80.3)(typescript@5.6.2): dependencies: - '@rollup/plugin-alias': 5.1.1(rollup@3.29.4) - '@rollup/plugin-commonjs': 25.0.4(rollup@3.29.4) - '@rollup/plugin-json': 6.1.0(rollup@3.29.4) - '@rollup/plugin-node-resolve': 15.3.0(rollup@3.29.4) - '@rollup/plugin-replace': 5.0.2(rollup@3.29.4) - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/plugin-alias': 5.1.0(rollup@3.29.5) + '@rollup/plugin-commonjs': 25.0.4(rollup@3.29.5) + '@rollup/plugin-json': 6.1.0(rollup@3.29.5) + '@rollup/plugin-node-resolve': 15.2.3(rollup@3.29.5) + '@rollup/plugin-replace': 5.0.2(rollup@3.29.5) + '@rollup/pluginutils': 5.1.2(rollup@3.29.5) chalk: 5.3.0 citty: 0.1.4 consola: 3.2.3 @@ -12595,8 +12647,8 @@ snapshots: pathe: 1.1.2 pkg-types: 1.2.0 pretty-bytes: 6.1.1 - rollup: 3.29.4 - rollup-plugin-dts: 6.1.1(rollup@3.29.4)(typescript@5.6.2) + rollup: 3.29.5 + rollup-plugin-dts: 6.1.1(rollup@3.29.5)(typescript@5.6.2) scule: 1.0.0 untyped: 1.4.0 optionalDependencies: