Skip to content

Commit 50bef56

Browse files
committed
perf: let the bundler filter the build plugins
All three build plugins used the legacy `transformInclude` callback. That forces unplugin's JS wrapper and stops the bundler applying the filter natively, so every module in the graph called into the plugin. - moved the id tests into `transform.filter.id`, and the `defineOgImage` substring test into `transform.filter.code` - dropped `isJS`. Its regex `/\.(?:[cm]?j|t)sx?$/` matches `mj` or `t`, never `mt`, so a `.mts` or `.cts` module never reached the handler. `defineOgImage` in a `.mts` file was silently left in the client bundle under `zeroRuntime` - the remaining `isVue` call is not redundant: `/\.vue/` admits `?vue&type=style` and `?nuxt_component`, which only `isVue` rejects - `stripLiteral` parses the whole module and ran before the cheap composable test. Reordered - anchored every extension pattern to end-or-query, since ids carry a query in dev - `components.islands.mjs` was a no-op branch inside the handler. It is a filter exclude - `addBuildPlugin(..., { build: true })` filtered nothing. Kit skips a plugin on `build: false`, and `nuxt.options.build` is always truthy
1 parent f8308f5 commit 50bef56

11 files changed

Lines changed: 893 additions & 706 deletions

src/build/tree-shake-plugin.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ export function isVue(id: string, opts: { type?: Array<'template' | 'script' | '
3737
return true
3838
}
3939

40-
const JS_RE = /\.(?:[cm]?j|t)sx?$/
41-
42-
export function isJS(id: string) {
43-
// JavaScript files
44-
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href))
45-
return JS_RE.test(pathname)
46-
}
40+
// Ids carry a query in dev and for SFC blocks, so every extension match allows one.
41+
const VUE_RE = /\.vue(?:\?|$)/
42+
const JS_RE = /\.[cm]?[jt]sx?(?:\?|$)/
43+
// Nuxt's island component registry re-exports every island component. Rewriting a call
44+
// there would break the manifest, so the plugin has always skipped the file.
45+
const ISLANDS_RE = /components\.islands\.mjs(?:\?|$)/
46+
// Every composable this plugin rewrites starts with `defineOgImage`, so a module without
47+
// that substring can never need the transform. unplugin hands the test to the bundler
48+
// natively where supported, so the hook is not called at all for the rest of the graph.
49+
const COMPOSABLE_CODE_MARKER = 'defineOgImage'
4750

4851
export const TreeShakeComposablesPlugin = createUnplugin(() => {
4952
/**
@@ -64,29 +67,35 @@ export const TreeShakeComposablesPlugin = createUnplugin(() => {
6467
return {
6568
name: 'nuxt-og-image:zero-runtime:transform',
6669
enforce: 'pre',
67-
transformInclude(id) {
68-
return isVue(id, { type: ['script'] }) || isJS(id)
69-
},
70-
transform(code, id) {
71-
const s = new MagicString(code)
72-
// @todo re-implement composable tree-shaking for island files
73-
if (!id.endsWith('components.islands.mjs')) {
74-
const strippedCode = stripLiteral(code)
70+
transform: {
71+
filter: {
72+
// @todo re-implement composable tree-shaking for island files
73+
id: { include: [VUE_RE, JS_RE], exclude: [ISLANDS_RE] },
74+
code: COMPOSABLE_CODE_MARKER,
75+
},
76+
handler(code, id) {
77+
// A `.vue` id reaches us once per SFC block. Only the script block is ours.
78+
if (VUE_RE.test(id) && !isVue(id, { type: ['script'] })) {
79+
return
80+
}
81+
// `stripLiteral` parses the whole module, so run the cheap test first.
7582
if (!COMPOSABLE_RE.test(code)) {
7683
return
7784
}
7885

79-
for (const match of strippedCode.matchAll(COMPOSABLE_RE_GLOBAL)) {
86+
const s = new MagicString(code)
87+
for (const match of stripLiteral(code).matchAll(COMPOSABLE_RE_GLOBAL)) {
8088
s.overwrite(match.index!, match.index! + match[0].length, `${match[1]} import.meta.prerender && ${match[2]}`)
8189
}
82-
}
8390

84-
if (s.hasChanged()) {
91+
if (!s.hasChanged()) {
92+
return
93+
}
8594
return {
8695
code: s.toString(),
8796
map: s.generateMap({ hires: true }),
8897
}
89-
}
98+
},
9099
},
91100
}
92101
})

0 commit comments

Comments
 (0)