Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: remove ssr proxy for externalized modules #14521

Merged
merged 10 commits into from
Oct 19, 2023
26 changes: 11 additions & 15 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ import {
dynamicImport,
isBuiltin,
isExternalUrl,
isFilePathESM,
isNodeBuiltin,
isObject,
lookupFile,
mergeAlias,
mergeConfig,
normalizeAlias,
Expand Down Expand Up @@ -323,8 +323,16 @@ export interface ExperimentalOptions {

export interface LegacyOptions {
/**
* No longer needed for now, but kept for backwards compatibility.
* In Vite 4, SSR-externalized modules (modules not bundled and loaded by Node.js at runtime)
* are implicitly proxied in dev to automatically handle `default` and `__esModule` access.
* However, this does not correctly reflect how it works in the Node.js runtime, causing
* inconsistencies between dev and prod.
*
* In Vite 5, the proxy is removed so dev and prod are consistent, but if you still require
* the old behaviour, you can enable this option. If so, please leave your feedback at
* **TODO GitHub discussion link**.
*/
proxySsrExternalModules?: boolean
}

export interface ResolveWorkerOptions extends PluginHookUtils {
Expand Down Expand Up @@ -980,19 +988,7 @@ export async function loadConfigFromFile(
return null
}

let isESM = false
if (/\.m[jt]s$/.test(resolvedPath)) {
isESM = true
} else if (/\.c[jt]s$/.test(resolvedPath)) {
isESM = false
} else {
// check package.json for type: "module" and set `isESM` to true
try {
const pkg = lookupFile(configRoot, ['package.json'])
isESM =
!!pkg && JSON.parse(fs.readFileSync(pkg, 'utf-8')).type === 'module'
} catch (e) {}
}
const isESM = isFilePathESM(resolvedPath)

try {
const bundled = await bundleConfigFile(resolvedPath, isESM)
Expand Down
83 changes: 42 additions & 41 deletions packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('named import', async () => {
`import { ref } from 'vue';function foo() { return ref(0) }`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"ref\\"]});
function foo() { return __vite_ssr_import_0__.ref(0) }"
`)
})
Expand Down Expand Up @@ -77,7 +77,7 @@ test('export named from', async () => {
expect(
await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"ref\\",\\"computed\\"]});

Object.defineProperty(__vite_ssr_exports__, \\"ref\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.ref }});
Object.defineProperty(__vite_ssr_exports__, \\"c\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.computed }});"
Expand All @@ -90,7 +90,7 @@ test('named exports of imported binding', async () => {
`import {createApp} from 'vue';export {createApp}`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"createApp\\"]});

Object.defineProperty(__vite_ssr_exports__, \\"createApp\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.createApp }});"
`)
Expand All @@ -102,9 +102,9 @@ test('export * from', async () => {
`export * from 'vue'\n` + `export * from 'react'`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"isExportAll\\":true});
__vite_ssr_exportAll__(__vite_ssr_import_0__);
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"react\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"react\\", {\\"isExportAll\\":true});
__vite_ssr_exportAll__(__vite_ssr_import_1__);

"
Expand All @@ -114,10 +114,10 @@ test('export * from', async () => {
test('export * as from', async () => {
expect(await ssrTransformSimpleCode(`export * as foo from 'vue'`))
.toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"isExportAll\\":true});

Object.defineProperty(__vite_ssr_exports__, \\"foo\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__ }});"
`)
Object.defineProperty(__vite_ssr_exports__, \\"foo\\", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__ }});"
`)
})

test('export default', async () => {
Expand All @@ -132,8 +132,8 @@ test('export then import minified', async () => {
`export * from 'vue';import {createApp} from 'vue';`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"createApp\\"]});
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\", {\\"isExportAll\\":true});
__vite_ssr_exportAll__(__vite_ssr_import_1__);
"
`)
Expand Down Expand Up @@ -173,7 +173,7 @@ 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\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
class A { fn() { __vite_ssr_import_0__.fn() } }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -184,7 +184,7 @@ test('do not rewrite when variable is in scope', async () => {
`import { fn } from 'vue';function A(){ const fn = () => {}; return { fn }; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A(){ const fn = () => {}; return { fn }; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -196,7 +196,7 @@ test('do not rewrite when variable is in scope with object destructuring', async
`import { fn } from 'vue';function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -208,7 +208,7 @@ test('do not rewrite when variable is in scope with array destructuring', async
`import { fn } from 'vue';function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -220,7 +220,7 @@ test('rewrite variable in string interpolation in function nested arguments', as
`import { fn } from 'vue';function A({foo = \`test\${fn}\`} = {}){ return {}; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A({foo = \`test\${__vite_ssr_import_0__.fn}\`} = {}){ return {}; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -232,7 +232,7 @@ test('rewrite variables in default value of destructuring params', async () => {
`import { fn } from 'vue';function A({foo = fn}){ return {}; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A({foo = __vite_ssr_import_0__.fn}){ return {}; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -243,7 +243,7 @@ test('do not rewrite when function declaration is in scope', async () => {
`import { fn } from 'vue';function A(){ function fn() {}; return { fn }; }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"fn\\"]});
function A(){ function fn() {}; return { fn }; }"
`)
expect(result?.deps).toEqual(['vue'])
Expand All @@ -254,7 +254,7 @@ test('do not rewrite catch clause', async () => {
`import {error} from './dependency';try {} catch(error) {}`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"error\\"]});
try {} catch(error) {}"
`)
expect(result?.deps).toEqual(['./dependency'])
Expand All @@ -267,7 +267,7 @@ test('should declare variable for imported super class', async () => {
`import { Foo } from './dependency';` + `class A extends Foo {}`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"Foo\\"]});
const Foo = __vite_ssr_import_0__.Foo;
class A extends Foo {}"
`)
Expand All @@ -281,7 +281,7 @@ test('should declare variable for imported super class', async () => {
`export class B extends Foo {}`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./dependency\\", {\\"namedImportSpecifiers\\":[\\"Foo\\"]});
const Foo = __vite_ssr_import_0__.Foo;
class A extends Foo {}
class B extends Foo {}
Expand Down Expand Up @@ -354,7 +354,7 @@ 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\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"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) }
Expand Down Expand Up @@ -383,7 +383,7 @@ function c({ _ = bar() + foo() }) {}
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]});


const a = ({ _ = __vite_ssr_import_0__.foo() }) => {}
Expand All @@ -405,7 +405,7 @@ const a = () => {
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"n\\"]});


const a = () => {
Expand All @@ -428,7 +428,7 @@ const foo = {}
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"n\\",\\"m\\"]});


const foo = {}
Expand Down Expand Up @@ -471,7 +471,7 @@ objRest()
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"remove\\",\\"add\\",\\"get\\",\\"set\\",\\"rest\\",\\"objRest\\"]});



Expand Down Expand Up @@ -553,7 +553,7 @@ class A {
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"remove\\",\\"add\\"]});



Expand Down Expand Up @@ -631,7 +631,7 @@ bbb()
`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\", {\\"namedImportSpecifiers\\":[\\"aaa\\",\\"bbb\\",\\"ccc\\",\\"ddd\\"]});



Expand Down Expand Up @@ -677,7 +677,7 @@ test('jsx', async () => {
expect(await ssrTransformSimpleCode(result.code, '/foo.jsx'))
.toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\", {\\"namedImportSpecifiers\\":[\\"Foo\\",\\"Slot\\"]});


function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_1__.Foo, null) }) {
Expand Down Expand Up @@ -788,7 +788,7 @@ export class Test {
};`.trim()

expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]});

if (false) {
const foo = 'foo'
Expand Down Expand Up @@ -830,7 +830,7 @@ function test() {
return [foo, bar]
}`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\"]});


function test() {
Expand All @@ -857,7 +857,7 @@ function test() {
return bar;
}`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\", {\\"namedImportSpecifiers\\":[\\"foo\\",\\"bar\\",\\"baz\\"]});


function test() {
Expand Down Expand Up @@ -889,7 +889,7 @@ for (const test in tests) {
console.log(test)
}`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./test.js\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./test.js\\", {\\"namedImportSpecifiers\\":[\\"test\\"]});



Expand Down Expand Up @@ -921,7 +921,7 @@ const Baz = class extends Foo {}
`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"namedImportSpecifiers\\":[\\"Bar\\"]});



Expand All @@ -942,11 +942,12 @@ test('import assertion attribute', async () => {
import('./bar.json', { assert: { type: 'json' } });
`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo.json\\");


__vite_ssr_dynamic_import__('./bar.json', { assert: { type: 'json' } });
"`)
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo.json\\");


__vite_ssr_dynamic_import__('./bar.json', { assert: { type: 'json' } });
"
`)
})

test('import and export ordering', async () => {
Expand All @@ -962,10 +963,10 @@ export * from './b'
console.log(foo + 2)
`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"./a\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"./foo\\", {\\"namedImportSpecifiers\\":[\\"foo\\"]});
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"./a\\", {\\"isExportAll\\":true});
__vite_ssr_exportAll__(__vite_ssr_import_1__);
const __vite_ssr_import_2__ = await __vite_ssr_import__(\\"./b\\");
const __vite_ssr_import_2__ = await __vite_ssr_import__(\\"./b\\", {\\"isExportAll\\":true});
__vite_ssr_exportAll__(__vite_ssr_import_2__);

console.log(__vite_ssr_import_0__.foo + 1)
Expand Down
Loading