Skip to content
118 changes: 108 additions & 10 deletions packages/plugin-rsc/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,21 +956,21 @@ function vitePluginUseClient(
const browserEnvironmentName =
useClientPluginOptions.environment?.browser ?? 'client'

let optimizerMetadata: CustomOptimizerMetadata | undefined

// TODO: warning for late optimizer discovery
function warnInoncistentClientOptimization(
ctx: Rollup.TransformPluginContext,
id: string,
) {
const { depsOptimizer } = server.environments.client
if (depsOptimizer) {
for (const dep of Object.values(depsOptimizer.metadata.optimized)) {
if (dep.src === id) {
ctx.warn(
`client component dependency is inconsistently optimized. ` +
`It's recommended to add the dependency to 'optimizeDeps.exclude'.`,
)
}
}
// path in metafile is relative to cwd
// https://github.com/vitejs/vite/blob/dd96c2cd831ecba3874458b318ad4f0a7f173736/packages/vite/src/node/optimizer/index.ts#L644
id = normalizePath(path.relative(process.cwd(), id))
if (optimizerMetadata?.ids.includes(id)) {
ctx.warn(
`client component dependency is inconsistently optimized. ` +
`It's recommended to add the dependency to 'optimizeDeps.exclude'.`,
)
}
}

Expand Down Expand Up @@ -1160,6 +1160,104 @@ function vitePluginUseClient(
}
},
},
...customOptimizerMetadataPlugin({
setMetadata: (metadata) => {
optimizerMetadata = metadata
},
}),
]
}

type CustomOptimizerMetadata = {
ids: string[]
}

function customOptimizerMetadataPlugin({
setMetadata,
}: {
setMetadata: (metadata: CustomOptimizerMetadata) => void
}): Plugin[] {
const MEATADATA_FILE = '_metadata-rsc.json'

type EsbuildPlugin = NonNullable<
NonNullable<ResolvedConfig['optimizeDeps']['esbuildOptions']>['plugins']
>[number]

function optimizerPluginEsbuild(): EsbuildPlugin {
return {
name: 'vite-rsc-metafile',
setup(build) {
build.onEnd((result) => {
// skip scan
if (!result.metafile?.inputs || !build.initialOptions.outdir) return

const ids = Object.keys(result.metafile.inputs)
const metadata: CustomOptimizerMetadata = { ids }
setMetadata(metadata)
fs.writeFileSync(
path.join(build.initialOptions.outdir, MEATADATA_FILE),
JSON.stringify(metadata, null, 2),
)
})
},
}
}

function optimizerPluginRolldown(): Rollup.Plugin {
return {
name: 'vite-rsc-metafile',
writeBundle(options) {
assert(options.dir)
const ids = [...this.getModuleIds()].map((id) =>
path.relative(process.cwd(), id),
)
const metadata: CustomOptimizerMetadata = { ids }
setMetadata(metadata)
fs.writeFileSync(
path.join(options.dir!, MEATADATA_FILE),
JSON.stringify(metadata, null, 2),
)
},
}
}

return [
{
name: 'rsc:use-client:optimizer-metadata',
apply: 'serve',
config() {
return {
environments: {
client: {
optimizeDeps:
'rolldownVersion' in this.meta
? ({
rolldownOptions: {
plugins: [optimizerPluginRolldown()],
},
} as any)
: {
esbuildOptions: {
plugins: [optimizerPluginEsbuild()],
},
},
},
},
}
},
configResolved(config) {
// https://github.com/vitejs/vite/blob/84079a84ad94de4c1ef4f1bdb2ab448ff2c01196/packages/vite/src/node/optimizer/index.ts#L941
const file = path.join(config.cacheDir, 'deps', MEATADATA_FILE)
if (fs.existsSync(file)) {
try {
const metadata = JSON.parse(fs.readFileSync(file, 'utf-8'))
setMetadata(metadata)
} catch (e) {
this.warn(`failed to load '${file}'`)
}
}
},
},
]
}

Expand Down
Loading