From b80daa7c0970645dca569d572892648f66c6799c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Wed, 23 Oct 2024 23:59:33 +0900 Subject: [PATCH 01/14] feat(json)!: add `json.stringify: 'auto'` and make that the default (#18303) --- docs/config/shared-options.md | 6 +- .../src/node/__tests__/plugins/json.spec.ts | 114 +++++++++++++++++- packages/vite/src/node/plugins/index.ts | 1 + packages/vite/src/node/plugins/json.ts | 74 +++++++++--- packages/vite/src/node/server/index.ts | 8 +- .../vite/src/node/server/transformRequest.ts | 15 +-- .../json/__tests__/ssr/json-ssr.spec.ts | 5 +- 7 files changed, 194 insertions(+), 29 deletions(-) diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index 3502d31a2..b803e36cc 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -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/packages/vite/src/node/__tests__/plugins/json.spec.ts b/packages/vite/src/node/__tests__/plugins/json.spec.ts index b95d31eef..18438a007 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/plugins/index.ts b/packages/vite/src/node/plugins/index.ts index 7d4efd6a0..01e0c140f 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 5de486cf5..261250ba0 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/server/index.ts b/packages/vite/src/node/server/index.ts index 29244d0b5..ab15ac5a4 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -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/transformRequest.ts b/packages/vite/src/node/server/transformRequest.ts index 666521867..66e81559b 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/playground/json/__tests__/ssr/json-ssr.spec.ts b/playground/json/__tests__/ssr/json-ssr.spec.ts index 5efbeac7d..374e7ca02 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', ) }) From fd55c60917a6e9fe2bc251321b880ca9337868be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Oct 2024 14:24:50 +0900 Subject: [PATCH 02/14] docs: add some migration guide for v6 (#18444) --- docs/guide/migration.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 003b31f4b..97277aab9 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -10,6 +10,25 @@ 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. + +- [[#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. From 377488178a7ef372d9b76526bb01fd60b97f51df Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:39:49 +0800 Subject: [PATCH 03/14] chore(deps): update dependency picomatch to v4 (#15876) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: sapphi-red <49056869+sapphi-red@users.noreply.github.com> --- packages/vite/package.json | 2 +- pnpm-lock.yaml | 48 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/vite/package.json b/packages/vite/package.json index 9a05f9f84..672b89b7e 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -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/pnpm-lock.yaml b/pnpm-lock.yaml index 31e590d93..496fb78cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -270,7 +270,7 @@ importers: version: 15.3.0(rollup@4.22.5) '@rollup/pluginutils': specifier: ^5.1.2 - version: 5.1.2(rollup@4.22.5) + version: 5.1.3(rollup@4.22.5) '@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) @@ -384,7 +384,7 @@ importers: version: 6.1.1(esbuild@0.24.0)(rollup@4.22.5) 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.22.5) sass: specifier: ^1.80.3 version: 1.80.3 @@ -3100,8 +3100,8 @@ packages: rollup: optional: true - '@rollup/pluginutils@5.1.2': - resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==} + '@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 @@ -8457,7 +8457,7 @@ snapshots: '@rollup/plugin-commonjs@25.0.4(rollup@3.29.4)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.4) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.1.0 @@ -8468,7 +8468,7 @@ snapshots: '@rollup/plugin-commonjs@28.0.1(rollup@4.22.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.22.5) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.4.0(picomatch@4.0.2) @@ -8480,7 +8480,7 @@ snapshots: '@rollup/plugin-dynamic-import-vars@2.1.4(rollup@4.22.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.22.5) astring: 1.8.6 estree-walker: 2.0.2 magic-string: 0.30.12 @@ -8490,19 +8490,19 @@ snapshots: '@rollup/plugin-json@6.1.0(rollup@3.29.4)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.4) optionalDependencies: rollup: 3.29.4 '@rollup/plugin-json@6.1.0(rollup@4.22.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.22.5) optionalDependencies: rollup: 4.22.5 '@rollup/plugin-node-resolve@15.3.0(rollup@3.29.4)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.4) '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-module: 1.0.0 @@ -8512,7 +8512,7 @@ snapshots: '@rollup/plugin-node-resolve@15.3.0(rollup@4.22.5)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.22.5) '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-module: 1.0.0 @@ -8522,24 +8522,24 @@ snapshots: '@rollup/plugin-replace@5.0.2(rollup@3.29.4)': dependencies: - '@rollup/pluginutils': 5.1.2(rollup@3.29.4) + '@rollup/pluginutils': 5.1.3(rollup@3.29.4) magic-string: 0.27.0 optionalDependencies: rollup: 3.29.4 - '@rollup/pluginutils@5.1.2(rollup@3.29.4)': + '@rollup/pluginutils@5.1.3(rollup@3.29.4)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 4.0.2 optionalDependencies: rollup: 3.29.4 - '@rollup/pluginutils@5.1.2(rollup@4.22.5)': + '@rollup/pluginutils@5.1.3(rollup@4.22.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 @@ -10335,9 +10335,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: @@ -11943,7 +11943,7 @@ snapshots: rollup-plugin-esbuild@6.1.1(esbuild@0.24.0)(rollup@4.22.5): dependencies: - '@rollup/pluginutils': 5.1.2(rollup@4.22.5) + '@rollup/pluginutils': 5.1.3(rollup@4.22.5) debug: 4.3.7 es-module-lexer: 1.5.4 esbuild: 0.24.0 @@ -11952,10 +11952,10 @@ snapshots: 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.22.5): 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 @@ -12580,7 +12580,7 @@ snapshots: '@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/pluginutils': 5.1.3(rollup@3.29.4) chalk: 5.3.0 citty: 0.1.4 consola: 3.2.3 From 8e382a6a1fed2cd41051b81f9cd9c94b484352a5 Mon Sep 17 00:00:00 2001 From: Simon McEnlly Date: Thu, 24 Oct 2024 16:44:50 +1000 Subject: [PATCH 04/14] fix(ssr): preserve source maps for hoisted imports (fix #16355) (#16356) Co-authored-by: sapphi-red <49056869+sapphi-red@users.noreply.github.com> --- .../node/ssr/__tests__/ssrTransform.spec.ts | 31 ++++++++++ packages/vite/src/node/ssr/ssrTransform.ts | 59 ++++++++++++------- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 2caffa586..6a73362f5 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,36 @@ 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_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_import_0__.foo, __vite_ssr_import_1__.bar); + + " + `) + + const traceMap = new TraceMap(result.map as any) + expect(originalPositionFor(traceMap, { line: 1, column: 0 })).toStrictEqual({ + source: 'input.js', + line: 5, + column: 0, + name: null, + }) + expect(originalPositionFor(traceMap, { line: 2, 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') diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 0cd4979ae..1e5a398a9 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,21 @@ 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 + let hoistIndex = hashbangRE.exec(code)?.[0].length ?? 0 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 +126,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 +154,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 +178,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 +187,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 +236,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 +250,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 +307,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`) } } } From 65014a32ef618619c5a34b729d67340d9253bdd5 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Thu, 24 Oct 2024 15:03:18 +0800 Subject: [PATCH 05/14] fix(preview): set resolvedUrls null after close (#18445) --- docs/guide/api-javascript.md | 8 ++++---- packages/vite/src/node/preview.ts | 5 +++-- packages/vite/src/node/server/index.ts | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index 5a883c75e..c0a7a3d50 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/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index 8ea36ab2d..a341f5948 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 ab15ac5a4..1ecc1e174 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 /** From 94cd1e6f95e2434d2b52b5c16d50fe0472214634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Oct 2024 16:10:37 +0900 Subject: [PATCH 06/14] test: fix test conflict (#18446) --- .../node/ssr/__tests__/ssrTransform.spec.ts | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 6a73362f5..f78432517 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -26,8 +26,8 @@ test('named import', async () => { `import { ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); + const __vite_ssr_identity__ = v => v; function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__.ref)(0) }" `) }) @@ -38,8 +38,8 @@ test('named import: arbitrary module namespace specifier', async () => { `import { "some thing" as ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); + const __vite_ssr_identity__ = v => v; function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__["some thing"])(0) }" `) }) @@ -223,8 +223,8 @@ test('do not rewrite method definition', async () => { `import { fn } from 'vue';class A { fn() { fn() } }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); + const __vite_ssr_identity__ = v => v; class A { fn() { __vite_ssr_identity__(__vite_ssr_import_0__.fn)() } }" `) expect(result?.deps).toEqual(['vue']) @@ -451,24 +451,25 @@ test('sourcemap is correct for hoisted imports', async () => { const result = (await ssrTransform(code, null, 'input.js', code))! expect(result.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["foo"]}); + "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_import_0__.foo, __vite_ssr_import_1__.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: 1, column: 0 })).toStrictEqual({ + expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({ source: 'input.js', line: 5, column: 0, name: null, }) - expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({ + expect(originalPositionFor(traceMap, { line: 3, column: 0 })).toStrictEqual({ source: 'input.js', line: 6, column: 0, @@ -535,8 +536,8 @@ test('overwrite bindings', async () => { `function g() { const f = () => { const inject = true }; console.log(inject) }\n`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); + const __vite_ssr_identity__ = v => v; const a = { inject: __vite_ssr_import_0__.inject } const b = { test: __vite_ssr_import_0__.inject } function c() { const { test: inject } = { test: true }; console.log(inject) } @@ -861,8 +862,8 @@ test('jsx', async () => { const result = await transformWithEsbuild(code, id) expect(await ssrTransformSimpleCode(result.code, '/foo.jsx')) .toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); + const __vite_ssr_identity__ = v => v; const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["Foo","Slot"]}); @@ -954,8 +955,8 @@ foo()`, ), ).toMatchInlineSnapshot(` "#!/usr/bin/env node - const __vite_ssr_identity__ = v => v; const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); + const __vite_ssr_identity__ = v => v; __vite_ssr_identity__(__vite_ssr_import_0__.foo)()" `) @@ -991,8 +992,8 @@ export class Test { };`.trim() expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` - "const __vite_ssr_identity__ = v => v; - const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); + "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); + const __vite_ssr_identity__ = v => v; if (false) { const foo = 'foo' From 7eeb6f2f97abf5dfc71c225b9cff9779baf2ed2f Mon Sep 17 00:00:00 2001 From: Alex <8125011+alex-kinokon@users.noreply.github.com> Date: Thu, 24 Oct 2024 03:44:36 -0400 Subject: [PATCH 07/14] fix: add typing to `CSSOptions.preprocessorOptions` (#18001) Co-authored-by: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Co-authored-by: bluwy --- packages/vite/src/node/plugins/css.ts | 183 ++++++++++-------- packages/vite/src/types/shims.d.ts | 5 - .../vite/types/cssPreprocessorOptions.d.ts | 43 ++++ 3 files changed, 143 insertions(+), 88 deletions(-) create mode 100644 packages/vite/types/cssPreprocessorOptions.d.ts diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 2dddeb710..778698bf6 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 { @@ -111,7 +117,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. @@ -1135,32 +1148,15 @@ async function compileCSSPreprocessors( const atImportResolvers = getAtImportResolvers( environment.getTopLevelConfig(), ) + const opts = { + ...((preprocessorOptions && preprocessorOptions[lang]) || {}), + alias: config.resolve.alias, + // important: set this for relative import resolving + filename: cleanUrl(id), + enableSourcemap: devSourcemap ?? false, + } 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, - } - } - // important: set this for relative import resolving - opts.filename = cleanUrl(id) - opts.enableSourcemap = devSourcemap ?? false - const preprocessResult = await preProcessor( environment, code, @@ -1977,52 +1973,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 = { +type StylusStylePreprocessorInternalOptions = StylePreprocessorInternalOptions & + StylusPreprocessorOptions + +type StylePreprocessor = { process: ( environment: PartialEnvironment, source: string, root: string, - options: StylePreprocessorOptions, - resolvers: CSSAtImportResolvers, - ) => StylePreprocessorResults | Promise - close: () => void -} - -type SassStylePreprocessor = { - 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 +2163,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 +2194,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 +2279,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 +2448,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 +2513,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 +2709,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 +2720,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 +2741,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 +2749,9 @@ const makeLessWorker = ( return worker } -const lessProcessor = (maxWorkers: number | undefined): StylePreprocessor => { +const lessProcessor = ( + maxWorkers: number | undefined, +): StylePreprocessor => { const workerMap = new Map>() return { @@ -2820,12 +2829,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 +2879,7 @@ const makeStylWorker = (maxWorkers: number | undefined) => { const stylProcessor = ( maxWorkers: number | undefined, -): StylusStylePreprocessor => { +): StylePreprocessor => { const workerMap = new Map>() return { @@ -2981,21 +2996,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/types/shims.d.ts b/packages/vite/src/types/shims.d.ts index 3a8c070e3..00123f17d 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 000000000..5064ac18f --- /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 {} +} From 56b71768f3ee498962fba898804086299382bb59 Mon Sep 17 00:00:00 2001 From: Sun Date: Thu, 24 Oct 2024 16:24:47 +0800 Subject: [PATCH 08/14] fix(dev): prevent double URL encoding in server.open on macOS (#18443) --- packages/vite/src/node/server/openBrowser.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/vite/src/node/server/openBrowser.ts b/packages/vite/src/node/server/openBrowser.ts index 101cd567a..eebf4b0ad 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'), }, From 0a4427fc44b9b2075225bf8a9f1d88a8a428a217 Mon Sep 17 00:00:00 2001 From: Yusuke Mizuno <38448411+hairihou@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:30:09 +0900 Subject: [PATCH 09/14] fix(create-vite): add tsBuildInfoFile option (#18435) --- packages/create-vite/template-preact-ts/tsconfig.app.json | 1 + packages/create-vite/template-preact-ts/tsconfig.node.json | 1 + packages/create-vite/template-qwik-ts/tsconfig.app.json | 1 + packages/create-vite/template-qwik-ts/tsconfig.node.json | 1 + packages/create-vite/template-react-ts/tsconfig.app.json | 1 + packages/create-vite/template-react-ts/tsconfig.node.json | 1 + packages/create-vite/template-solid-ts/tsconfig.app.json | 1 + packages/create-vite/template-solid-ts/tsconfig.node.json | 1 + packages/create-vite/template-vue-ts/tsconfig.app.json | 1 + packages/create-vite/template-vue-ts/tsconfig.node.json | 1 + 10 files changed, 10 insertions(+) diff --git a/packages/create-vite/template-preact-ts/tsconfig.app.json b/packages/create-vite/template-preact-ts/tsconfig.app.json index 634dfa3cf..00a7cc1e9 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 9dad70185..abcd7f0da 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 0052c0d84..0d65579a4 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 9dad70185..abcd7f0da 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 5a2def4b7..f867de0dd 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 9dad70185..abcd7f0da 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 c6ab232ad..c811fcbb3 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 9dad70185..abcd7f0da 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 909eec5c6..cb88a5a6c 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 9dad70185..abcd7f0da 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", From f1d3bf74cc7f12e759442fd7111d07e2c0262a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Oct 2024 19:01:59 +0900 Subject: [PATCH 10/14] fix!: default `build.cssMinify` to `'esbuild'` for SSR (#15637) --- docs/config/build-options.md | 2 +- docs/guide/migration.md | 2 ++ packages/vite/src/node/build.ts | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/config/build-options.md b/docs/config/build-options.md index 9bff0380a..891b2e958 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/guide/migration.md b/docs/guide/migration.md index 97277aab9..f4c11d580 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -24,6 +24,8 @@ Vite 6 also introduces a new default value for `json.stringify` which is `'auto' 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) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index e3f170a4b..2f5c51a96 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 From 8cc8e51042833c58d91ad42ba96c140ff7aee9ab Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Thu, 24 Oct 2024 11:14:48 +0100 Subject: [PATCH 11/14] chore: replace deprecated `File` type with `RunnerTestFile` (#18448) --- playground/vitestSetup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playground/vitestSetup.ts b/playground/vitestSetup.ts index 2b2385209..a1a986d98 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] From f2957c84f69c14c882809889fbd0fc66b97ca3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Oct 2024 19:24:53 +0900 Subject: [PATCH 12/14] refactor: use `originalFileNames`/`names` (#18240) --- package.json | 2 +- packages/vite/package.json | 2 +- packages/vite/src/node/plugins/asset.ts | 17 +- packages/vite/src/node/plugins/css.ts | 11 +- packages/vite/src/node/plugins/html.ts | 3 +- packages/vite/src/node/plugins/manifest.ts | 47 ++- packages/vite/src/node/plugins/worker.ts | 8 +- pnpm-lock.yaml | 340 ++++++++++++--------- 8 files changed, 236 insertions(+), 194 deletions(-) diff --git a/package.json b/package.json index a48ecc09c..921cf3d0a 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/vite/package.json b/packages/vite/package.json index 672b89b7e..862705103 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -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" diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 2b1330864..2eaec3d80 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 778698bf6..2fa8a4281 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -83,9 +83,9 @@ import type { DevEnvironment } from '..' import { addToHTMLProxyTransformResult } from './html' import { assetUrlRE, + cssEntriesMap, fileToDevUrl, fileToUrl, - generatedAssetsMap, publicAssetUrlCache, publicAssetUrlRE, publicFileToBuiltUrl, @@ -447,7 +447,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { assetFileNames({ type: 'asset', name: cssAssetName, + names: [cssAssetName], originalFileName: null, + originalFileNames: [], source: '/* vite internal call, ignore */', }), ) @@ -576,8 +578,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 @@ -736,7 +736,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)) @@ -794,7 +793,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 diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 6616c0f35..f660ed1d0 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/manifest.ts b/packages/vite/src/node/plugins/manifest.ts index 5ea977963..69538f370 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 + if (!(file && endsWithJSRE.test(file))) { + manifest[src] = asset + fileNameToAsset.set(chunk.fileName, asset) + } - 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 a480752e3..b20defb42 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/pnpm-lock.yaml b/pnpm-lock.yaml index 496fb78cc..0365cbc56 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.3(rollup@4.22.5) + version: 5.1.3(rollup@4.23.0) '@types/escape-html': specifier: ^1.0.4 version: 1.0.4 @@ -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@4.0.2)(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'} @@ -3100,6 +3118,15 @@ packages: rollup: optional: true + '@rollup/pluginutils@5.1.2': + resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/pluginutils@5.1.3': resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} engines: {node: '>=14.0.0'} @@ -3109,83 +3136,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.22.5': - resolution: {integrity: sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==} + '@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)': - optionalDependencies: - rollup: 3.29.4 - - '@rollup/plugin-alias@5.1.1(rollup@4.22.5)': - optionalDependencies: - rollup: 4.22.5 - - '@rollup/plugin-commonjs@25.0.4(rollup@3.29.4)': + '@rollup/plugin-alias@5.1.0(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@3.29.4) + slash: 4.0.0 + optionalDependencies: + rollup: 3.29.5 + + '@rollup/plugin-alias@5.1.1(rollup@4.23.0)': + optionalDependencies: + rollup: 4.23.0 + + '@rollup/plugin-commonjs@25.0.4(rollup@3.29.5)': + dependencies: + '@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.3(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.3(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.3(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.3(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.3(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.5 + + '@rollup/plugin-node-resolve@15.3.0(rollup@4.23.0)': + dependencies: + '@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: 3.29.4 + rollup: 4.23.0 - '@rollup/plugin-node-resolve@15.3.0(rollup@4.22.5)': + '@rollup/plugin-replace@5.0.2(rollup@3.29.5)': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.22.5) - '@types/resolve': 1.20.2 - deepmerge: 4.2.2 - is-module: 1.0.0 - resolve: 1.22.8 - optionalDependencies: - rollup: 4.22.5 - - '@rollup/plugin-replace@5.0.2(rollup@3.29.4)': - dependencies: - '@rollup/pluginutils': 5.1.3(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.3(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.5 + + '@rollup/pluginutils@5.1.3(rollup@3.29.5)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 3.29.4 + rollup: 3.29.5 - '@rollup/pluginutils@5.1.3(rollup@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.22.5 + rollup: 4.23.0 - '@rollup/rollup-android-arm-eabi@4.22.5': + '@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 @@ -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,34 +11977,34 @@ 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.3(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@4.0.2)(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@4.0.2) @@ -11960,36 +12012,36 @@ snapshots: 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.3(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: From d23a493cc4b54a2e2b2c1337b3b1f0c9b1be311e Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Thu, 24 Oct 2024 18:26:47 +0800 Subject: [PATCH 13/14] feat(css)!: load postcss config within workspace root only (#18440) --- docs/config/shared-options.md | 2 +- packages/vite/src/node/plugins/css.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index b803e36cc..0ea4aeeb6 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. diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 2fa8a4281..958c923e1 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -79,7 +79,8 @@ 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, @@ -1637,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 From 0ab20a3ee26eacf302415b3087732497d0a2f358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Oct 2024 21:04:10 +0900 Subject: [PATCH 14/14] fix(ssr): inject identity function at the top (#18449) --- .../node/ssr/__tests__/ssrTransform.spec.ts | 48 ++++++++++++++----- packages/vite/src/node/ssr/ssrTransform.ts | 5 +- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index f78432517..fa8bd6e52 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -26,8 +26,8 @@ test('named import', async () => { `import { ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]}); function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__.ref)(0) }" `) }) @@ -38,8 +38,8 @@ test('named import: arbitrary module namespace specifier', async () => { `import { "some thing" as ref } from 'vue';function foo() { return ref(0) }`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__["some thing"])(0) }" `) }) @@ -223,8 +223,8 @@ test('do not rewrite method definition', async () => { `import { fn } from 'vue';class A { fn() { fn() } }`, ) expect(result?.code).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]}); class A { fn() { __vite_ssr_identity__(__vite_ssr_import_0__.fn)() } }" `) expect(result?.deps).toEqual(['vue']) @@ -536,8 +536,8 @@ test('overwrite bindings', async () => { `function g() { const f = () => { const inject = true }; console.log(inject) }\n`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]}); const a = { inject: __vite_ssr_import_0__.inject } const b = { test: __vite_ssr_import_0__.inject } function c() { const { test: inject } = { test: true }; console.log(inject) } @@ -862,8 +862,8 @@ test('jsx', async () => { const result = await transformWithEsbuild(code, id) expect(await ssrTransformSimpleCode(result.code, '/foo.jsx')) .toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]}); const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["Foo","Slot"]}); @@ -955,8 +955,8 @@ foo()`, ), ).toMatchInlineSnapshot(` "#!/usr/bin/env node - const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]}); __vite_ssr_identity__(__vite_ssr_import_0__.foo)()" `) @@ -992,8 +992,8 @@ export class Test { };`.trim() expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); - const __vite_ssr_identity__ = v => v; + "const __vite_ssr_identity__ = v => v; + const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); if (false) { const foo = 'foo' @@ -1183,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 1e5a398a9..a93b2c9d8 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -99,7 +99,8 @@ async function ssrTransformScript( const declaredConst = new Set() // hoist at the start of the file, after the hashbang - let hoistIndex = hashbangRE.exec(code)?.[0].length ?? 0 + const fileStartIndex = hashbangRE.exec(code)?.[0].length ?? 0 + let hoistIndex = fileStartIndex function defineImport( index: number, @@ -375,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' })