Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: avoid splitting vendor chunk by default #6534

Merged
merged 10 commits into from Mar 4, 2022
3 changes: 2 additions & 1 deletion packages/playground/vue/vite.config.ts
@@ -1,4 +1,4 @@
import { defineConfig } from 'vite'
import { defineConfig, splitVendorChunkPlugin } from 'vite'
import vuePlugin from '@vitejs/plugin-vue'
import { vueI18nPlugin } from './CustomBlockPlugin'

Expand All @@ -12,6 +12,7 @@ export default defineConfig({
vuePlugin({
reactivityTransform: true
}),
splitVendorChunkPlugin(),
vueI18nPlugin
],
build: {
Expand Down
59 changes: 0 additions & 59 deletions packages/vite/src/node/build.ts
Expand Up @@ -12,8 +12,6 @@ import type {
OutputOptions,
RollupOutput,
ExternalOption,
GetManualChunk,
GetModuleInfo,
WatcherOptions,
RollupWatcher,
RollupError,
Expand All @@ -37,7 +35,6 @@ import { dataURIPlugin } from './plugins/dataUri'
import { buildImportAnalysisPlugin } from './plugins/importAnalysisBuild'
import { resolveSSRExternal, shouldExternalizeForSSR } from './ssr/ssrExternal'
import { ssrManifestPlugin } from './ssr/ssrManifestPlugin'
import { isCSSRequest } from './plugins/css'
import type { DepOptimizationMetadata } from './optimizer'
import { scanImports } from './optimizer/scan'
import { assetImportMetaUrlPlugin } from './plugins/assetImportMetaUrl'
Expand Down Expand Up @@ -509,13 +506,6 @@ async function doBuild(
// #1048 add `Symbol.toStringTag` for module default export
namespaceToStringTag: true,
inlineDynamicImports: ssr && typeof input === 'string',
manualChunks:
!ssr &&
!libOptions &&
output?.format !== 'umd' &&
output?.format !== 'iife'
? createMoveToVendorChunkFn(config)
: undefined,
...output
}
}
Expand Down Expand Up @@ -642,55 +632,6 @@ function getPkgName(root: string) {
return name?.startsWith('@') ? name.split('/')[1] : name
}

function createMoveToVendorChunkFn(config: ResolvedConfig): GetManualChunk {
const cache = new Map<string, boolean>()
return (id, { getModuleInfo }) => {
if (
id.includes('node_modules') &&
!isCSSRequest(id) &&
staticImportedByEntry(id, getModuleInfo, cache)
) {
return 'vendor'
}
}
}

function staticImportedByEntry(
id: string,
getModuleInfo: GetModuleInfo,
cache: Map<string, boolean>,
importStack: string[] = []
): boolean {
if (cache.has(id)) {
return cache.get(id) as boolean
}
if (importStack.includes(id)) {
// circular deps!
cache.set(id, false)
return false
}
const mod = getModuleInfo(id)
if (!mod) {
cache.set(id, false)
return false
}

if (mod.isEntry) {
cache.set(id, true)
return true
}
const someImporterIs = mod.importers.some((importer) =>
staticImportedByEntry(
importer,
getModuleInfo,
cache,
importStack.concat(id)
)
)
cache.set(id, someImporterIs)
return someImporterIs
}

export function resolveLibFilename(
libOptions: LibraryOptions,
format: ModuleFormat,
Expand Down
5 changes: 5 additions & 0 deletions packages/vite/src/node/index.ts
Expand Up @@ -7,6 +7,10 @@ export { send } from './server/send'
export { createLogger, printHttpServerUrls } from './logger'
export { transformWithEsbuild } from './plugins/esbuild'
export { resolvePackageEntry } from './plugins/resolve'
export {
splitVendorChunkPlugin,
splitVendorChunk
} from './plugins/splitVendorChunk'
export { resolvePackageData } from './packages'
export { normalizePath } from './utils'

Expand Down Expand Up @@ -91,3 +95,4 @@ export type { Terser } from 'types/terser'
export type { RollupCommonJSOptions } from 'types/commonjs'
export type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars'
export type { Matcher, AnymatchPattern, AnymatchFn } from 'types/anymatch'
export type { SplitVendorChunkCache } from './plugins/splitVendorChunk'
95 changes: 95 additions & 0 deletions packages/vite/src/node/plugins/splitVendorChunk.ts
@@ -0,0 +1,95 @@
import type { Plugin } from '../plugin'
import type { OutputOptions, GetManualChunk, GetModuleInfo } from 'rollup'
import { isCSSRequest } from './css'

// Use splitVendorChunkPlugin() to get the same manualChunks strategy as Vite 2.7
// We don't recomment using this strategy as a general solution moving forward
patak-dev marked this conversation as resolved.
Show resolved Hide resolved

// splitVendorChunk is a simple index/vendor strategy that was used in Vite
// until v2.8. It is exposed to let people continue to use it in case it was
// working well for their setups.
// The cache needs to be reset on buildStart for watch mode to work correctly
// Don't use this manualChunks strategy for ssr, lib mode, and 'umd' or 'iife'

export class SplitVendorChunkCache {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class seems unnecessary. The Map object has a clear method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if we will need to expand the cache later. I wanted to expose the cache for the method, not a particular Map that is an implementation detail and may change

cache: Map<string, boolean>
constructor() {
this.cache = new Map<string, boolean>()
}
reset() {
this.cache = new Map<string, boolean>()
}
}

export function splitVendorChunk({
cache = new SplitVendorChunkCache()
}): GetManualChunk {
patak-dev marked this conversation as resolved.
Show resolved Hide resolved
patak-dev marked this conversation as resolved.
Show resolved Hide resolved
return (id, { getModuleInfo }) => {
if (
id.includes('node_modules') &&
!isCSSRequest(id) &&
staticImportedByEntry(id, getModuleInfo, cache.cache)
) {
return 'vendor'
}
}
}

function staticImportedByEntry(
id: string,
getModuleInfo: GetModuleInfo,
cache: Map<string, boolean>,
importStack: string[] = []
): boolean {
if (cache.has(id)) {
return cache.get(id) as boolean
}
if (importStack.includes(id)) {
// circular deps!
cache.set(id, false)
return false
}
const mod = getModuleInfo(id)
if (!mod) {
cache.set(id, false)
return false
}

if (mod.isEntry) {
cache.set(id, true)
return true
}
const someImporterIs = mod.importers.some((importer) =>
staticImportedByEntry(
importer,
getModuleInfo,
cache,
importStack.concat(id)
)
)
cache.set(id, someImporterIs)
return someImporterIs
}

export function splitVendorChunkPlugin(): Plugin {
const cache = new SplitVendorChunkCache()
return {
name: 'vite:split-vendor-chunk',
config(config) {
const build = config.build ?? {}
const format = (build.rollupOptions?.output as OutputOptions)?.format
patak-dev marked this conversation as resolved.
Show resolved Hide resolved
if (!build.ssr && !build.lib && format !== 'umd' && format !== 'iife') {
aleclarson marked this conversation as resolved.
Show resolved Hide resolved
return {
build: {
rollupOptions: {
manualChunks: splitVendorChunk({ cache })
}
}
}
}
},
buildStart() {
cache.reset()
}
}
}