Skip to content

Commit

Permalink
fix: build.modulePreload.resolveDependencies is optimizable (#16083)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Aug 9, 2024
1 parent 1c9df61 commit e961b31
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 40 deletions.
5 changes: 3 additions & 2 deletions docs/config/build-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ type ResolveModulePreloadDependenciesFn = (
url: string,
deps: string[],
context: {
importer: string
hostId: string
hostType: 'html' | 'js'
},
) => string[]
```
The `resolveDependencies` function will be called for each dynamic import with a list of the chunks it depends on, and it will also be called for each chunk imported in entry HTML files. A new dependencies array can be returned with these filtered or more dependencies injected, and their paths modified. The `deps` paths are relative to the `build.outDir`. Returning a relative path to the `hostId` for `hostType === 'js'` is allowed, in which case `new URL(dep, import.meta.url)` is used to get an absolute path when injecting this module preload in the HTML head.
The `resolveDependencies` function will be called for each dynamic import with a list of the chunks it depends on, and it will also be called for each chunk imported in entry HTML files. A new dependencies array can be returned with these filtered or more dependencies injected, and their paths modified. The `deps` paths are relative to the `build.outDir`. The return value should be a relative path to the `build.outDir`.
```js twoslash
/** @type {import('vite').UserConfig} */
Expand Down
66 changes: 28 additions & 38 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
const isWorker = config.isWorker
const insertPreload = !(ssr || !!config.build.lib || isWorker)

const resolveModulePreloadDependencies =
config.build.modulePreload && config.build.modulePreload.resolveDependencies
const renderBuiltUrl = config.experimental.renderBuiltUrl
const customModulePreloadPaths = !!(
resolveModulePreloadDependencies || renderBuiltUrl
)
const isRelativeBase = config.base === './' || config.base === ''
const optimizeModulePreloadRelativePaths =
isRelativeBase && !customModulePreloadPaths
const optimizeModulePreloadRelativePaths = isRelativeBase && !renderBuiltUrl

const { modulePreload } = config.build
const scriptRel =
Expand All @@ -189,10 +183,10 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
// This is maintained to keep backwards compatibility as some users developed plugins
// using regex over this list to workaround the fact that module preload wasn't
// configurable.
const assetsURL = customModulePreloadPaths
? // If `experimental.renderBuiltUrl` or `build.modulePreload.resolveDependencies` are used
// the dependencies are already resolved. To avoid the need for `new URL(dep, import.meta.url)`
// a helper `__vitePreloadRelativeDep` is used to resolve from relative paths which can be minimized.
const assetsURL = renderBuiltUrl
? // If `experimental.renderBuiltUrl` is used, the dependencies are already resolved.
// To avoid the need for `new URL(dep, import.meta.url)`, a helper `__vitePreloadRelativeDep` is
// used to resolve from relative paths which can be minimized.
`function(dep, importerUrl) { return dep[0] === '.' ? new URL(dep, importerUrl).href : dep }`
: optimizeModulePreloadRelativePaths
? // If there isn't custom resolvers affecting the deps list, deps in the list are relative
Expand Down Expand Up @@ -353,7 +347,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
str().appendRight(
expEnd,
`,${isModernFlag}?${preloadMarker}:void 0${
optimizeModulePreloadRelativePaths || customModulePreloadPaths
optimizeModulePreloadRelativePaths || renderBuiltUrl
? ',import.meta.url'
: ''
})`,
Expand Down Expand Up @@ -580,7 +574,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {

if (markerStartPos > 0) {
// the dep list includes the main chunk, so only need to reload when there are actual other deps.
const depsArray =
let depsArray =
deps.size > 1 ||
// main chunk is removed
(hasRemovedPureCssChunk && deps.size > 0)
Expand All @@ -591,33 +585,29 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
: [...deps]
: []

let renderedDeps: number[]
if (normalizedFile && customModulePreloadPaths) {
const { modulePreload } = config.build
const resolveDependencies = modulePreload
? modulePreload.resolveDependencies
: undefined
let resolvedDeps: string[]
if (resolveDependencies) {
// We can't let the user remove css deps as these aren't really preloads, they are just using
// the same mechanism as module preloads for this chunk
const cssDeps: string[] = []
const otherDeps: string[] = []
for (const dep of depsArray) {
;(dep.endsWith('.css') ? cssDeps : otherDeps).push(dep)
}
resolvedDeps = [
...resolveDependencies(normalizedFile, otherDeps, {
hostId: file,
hostType: 'js',
}),
...cssDeps,
]
} else {
resolvedDeps = depsArray
const resolveDependencies = modulePreload
? modulePreload.resolveDependencies
: undefined
if (resolveDependencies && normalizedFile) {
// We can't let the user remove css deps as these aren't really preloads, they are just using
// the same mechanism as module preloads for this chunk
const cssDeps: string[] = []
const otherDeps: string[] = []
for (const dep of depsArray) {
;(dep.endsWith('.css') ? cssDeps : otherDeps).push(dep)
}
depsArray = [
...resolveDependencies(normalizedFile, otherDeps, {
hostId: file,
hostType: 'js',
}),
...cssDeps,
]
}

renderedDeps = resolvedDeps.map((dep) => {
let renderedDeps: number[]
if (renderBuiltUrl) {
renderedDeps = depsArray.map((dep) => {
const replacement = toOutputFilePathInJS(
dep,
'asset',
Expand Down

0 comments on commit e961b31

Please sign in to comment.