Skip to content

Commit 69b56f7

Browse files
committed
feat: integrate vite:build-html plugin
1 parent b33cd74 commit 69b56f7

File tree

3 files changed

+34
-85
lines changed

3 files changed

+34
-85
lines changed

packages/vite/src/node/plugins/html.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,10 @@ export function buildHtmlPlugin(config: ResolvedConfig): RolldownPlugin {
732732

733733
await Promise.all(setModuleSideEffectPromises)
734734

735+
if (config.experimental.rolldownDev?.reactRefresh) {
736+
js = `import "virtual:react-refresh/entry";\n${js}`
737+
}
738+
735739
// Force rollup to keep this module from being shared between other entry points.
736740
// If the resulting chunk is empty, it will be removed in generateBundle.
737741
return { code: js, moduleSideEffects: 'no-treeshake' }
@@ -768,7 +772,13 @@ export function buildHtmlPlugin(config: ResolvedConfig): RolldownPlugin {
768772
tag: 'script',
769773
attrs: {
770774
...(isAsync ? { async: true } : {}),
771-
type: 'module',
775+
...(config.experimental.rolldownDev
776+
? {
777+
defer: true,
778+
}
779+
: {
780+
type: 'module',
781+
}),
772782
// crossorigin must be set not only for serving assets in a different origin
773783
// but also to make it possible to preload the script using `<link rel="preload">`.
774784
// `<script type="module">` used to fetch the script with credential mode `omit`,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export async function resolvePlugins(
6161

6262
return [
6363
depOptimizationEnabled ? optimizedDepsPlugin() : null,
64-
isBuild ? metadataPlugin() : null,
64+
rolldownDev || isBuild ? metadataPlugin() : null,
6565
!isWorker ? watchPackageDataPlugin(config.packageCache) : null,
6666
!isBuild ? preAliasPlugin(config) : null,
6767
enableNativePlugin
@@ -164,7 +164,7 @@ export async function resolvePlugins(
164164
enableNativePlugin ? nativeWasmFallbackPlugin() : wasmFallbackPlugin(),
165165
definePlugin(config),
166166
cssPostPlugin(config),
167-
isBuild && buildHtmlPlugin(config),
167+
(rolldownDev || isBuild) && buildHtmlPlugin(config),
168168
workerImportMetaUrlPlugin(config),
169169
assetImportMetaUrlPlugin(config),
170170
...buildPlugins.pre,

packages/vite/src/node/server/environments/rolldown.ts

Lines changed: 21 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import type {
1313
ConfigEnv,
1414
DevEnvironmentOptions,
1515
HmrContext,
16-
ResolvedConfig,
1716
UserConfig,
1817
ViteDevServer,
1918
} from '../..'
@@ -33,6 +32,10 @@ const logger = createLogger('info', {
3332
allowClearScreen: false,
3433
})
3534

35+
//
36+
// Vite plugin hooks
37+
//
38+
3639
export function rolldownDevHandleConfig(
3740
config: UserConfig,
3841
env: ConfigEnv,
@@ -64,6 +67,7 @@ export function rolldownDevHandleConfig(
6467
// NOTE
6568
// this is not "build" option any more (or is there a way to handle entry lazily?)
6669
build: {
70+
modulePreload: false,
6771
rollupOptions: {
6872
input:
6973
config.build?.rollupOptions?.input ??
@@ -167,6 +171,10 @@ window.__rolldown_hot = hot;
167171
return code
168172
}
169173

174+
//
175+
// Rolldown dev environment
176+
//
177+
170178
class RolldownEnvironment extends DevEnvironment {
171179
instance!: rolldown.RolldownBuild
172180
result!: rolldown.RolldownOutput
@@ -220,7 +228,9 @@ class RolldownEnvironment extends DevEnvironment {
220228
plugins = plugins.filter(
221229
(p) =>
222230
!(typeof p.name === 'number' || p.name?.startsWith('vite:')) ||
223-
['vite:define'].includes(p.name) ||
231+
['vite:define', 'vite:build-html', 'vite:build-metadata'].includes(
232+
p.name,
233+
) ||
224234
['AliasPlugin', 'TransformPlugin'].includes(p.constructor.name),
225235
)
226236
plugins = plugins.map((p) => injectEnvironmentToHooks(this as any, p))
@@ -238,7 +248,7 @@ class RolldownEnvironment extends DevEnvironment {
238248
},
239249
plugins: [
240250
...plugins,
241-
rolldownHtmlPlugin(this.config, this.rolldownDevOptions),
251+
patchRuntimePlugin(),
242252
reactRefreshPlugin(this.rolldownDevOptions),
243253
],
244254
}
@@ -293,60 +303,18 @@ class RolldownEnvironment extends DevEnvironment {
293303
}
294304
}
295305

296-
// TODO: use vite:build-html plugin
297-
function rolldownHtmlPlugin(
298-
config: ResolvedConfig,
299-
rolldownDevOptions: RolldownDevOptions,
300-
): rolldown.Plugin {
301-
const htmlEntryMap = new Map<string, MagicString>()
302-
306+
function patchRuntimePlugin(): rolldown.Plugin {
303307
return {
304-
name: 'vite:rolldown-html',
305-
transform: {
306-
filter: {
307-
id: {
308-
include: [/\.html$/],
309-
},
310-
},
311-
async handler(code, id) {
312-
// process html (will be emiited later during generateBundle)
313-
const htmlOutput = new MagicString(code)
314-
htmlEntryMap.set(id, htmlOutput)
315-
316-
let jsOutput = ``
317-
if (rolldownDevOptions?.reactRefresh) {
318-
jsOutput += `import "virtual:react-refresh/entry";\n`
319-
}
320-
321-
// extract <script src="...">
322-
const matches = code.matchAll(
323-
/<script\b[^>]+\bsrc=["']([^"']+)["'][^>]*>.*?<\/script>/dg,
324-
)
325-
for (const match of matches) {
326-
const src = match[1]
327-
const resolved = await this.resolve(src, id)
328-
if (!resolved) {
329-
this.warn(`unresolved src '${src}' in '${id}'`)
330-
continue
331-
}
332-
jsOutput += `import ${JSON.stringify(resolved.id)};\n`
333-
const [start, end] = match.indices![0]
334-
htmlOutput.remove(start, end)
335-
}
336-
337-
// emit js entry
338-
return {
339-
code: jsOutput,
340-
moduleSideEffects: 'no-treeshake',
341-
}
342-
},
343-
},
308+
name: 'vite:rolldown-patch-runtime',
344309
renderChunk(code) {
345310
// patch rolldown_runtime to workaround a few things
346311
if (code.includes('//#region rolldown:runtime')) {
347312
const output = new MagicString(code)
348-
// patch out hard-coded WebSocket setup "const socket = WebSocket(`ws://localhost:8080`)"
349-
output.replace(/const socket =.*?\n\};/s, '')
313+
// replace hard-coded WebSocket setup with custom client
314+
output.replace(
315+
/const socket =.*?\n\};/s,
316+
'import("/@rolldown/client");',
317+
)
350318
// trigger full rebuild on non-accepting entry invalidation
351319
output
352320
.replace('parents: [parent],', 'parents: parent ? [parent] : [],')
@@ -362,40 +330,11 @@ function rolldownHtmlPlugin(
362330
return { code: output.toString(), map: output.generateMap() }
363331
}
364332
},
365-
generateBundle(options, bundle) {
366-
for (const key in bundle) {
367-
const chunk = bundle[key]
368-
// emit final html
369-
if (chunk.type === 'chunk' && chunk.facadeModuleId) {
370-
const htmlId = chunk.facadeModuleId
371-
const htmlOutput = htmlEntryMap.get(htmlId)
372-
if (htmlOutput) {
373-
// inject js entry
374-
htmlOutput.appendLeft(
375-
htmlOutput.original.indexOf(`</body>`),
376-
`<script ${options.format === 'es' ? 'type="module"' : ''} src="/${chunk.fileName}"></script>`,
377-
)
378-
379-
// inject client
380-
htmlOutput.appendLeft(
381-
htmlOutput.original.indexOf(`</head>`),
382-
`<script type="module" src="/@rolldown/client"></script>`,
383-
)
384-
385-
this.emitFile({
386-
type: 'asset',
387-
fileName: path.relative(config.root, htmlId),
388-
originalFileName: htmlId,
389-
source: htmlOutput.toString(),
390-
})
391-
}
392-
}
393-
}
394-
},
395333
}
396334
}
397335

398336
// TODO: workaround rolldownExperimental.reactPlugin which injects js to html via `load` hook
337+
// TODO: can we inject to "react" itself?
399338
function reactRefreshPlugin(
400339
rolldownDevOptions: RolldownDevOptions,
401340
): rolldown.Plugin {

0 commit comments

Comments
 (0)