Skip to content

Commit cfb5271

Browse files
perf: use filter for plugins
Co-authored-by: IWANABETHATGUY <[email protected]>
1 parent 08123d4 commit cfb5271

14 files changed

+638
-628
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,14 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
163163
},
164164

165165
load: {
166-
async handler(id) {
167-
if (id[0] === '\0') {
166+
filter: {
167+
id: {
168168
// Rollup convention, this id should be handled by the
169169
// plugin that marked it with \0
170-
return
170+
exclude: /^\0/
171171
}
172-
172+
},
173+
async handler(id) {
173174
// raw requests, read from disk
174175
if (rawRE.test(id)) {
175176
const file = checkPublicFile(id, config) || cleanUrl(id)

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

Lines changed: 99 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -50,123 +50,121 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
5050
},
5151

5252
transform: {
53+
filter: {
54+
id: {
55+
exclude: [preloadHelperId, CLIENT_ENTRY],
56+
},
57+
code: /new\s+URL.+import\.meta\.url/,
58+
},
5359
async handler(code, id) {
54-
if (
55-
id !== preloadHelperId &&
56-
id !== CLIENT_ENTRY &&
57-
code.includes('new URL') &&
58-
code.includes(`import.meta.url`)
59-
) {
60-
let s: MagicString | undefined
61-
const assetImportMetaUrlRE =
62-
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
63-
const cleanString = stripLiteral(code)
64-
65-
let match: RegExpExecArray | null
66-
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
67-
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
68-
if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue
60+
let s: MagicString | undefined
61+
const assetImportMetaUrlRE =
62+
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
63+
const cleanString = stripLiteral(code)
6964

70-
const rawUrl = code.slice(urlStart, urlEnd)
65+
let match: RegExpExecArray | null
66+
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
67+
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
68+
if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue
7169

72-
if (!s) s = new MagicString(code)
70+
const rawUrl = code.slice(urlStart, urlEnd)
7371

74-
// potential dynamic template string
75-
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
76-
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
77-
const hasQueryDelimiter = queryDelimiterIndex !== -1
78-
const pureUrl = hasQueryDelimiter
79-
? rawUrl.slice(0, queryDelimiterIndex) + '`'
80-
: rawUrl
81-
const queryString = hasQueryDelimiter
82-
? rawUrl.slice(queryDelimiterIndex, -1)
83-
: ''
84-
const ast = this.parse(pureUrl)
85-
const templateLiteral = (ast as any).body[0].expression
86-
if (templateLiteral.expressions.length) {
87-
const pattern = buildGlobPattern(templateLiteral)
88-
if (pattern.startsWith('*')) {
89-
// don't transform for patterns like this
90-
// because users won't intend to do that in most cases
91-
continue
92-
}
72+
if (!s) s = new MagicString(code)
9373

94-
const globOptions = {
95-
eager: true,
96-
import: 'default',
97-
// A hack to allow 'as' & 'query' exist at the same time
98-
query: injectQuery(queryString, 'url'),
99-
}
100-
s.update(
101-
startIndex,
102-
endIndex,
103-
`new URL((import.meta.glob(${JSON.stringify(
104-
pattern,
105-
)}, ${JSON.stringify(
106-
globOptions,
107-
)}))[${pureUrl}], import.meta.url)`,
108-
)
74+
// potential dynamic template string
75+
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
76+
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
77+
const hasQueryDelimiter = queryDelimiterIndex !== -1
78+
const pureUrl = hasQueryDelimiter
79+
? rawUrl.slice(0, queryDelimiterIndex) + '`'
80+
: rawUrl
81+
const queryString = hasQueryDelimiter
82+
? rawUrl.slice(queryDelimiterIndex, -1)
83+
: ''
84+
const ast = this.parse(pureUrl)
85+
const templateLiteral = (ast as any).body[0].expression
86+
if (templateLiteral.expressions.length) {
87+
const pattern = buildGlobPattern(templateLiteral)
88+
if (pattern.startsWith('*')) {
89+
// don't transform for patterns like this
90+
// because users won't intend to do that in most cases
10991
continue
11092
}
111-
}
11293

113-
const url = rawUrl.slice(1, -1)
114-
if (isDataUrl(url)) {
94+
const globOptions = {
95+
eager: true,
96+
import: 'default',
97+
// A hack to allow 'as' & 'query' exist at the same time
98+
query: injectQuery(queryString, 'url'),
99+
}
100+
s.update(
101+
startIndex,
102+
endIndex,
103+
`new URL((import.meta.glob(${JSON.stringify(
104+
pattern,
105+
)}, ${JSON.stringify(
106+
globOptions,
107+
)}))[${pureUrl}], import.meta.url)`,
108+
)
115109
continue
116110
}
117-
let file: string | undefined
118-
if (url[0] === '.') {
119-
file = slash(path.resolve(path.dirname(id), url))
120-
file = tryFsResolve(file, fsResolveOptions) ?? file
121-
} else {
122-
assetResolver ??= createBackCompatIdResolver(config, {
123-
extensions: [],
124-
mainFields: [],
125-
tryIndex: false,
126-
preferRelative: true,
127-
})
128-
file = await assetResolver(this.environment, url, id)
129-
file ??=
130-
url[0] === '/'
131-
? slash(path.join(publicDir, url))
132-
: slash(path.resolve(path.dirname(id), url))
133-
}
111+
}
134112

135-
// Get final asset URL. If the file does not exist,
136-
// we fall back to the initial URL and let it resolve in runtime
137-
let builtUrl: string | undefined
138-
if (file) {
139-
try {
140-
if (publicDir && isParentDirectory(publicDir, file)) {
141-
const publicPath = '/' + path.posix.relative(publicDir, file)
142-
builtUrl = await fileToUrl(this, publicPath)
143-
} else {
144-
builtUrl = await fileToUrl(this, file)
145-
}
146-
} catch {
147-
// do nothing, we'll log a warning after this
113+
const url = rawUrl.slice(1, -1)
114+
if (isDataUrl(url)) {
115+
continue
116+
}
117+
let file: string | undefined
118+
if (url[0] === '.') {
119+
file = slash(path.resolve(path.dirname(id), url))
120+
file = tryFsResolve(file, fsResolveOptions) ?? file
121+
} else {
122+
assetResolver ??= createBackCompatIdResolver(config, {
123+
extensions: [],
124+
mainFields: [],
125+
tryIndex: false,
126+
preferRelative: true,
127+
})
128+
file = await assetResolver(this.environment, url, id)
129+
file ??=
130+
url[0] === '/'
131+
? slash(path.join(publicDir, url))
132+
: slash(path.resolve(path.dirname(id), url))
133+
}
134+
135+
// Get final asset URL. If the file does not exist,
136+
// we fall back to the initial URL and let it resolve in runtime
137+
let builtUrl: string | undefined
138+
if (file) {
139+
try {
140+
if (publicDir && isParentDirectory(publicDir, file)) {
141+
const publicPath = '/' + path.posix.relative(publicDir, file)
142+
builtUrl = await fileToUrl(this, publicPath)
143+
} else {
144+
builtUrl = await fileToUrl(this, file)
148145
}
146+
} catch {
147+
// do nothing, we'll log a warning after this
149148
}
150-
if (!builtUrl) {
151-
const rawExp = code.slice(startIndex, endIndex)
152-
config.logger.warnOnce(
153-
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
154-
`If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,
155-
)
156-
builtUrl = url
157-
}
158-
s.update(
159-
startIndex,
160-
endIndex,
161-
// NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745
162-
`new URL(${JSON.stringify(builtUrl)}, '' + import.meta.url)`,
163-
)
164149
}
165-
if (s) {
166-
return transformStableResult(s, id, config)
150+
if (!builtUrl) {
151+
const rawExp = code.slice(startIndex, endIndex)
152+
config.logger.warnOnce(
153+
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
154+
`If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,
155+
)
156+
builtUrl = url
167157
}
158+
s.update(
159+
startIndex,
160+
endIndex,
161+
// NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745
162+
`new URL(${JSON.stringify(builtUrl)}, '' + import.meta.url)`,
163+
)
164+
}
165+
if (s) {
166+
return transformStableResult(s, id, config)
168167
}
169-
return null
170168
},
171169
},
172170
}

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,10 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
336336
},
337337

338338
load: {
339+
filter: {
340+
id: CSS_LANGS_RE,
341+
},
339342
async handler(id) {
340-
if (!isCSSRequest(id)) return
341-
342343
if (urlRE.test(id)) {
343344
if (isModuleCSSRequest(id)) {
344345
throw new Error(
@@ -365,7 +366,14 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
365366
}
366367

367368
const transformHook: Plugin['transform'] = {
369+
filter: {
370+
id: {
371+
include: CSS_LANGS_RE,
372+
exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],
373+
},
374+
},
368375
async handler(raw, id) {
376+
// for backward compat this if statement is needed
369377
if (
370378
!isCSSRequest(id) ||
371379
commonjsProxyRE.test(id) ||
@@ -443,9 +451,10 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
443451
}
444452

445453
// for backward compat, make `plugin.transform` a function
446-
// but still keep the `handler` property
447-
// so that we can use `filter` property in the future
454+
// but still keep the `filter` and `handler` properties
455+
// so that rolldown can use `filter`
448456
plugin.transform = transformHook.handler
457+
;(plugin.transform as any).filter = transformHook.filter
449458
;(plugin.transform as any).handler = transformHook.handler
450459

451460
return plugin
@@ -575,7 +584,14 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
575584
},
576585

577586
transform: {
587+
filter: {
588+
id: {
589+
include: CSS_LANGS_RE,
590+
exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],
591+
},
592+
},
578593
async handler(css, id) {
594+
// for backward compat this if statement is needed
579595
if (
580596
!isCSSRequest(id) ||
581597
commonjsProxyRE.test(id) ||
@@ -1136,15 +1152,13 @@ export function cssAnalysisPlugin(config: ResolvedConfig): Plugin {
11361152
name: 'vite:css-analysis',
11371153

11381154
transform: {
1155+
filter: {
1156+
id: {
1157+
include: CSS_LANGS_RE,
1158+
exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],
1159+
},
1160+
},
11391161
async handler(_, id) {
1140-
if (
1141-
!isCSSRequest(id) ||
1142-
commonjsProxyRE.test(id) ||
1143-
SPECIAL_QUERY_RE.test(id)
1144-
) {
1145-
return
1146-
}
1147-
11481162
const { moduleGraph } = this.environment as DevEnvironment
11491163
const thisModule = moduleGraph.getModuleById(id)
11501164

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,29 +181,31 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin {
181181
name: 'vite:dynamic-import-vars',
182182

183183
resolveId: {
184+
filter: {
185+
id: dynamicImportHelperId,
186+
},
184187
handler(id) {
185-
if (id === dynamicImportHelperId) {
186-
return id
187-
}
188+
return id
188189
},
189190
},
190191

191192
load: {
192-
handler(id) {
193-
if (id === dynamicImportHelperId) {
194-
return `export default ${dynamicImportHelper.toString()}`
195-
}
193+
filter: {
194+
id: dynamicImportHelperId,
195+
},
196+
handler(_id) {
197+
return `export default ${dynamicImportHelper.toString()}`
196198
},
197199
},
198200

199201
transform: {
202+
filter: {
203+
id: { exclude: CLIENT_ENTRY },
204+
code: hasDynamicImportRE,
205+
},
200206
async handler(source, importer) {
201207
const { environment } = this
202-
if (
203-
!getFilter(this)(importer) ||
204-
importer === CLIENT_ENTRY ||
205-
!hasDynamicImportRE.test(source)
206-
) {
208+
if (!getFilter(this)(importer)) {
207209
return
208210
}
209211

0 commit comments

Comments
 (0)