fix: improve theme chunking logic

pull/3403/head
Divyansh Singh 2 years ago
parent 1407baf9b9
commit b194c232b5

@ -11,9 +11,6 @@ import type { Theme } from 'vitepress'
import VPBadge from './components/VPBadge.vue'
import Layout from './Layout.vue'
// Note: if we add more optional components here, i.e. components that are not
// used in the theme by default unless the user imports them, make sure to update
// the `lazyDefaultThemeComponentsRE` regex in src/node/build/bundle.ts.
export { default as VPImage } from './components/VPImage.vue'
export { default as VPButton } from './components/VPButton.vue'
export { default as VPHomeHero } from './components/VPHomeHero.vue'

@ -15,14 +15,24 @@ import { sanitizeFileName, slash } from '../shared'
import { task } from '../utils/task'
import { buildMPAClient } from './buildMPAClient'
// A list of default theme components that should only be loaded on demand.
const lazyDefaultThemeComponentsRE =
/VP(HomeSponsors|DocAsideSponsors|TeamPage|TeamMembers|LocalSearchBox|AlgoliaSearchBox|CarbonAds|DocAsideCarbonAds|Sponsors)/
const CSS_LANGS_RE =
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/
const clientDir = normalizePath(
path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../client')
)
// to avoid circular dependency issues
// these deps are also being used in the client code (outside of the theme)
const excludedModules = [
'/@siteData',
'node_modules/@vueuse/core/',
'node_modules/@vueuse/shared/',
'node_modules/vue/',
'node_modules/vue-demi/',
clientDir
]
// bundles the VitePress app for both client AND server.
export async function bundle(
config: SiteConfig,
@ -47,6 +57,12 @@ export async function bundle(
input[slash(alias).replace(/\//g, '_')] = path.resolve(config.srcDir, file)
})
const themeEntryRE = new RegExp(
`^${escapeRegExp(
path.resolve(config.themeDir, 'index.js').replace(/\\/g, '/')
).slice(0, -2)}m?(j|t)s`
)
// resolve options to pass to vite
const { rollupOptions } = options
@ -109,12 +125,6 @@ export async function bundle(
: `${config.assetsDir}/chunks/[name].[hash].js`
},
manualChunks(id, ctx) {
if (lazyDefaultThemeComponentsRE.test(id)) {
return
}
if (id.startsWith(`${clientDir}/theme-default`)) {
return 'theme'
}
// move known framework code into a stable chunk so that
// custom theme changes do not invalidate hash for all pages
if (id.startsWith('\0vite')) {
@ -135,6 +145,19 @@ export async function bundle(
) {
return 'framework'
}
if (
(id.startsWith(`${clientDir}/theme-default`) ||
!excludedModules.some((i) => id.includes(i))) &&
staticImportedByEntry(
id,
ctx.getModuleInfo,
cacheTheme,
themeEntryRE
)
) {
return 'theme'
}
}
})
}
@ -182,6 +205,7 @@ export async function bundle(
}
const cache = new Map<string, boolean>()
const cacheTheme = new Map<string, boolean>()
/**
* Check if a module is statically imported by at least one entry.
@ -189,7 +213,7 @@ const cache = new Map<string, boolean>()
function isEagerChunk(id: string, getModuleInfo: Rollup.GetModuleInfo) {
if (
id.includes('node_modules') &&
!/\.css($|\\?)/.test(id) &&
!CSS_LANGS_RE.test(id) &&
staticImportedByEntry(id, getModuleInfo, cache)
) {
return true
@ -200,6 +224,7 @@ function staticImportedByEntry(
id: string,
getModuleInfo: Rollup.GetModuleInfo,
cache: Map<string, boolean>,
entryRE: RegExp | null = null,
importStack: string[] = []
): boolean {
if (cache.has(id)) {
@ -216,7 +241,7 @@ function staticImportedByEntry(
return false
}
if (mod.isEntry) {
if (entryRE ? entryRE.test(id) : mod.isEntry) {
cache.set(id, true)
return true
}
@ -225,9 +250,14 @@ function staticImportedByEntry(
importer,
getModuleInfo,
cache,
entryRE,
importStack.concat(id)
)
)
cache.set(id, someImporterIs)
return someImporterIs
}
function escapeRegExp(str: string) {
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
}

Loading…
Cancel
Save