vite
Version:
Native-ESM powered web dev build tool
124 lines (103 loc) • 3.35 kB
text/typescript
import path from 'path'
import { OutputChunk } from 'rollup'
import { ResolvedConfig } from '..'
import { Plugin } from '../plugin'
import { chunkToEmittedCssFileMap } from './css'
import { chunkToEmittedAssetsMap } from './asset'
import { normalizePath } from '../utils'
export type Manifest = Record<string, ManifestChunk>
export interface ManifestChunk {
src?: string
file: string
css?: string[]
assets?: string[]
isEntry?: boolean
isDynamicEntry?: boolean
imports?: string[]
dynamicImports?: string[]
}
export function manifestPlugin(config: ResolvedConfig): Plugin {
const manifest: Manifest = {}
let outputCount: number
return {
name: 'vite:manifest',
buildStart() {
outputCount = 0
},
generateBundle({ format }, bundle) {
function getChunkName(chunk: OutputChunk) {
if (chunk.facadeModuleId) {
let name = normalizePath(
path.relative(config.root, chunk.facadeModuleId)
)
if (format === 'system' && !chunk.name.includes('-legacy')) {
const ext = path.extname(name)
name = name.slice(0, -ext.length) + `-legacy` + ext
}
return name
} else {
return `_` + path.basename(chunk.fileName)
}
}
function getInternalImports(imports: string[]): string[] {
const filteredImports: string[] = []
for (const file of imports) {
if (bundle[file] === undefined) {
continue
}
filteredImports.push(getChunkName(bundle[file] as OutputChunk))
}
return filteredImports
}
function createChunk(chunk: OutputChunk): ManifestChunk {
const manifestChunk: ManifestChunk = {
file: chunk.fileName
}
if (chunk.facadeModuleId) {
manifestChunk.src = getChunkName(chunk)
}
if (chunk.isEntry) {
manifestChunk.isEntry = true
}
if (chunk.isDynamicEntry) {
manifestChunk.isDynamicEntry = true
}
if (chunk.imports.length) {
const internalImports = getInternalImports(chunk.imports)
if (internalImports.length > 0) {
manifestChunk.imports = internalImports
}
}
if (chunk.dynamicImports.length) {
const internalImports = getInternalImports(chunk.dynamicImports)
if (internalImports.length > 0) {
manifestChunk.dynamicImports = internalImports
}
}
const cssFiles = chunkToEmittedCssFileMap.get(chunk)
if (cssFiles) {
manifestChunk.css = [...cssFiles]
}
const assets = chunkToEmittedAssetsMap.get(chunk)
if (assets) [(manifestChunk.assets = [...assets])]
return manifestChunk
}
for (const file in bundle) {
const chunk = bundle[file]
if (chunk.type === 'chunk') {
manifest[getChunkName(chunk)] = createChunk(chunk)
}
}
outputCount++
const output = config.build.rollupOptions?.output
const outputLength = Array.isArray(output) ? output.length : 1
if (outputCount >= outputLength) {
this.emitFile({
fileName: `manifest.json`,
type: 'asset',
source: JSON.stringify(manifest, null, 2)
})
}
}
}
}