sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
99 lines (83 loc) • 2.55 kB
text/typescript
import {type ChunkMetadata, type Plugin} from 'vite'
import {renderDocument} from '../renderDocument'
import {type SanityMonorepo} from '../sanityMonorepo'
interface ViteOutputBundle {
[fileName: string]: ViteRenderedChunk | ViteRenderedAsset
}
interface ViteRenderedAsset {
type: 'asset'
}
interface ViteRenderedChunk {
type: 'chunk'
name: string
fileName: string
facadeModuleId: string | null
code: string
imports: string[]
viteMetadata: ChunkMetadata
}
const entryChunkId = '.sanity/runtime/app.js'
export function sanityBuildEntries(options: {
cwd: string
monorepo: SanityMonorepo | undefined
basePath: string
}): Plugin {
const {cwd, monorepo, basePath} = options
return {
name: 'sanity/server/build-entries',
apply: 'build',
buildStart() {
this.emitFile({
type: 'chunk',
id: entryChunkId,
name: 'sanity',
})
},
async generateBundle(_options, outputBundle) {
const bundle = outputBundle as unknown as ViteOutputBundle
const entryFile = Object.values(bundle).find(
(file) =>
file.type === 'chunk' &&
file.name === 'sanity' &&
file.facadeModuleId?.endsWith(entryChunkId),
)
if (!entryFile) {
throw new Error(`Failed to find entry file in bundle (${entryChunkId})`)
}
if (entryFile.type !== 'chunk') {
throw new Error('Entry file is not a chunk')
}
const entryFileName = entryFile.fileName
const entryPath = [basePath.replace(/\/+$/, ''), entryFileName].join('/')
let css: string[] = []
if (entryFile.viteMetadata?.importedCss) {
// Check all the top-level imports of the entryPoint to see if they have
// static CSS assets that need loading
css = [...entryFile.viteMetadata.importedCss]
for (const key of entryFile.imports) {
// Traverse all CSS assets that isn't loaded by the runtime and
// need <link> tags in the HTML template
const entry = bundle[key]
const importedCss =
entry && entry.type === 'chunk' ? entry.viteMetadata.importedCss : undefined
if (importedCss) {
css.push(...importedCss)
}
}
}
this.emitFile({
type: 'asset',
fileName: 'index.html',
source: await renderDocument({
monorepo,
studioRootPath: cwd,
props: {
basePath,
entryPath,
css,
},
}),
})
},
}
}