Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions packages/plugin-rsc/e2e/rolldown.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,44 @@ test.describe('rolldownOptions', () => {
defineStarterTest(f)
})
})

// With `output.strictExecutionOrder`, rolldown can emit the client `index`
// entry as an empty facade (no `moduleIds`) that imports a shared chunk.
test.describe('strict-execution-order', () => {
test.skip(!('rolldownVersion' in vite), 'rolldown only')

const root = 'examples/e2e/temp/strict-execution-order'
test.beforeAll(async () => {
await setupInlineFixture({
src: 'examples/starter-extra',
dest: root,
files: {
'vite.config.base.ts': { cp: 'vite.config.ts' },
'vite.config.ts': /* js */ `
import { defineConfig, mergeConfig } from 'vite'
import baseConfig from './vite.config.base.ts'
export default mergeConfig(
baseConfig,
defineConfig({
environments: {
client: {
build: {
rollupOptions: {
output: { strictExecutionOrder: true },
},
},
},
},
}),
)
`,
},
})
})

test.describe('build', () => {
const f = useFixture({ root, mode: 'build' })
defineStarterTest(f)
})
})
19 changes: 12 additions & 7 deletions packages/plugin-rsc/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ export function createRpcClient(params) {
}

const serverResources: Record<string, AssetDeps> = {}
const rscAssetDeps = collectAssetDeps(rscBundle)
const rscAssetDeps = collectAssetDeps(rscBundle).idToDeps
for (const [id, meta] of Object.entries(
manager.serverResourcesMetaMap,
)) {
Expand All @@ -1208,7 +1208,7 @@ export function createRpcClient(params) {
)
}

const assetDeps = collectAssetDeps(bundle)
const { idToDeps: assetDeps, chunkToDeps } = collectAssetDeps(bundle)
let clientEntryUrl: string | RuntimeAsset | undefined
let clientEntryDeps: AssetDeps | undefined

Expand All @@ -1227,19 +1227,24 @@ export function createRpcClient(params) {
// When customClientEntry is enabled, don't require "index" entry
// and don't merge entry deps into client references
if (!rscPluginOptions.customClientEntry) {
const entry = Object.values(assetDeps).find(
(v) => v.chunk.name === 'index' && v.chunk.isEntry,
// Look up the entry chunk at chunk level rather than through
// `assetDeps`, which is keyed by module id. The entry can be an
// empty facade (no `moduleIds`) that imports a shared chunk holding
// the entry's modules, e.g. with `strictExecutionOrder`.
const entry = [...chunkToDeps].find(
([chunk]) => chunk.name === 'index' && chunk.isEntry,
)
if (!entry) {
throw new Error(
`[vite-rsc] Client build must have an entry chunk named "index". Use 'customClientEntry' option to disable this requirement.`,
)
}
clientEntryDeps = assetsURLOfDeps(entry.deps, manager)
const [entryChunk, entryDeps] = entry
clientEntryDeps = assetsURLOfDeps(entryDeps, manager)
for (const [key, deps] of Object.entries(clientReferenceDeps)) {
clientReferenceDeps[key] = mergeAssetDeps(deps, clientEntryDeps)
}
clientEntryUrl = assetsURL(entry.chunk.fileName, manager)
clientEntryUrl = assetsURL(entryChunk.fileName, manager)
}

manager.buildAssetsManifest = {
Expand Down Expand Up @@ -2308,7 +2313,7 @@ function collectAssetDeps(bundle: Rollup.OutputBundle) {
idToDeps[id] = { chunk, deps }
}
}
return idToDeps
return { idToDeps, chunkToDeps }
}

function collectAssetDepsInner(
Expand Down
Loading