Skip to content

Commit e451be2

Browse files
authored
feat(ssr): support external true (#10939)
1 parent d1b143f commit e451be2

File tree

9 files changed

+113
-32
lines changed

9 files changed

+113
-32
lines changed

docs/config/ssr-options.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22

33
## ssr.external
44

5-
- **Type:** `string[]`
5+
- **Type:** `string[] | true`
66
- **Related:** [SSR Externals](/guide/ssr#ssr-externals)
77

8-
Force externalize dependencies for SSR.
8+
Externalize the given dependencies and their transitive dependencies for SSR. By default, all dependencies are externalized except for linked dependencies (for HMR). If you prefer to externalize the linked dependency, you can pass its name to this option.
9+
10+
If `true`, all dependencies including linked dependencies are externalized.
11+
12+
Note that the explicitly listed dependencies (using `string[]` type) will always take priority if they're also listed in `ssr.noExternal` (using any type).
913

1014
## ssr.noExternal
1115

1216
- **Type:** `string | RegExp | (string | RegExp)[] | true`
1317
- **Related:** [SSR Externals](/guide/ssr#ssr-externals)
1418

15-
Prevent listed dependencies from being externalized for SSR. If `true`, no dependencies are externalized.
19+
Prevent listed dependencies from being externalized for SSR, which they will get bundled in build. By default, only linked dependencies are not externalized (for HMR). If you prefer to externalize the linked dependency, you can pass its name to the `ssr.external` option.
20+
21+
If `true`, no dependencies are externalized. However, dependencies explicitly listed in `ssr.external` (using `string[]` type) can take priority and still be externalized.
22+
23+
Note that if both `ssr.noExternal: true` and `ssr.external: true` are configured, `ssr.noExternal` takes priority and no dependencies are externalized.
1624

1725
## ssr.target
1826

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// eslint-disable-next-line no-undef
2+
module.exports = {
3+
hello: () => 'world',
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "@vitejs/cjs-ssr-dep",
3+
"private": true,
4+
"version": "0.0.0"
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "@vitejs/unit-ssr",
3+
"private": true,
4+
"version": "0.0.0",
5+
"dependencies": {
6+
"@vitejs/cjs-ssr-dep": "link:./fixtures/cjs-ssr-dep"
7+
}
8+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { fileURLToPath } from 'node:url'
2+
import { describe, expect, test } from 'vitest'
3+
import type { SSROptions } from '..'
4+
import { resolveConfig } from '../../config'
5+
import { createIsConfiguredAsSsrExternal } from '../ssrExternal'
6+
7+
describe('createIsConfiguredAsSsrExternal', () => {
8+
test('default', async () => {
9+
const isExternal = await createIsExternal()
10+
expect(isExternal('@vitejs/cjs-ssr-dep')).toBe(false)
11+
})
12+
13+
test('force external', async () => {
14+
const isExternal = await createIsExternal({ external: true })
15+
expect(isExternal('@vitejs/cjs-ssr-dep')).toBe(true)
16+
})
17+
})
18+
19+
async function createIsExternal(ssrConfig?: SSROptions) {
20+
const resolvedConfig = await resolveConfig(
21+
{
22+
configFile: false,
23+
root: fileURLToPath(new URL('./', import.meta.url)),
24+
ssr: ssrConfig,
25+
},
26+
'serve',
27+
)
28+
return createIsConfiguredAsSsrExternal(resolvedConfig)
29+
}

packages/vite/src/node/ssr/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export type SsrDepOptimizationOptions = DepOptimizationConfig
66

77
export interface SSROptions {
88
noExternal?: string | RegExp | (string | RegExp)[] | true
9-
external?: string[]
9+
external?: string[] | true
1010

1111
/**
1212
* Define the target for the ssr build. The browser field in package.json

packages/vite/src/node/ssr/ssrExternal.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -87,34 +87,35 @@ export function createIsConfiguredAsSsrExternal(
8787
// Returns true if it is configured as external, false if it is filtered
8888
// by noExternal and undefined if it isn't affected by the explicit config
8989
return (id: string, importer?: string) => {
90-
const { ssr } = config
91-
if (ssr) {
92-
if (
93-
// If this id is defined as external, force it as external
94-
// Note that individual package entries are allowed in ssr.external
95-
ssr.external?.includes(id)
96-
) {
97-
return true
98-
}
99-
const pkgName = getNpmPackageName(id)
100-
if (!pkgName) {
101-
return isExternalizable(id, importer)
102-
}
103-
if (
104-
// A package name in ssr.external externalizes every
105-
// externalizable package entry
106-
ssr.external?.includes(pkgName)
107-
) {
108-
return isExternalizable(id, importer, true)
109-
}
110-
if (typeof noExternal === 'boolean') {
111-
return !noExternal
112-
}
113-
if (noExternalFilter && !noExternalFilter(pkgName)) {
114-
return false
115-
}
90+
if (
91+
// If this id is defined as external, force it as external
92+
// Note that individual package entries are allowed in ssr.external
93+
ssr.external !== true &&
94+
ssr.external?.includes(id)
95+
) {
96+
return true
11697
}
117-
return isExternalizable(id, importer)
98+
const pkgName = getNpmPackageName(id)
99+
if (!pkgName) {
100+
return isExternalizable(id, importer)
101+
}
102+
if (
103+
// A package name in ssr.external externalizes every
104+
// externalizable package entry
105+
ssr.external !== true &&
106+
ssr.external?.includes(pkgName)
107+
) {
108+
return isExternalizable(id, importer, true)
109+
}
110+
if (typeof noExternal === 'boolean') {
111+
return !noExternal
112+
}
113+
if (noExternalFilter && !noExternalFilter(pkgName)) {
114+
return false
115+
}
116+
// If `ssr.external: true`, all will be externalized by default, regardless if
117+
// it's a linked package
118+
return isExternalizable(id, importer, ssr.external === true)
118119
}
119120
}
120121

pnpm-lock.yaml

Lines changed: 26 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
packages:
22
- 'packages/*'
33
- 'playground/**'
4+
- 'packages/**/__tests__/**'

0 commit comments

Comments
 (0)