Skip to content

Commit 9827df2

Browse files
authored
refactor: [hookName].handler in plugins (#19586)
1 parent 95424b2 commit 9827df2

19 files changed

Lines changed: 1432 additions & 1345 deletions

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ async function createAssetImportMetaurlPluginTransform() {
1010
const environment = new PartialEnvironment('client', config)
1111

1212
return async (code: string) => {
13-
// @ts-expect-error transform should exist
14-
const result = await instance.transform.call(
13+
// @ts-expect-error transform.handler should exist
14+
const result = await instance.transform.handler.call(
1515
{ environment, parse: parseAst },
1616
code,
1717
'foo.ts',

packages/vite/src/node/__tests__/plugins/define.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ async function createDefinePluginTransform(
1616
const environment = new PartialEnvironment(ssr ? 'ssr' : 'client', config)
1717

1818
return async (code: string) => {
19-
// @ts-expect-error transform should exist
20-
const result = await instance.transform.call(
19+
// @ts-expect-error transform.handler should exist
20+
const result = await instance.transform.handler.call(
2121
{ environment },
2222
code,
2323
'foo.ts',

packages/vite/src/node/__tests__/plugins/json.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ describe('transform', () => {
3636
isBuild: boolean,
3737
) => {
3838
const plugin = jsonPlugin(opts, isBuild)
39-
return (plugin.transform! as Function)(input, 'test.json').code
39+
// @ts-expect-error transform.handler should exist
40+
return plugin.transform.handler(input, 'test.json').code
4041
}
4142

4243
test("namedExports: true, stringify: 'auto' should not transformed an array input", () => {

packages/vite/src/node/__tests__/plugins/workerImportMetaUrl.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ async function createWorkerImportMetaUrlPluginTransform() {
1010
const environment = new PartialEnvironment('client', config)
1111

1212
return async (code: string) => {
13-
// @ts-expect-error transform should exist
14-
const result = await instance.transform.call(
13+
// @ts-expect-error transform.handler should exist
14+
const result = await instance.transform.handler.call(
1515
{ environment, parse: parseAst },
1616
code,
1717
'foo.ts',

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

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -148,60 +148,64 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
148148
cssEntriesMap.set(this.environment, new Set())
149149
},
150150

151-
resolveId(id) {
152-
if (!config.assetsInclude(cleanUrl(id)) && !urlRE.test(id)) {
153-
return
154-
}
155-
// imports to absolute urls pointing to files in /public
156-
// will fail to resolve in the main resolver. handle them here.
157-
const publicFile = checkPublicFile(id, config)
158-
if (publicFile) {
159-
return id
160-
}
151+
resolveId: {
152+
handler(id) {
153+
if (!config.assetsInclude(cleanUrl(id)) && !urlRE.test(id)) {
154+
return
155+
}
156+
// imports to absolute urls pointing to files in /public
157+
// will fail to resolve in the main resolver. handle them here.
158+
const publicFile = checkPublicFile(id, config)
159+
if (publicFile) {
160+
return id
161+
}
162+
},
161163
},
162164

163-
async load(id) {
164-
if (id[0] === '\0') {
165-
// Rollup convention, this id should be handled by the
166-
// plugin that marked it with \0
167-
return
168-
}
165+
load: {
166+
async handler(id) {
167+
if (id[0] === '\0') {
168+
// Rollup convention, this id should be handled by the
169+
// plugin that marked it with \0
170+
return
171+
}
169172

170-
// raw requests, read from disk
171-
if (rawRE.test(id)) {
172-
const file = checkPublicFile(id, config) || cleanUrl(id)
173-
this.addWatchFile(file)
174-
// raw query, read file and return as string
175-
return `export default ${JSON.stringify(
176-
await fsp.readFile(file, 'utf-8'),
177-
)}`
178-
}
173+
// raw requests, read from disk
174+
if (rawRE.test(id)) {
175+
const file = checkPublicFile(id, config) || cleanUrl(id)
176+
this.addWatchFile(file)
177+
// raw query, read file and return as string
178+
return `export default ${JSON.stringify(
179+
await fsp.readFile(file, 'utf-8'),
180+
)}`
181+
}
179182

180-
if (!urlRE.test(id) && !config.assetsInclude(cleanUrl(id))) {
181-
return
182-
}
183+
if (!urlRE.test(id) && !config.assetsInclude(cleanUrl(id))) {
184+
return
185+
}
183186

184-
id = removeUrlQuery(id)
185-
let url = await fileToUrl(this, id)
187+
id = removeUrlQuery(id)
188+
let url = await fileToUrl(this, id)
186189

187-
// Inherit HMR timestamp if this asset was invalidated
188-
if (!url.startsWith('data:') && this.environment.mode === 'dev') {
189-
const mod = this.environment.moduleGraph.getModuleById(id)
190-
if (mod && mod.lastHMRTimestamp > 0) {
191-
url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)
190+
// Inherit HMR timestamp if this asset was invalidated
191+
if (!url.startsWith('data:') && this.environment.mode === 'dev') {
192+
const mod = this.environment.moduleGraph.getModuleById(id)
193+
if (mod && mod.lastHMRTimestamp > 0) {
194+
url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)
195+
}
192196
}
193-
}
194197

195-
return {
196-
code: `export default ${JSON.stringify(encodeURIPath(url))}`,
197-
// Force rollup to keep this module from being shared between other entry points if it's an entrypoint.
198-
// If the resulting chunk is empty, it will be removed in generateBundle.
199-
moduleSideEffects:
200-
config.command === 'build' && this.getModuleInfo(id)?.isEntry
201-
? 'no-treeshake'
202-
: false,
203-
meta: config.command === 'build' ? { 'vite:asset': true } : undefined,
204-
}
198+
return {
199+
code: `export default ${JSON.stringify(encodeURIPath(url))}`,
200+
// Force rollup to keep this module from being shared between other entry points if it's an entrypoint.
201+
// If the resulting chunk is empty, it will be removed in generateBundle.
202+
moduleSideEffects:
203+
config.command === 'build' && this.getModuleInfo(id)?.isEntry
204+
? 'no-treeshake'
205+
: false,
206+
meta: config.command === 'build' ? { 'vite:asset': true } : undefined,
207+
}
208+
},
205209
},
206210

207211
renderChunk(code, chunk, opts) {

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

Lines changed: 103 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -49,122 +49,124 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
4949
return environment.config.consumer === 'client'
5050
},
5151

52-
async transform(code, id) {
53-
if (
54-
id !== preloadHelperId &&
55-
id !== CLIENT_ENTRY &&
56-
code.includes('new URL') &&
57-
code.includes(`import.meta.url`)
58-
) {
59-
let s: MagicString | undefined
60-
const assetImportMetaUrlRE =
61-
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
62-
const cleanString = stripLiteral(code)
52+
transform: {
53+
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)
6364

64-
let match: RegExpExecArray | null
65-
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
66-
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
67-
if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue
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
6869

69-
const rawUrl = code.slice(urlStart, urlEnd)
70+
const rawUrl = code.slice(urlStart, urlEnd)
7071

71-
if (!s) s = new MagicString(code)
72+
if (!s) s = new MagicString(code)
7273

73-
// potential dynamic template string
74-
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
75-
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
76-
const hasQueryDelimiter = queryDelimiterIndex !== -1
77-
const pureUrl = hasQueryDelimiter
78-
? rawUrl.slice(0, queryDelimiterIndex) + '`'
79-
: rawUrl
80-
const queryString = hasQueryDelimiter
81-
? rawUrl.slice(queryDelimiterIndex, -1)
82-
: ''
83-
const ast = this.parse(pureUrl)
84-
const templateLiteral = (ast as any).body[0].expression
85-
if (templateLiteral.expressions.length) {
86-
const pattern = buildGlobPattern(templateLiteral)
87-
if (pattern.startsWith('*')) {
88-
// don't transform for patterns like this
89-
// because users won't intend to do that in most cases
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+
}
93+
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+
)
90109
continue
91110
}
111+
}
92112

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

134-
// Get final asset URL. If the file does not exist,
135-
// we fall back to the initial URL and let it resolve in runtime
136-
let builtUrl: string | undefined
137-
if (file) {
138-
try {
139-
if (publicDir && isParentDirectory(publicDir, file)) {
140-
const publicPath = '/' + path.posix.relative(publicDir, file)
141-
builtUrl = await fileToUrl(this, publicPath)
142-
} else {
143-
builtUrl = await fileToUrl(this, file)
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
144148
}
145-
} catch {
146-
// do nothing, we'll log a warning after this
147149
}
148-
}
149-
if (!builtUrl) {
150-
const rawExp = code.slice(startIndex, endIndex)
151-
config.logger.warnOnce(
152-
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
153-
`If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,
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+
`new URL(${JSON.stringify(builtUrl)}, import.meta.url)`,
154162
)
155-
builtUrl = url
156163
}
157-
s.update(
158-
startIndex,
159-
endIndex,
160-
`new URL(${JSON.stringify(builtUrl)}, import.meta.url)`,
161-
)
162-
}
163-
if (s) {
164-
return transformStableResult(s, id, config)
164+
if (s) {
165+
return transformStableResult(s, id, config)
166+
}
165167
}
166-
}
167-
return null
168+
return null
169+
},
168170
},
169171
}
170172
}

0 commit comments

Comments
 (0)