UNPKG

polen

Version:

A framework for delightful GraphQL developer portals

177 lines (165 loc) 5.94 kB
import type { Config } from '#api/config/index' import type { PolenBuildManifest } from '#api/static/manifest' import { Vite } from '#dep/vite/index' import { ViteVirtual } from '#lib/vite-virtual/index' import { debugPolen } from '#singletons/debug' import { Fs, Path } from '@wollybeard/kit' import packageJson from '../../../../package.json' with { type: 'json' } import { isKitUnusedExternalImport, isRadixModuleLevelDirective } from '../log-filters.js' import { polenVirtual } from '../vi.js' export const Build = (config: Config.Config): Vite.Plugin[] => { const debug = debugPolen.sub(`vite-build`) debug(`construct`) // let viteConfigResolved: Vite.ResolvedConfig // const outDir = Path.join(config.paths.project.rootDir, `dist`) return [ Manifest(config), BuildManifest(config), { name: `polen:build-client`, apply: `build`, applyToEnvironment: Vite.isEnvironmentClient, // HACK: For some reason the ?url import doesn't lead to a rewrite in the build. // Furthermore we need to rely on the manifest to get its final name because it is // generated by the client build before the server build. // However, we still need the asset in development. // But we cannot exclude the import in build. // So this does that for us but it is really hacky. // FIXME // 1. Raise issue about having ?url lead to expected build path rewrite? // 2. And: Move asset generation to server build? // 3. And/or: Use Vite Environments API? generateBundle(_, bundle, isWrite) { if (isWrite) { for (const chunkOrAsset of Object.values(bundle)) { if (chunkOrAsset.type === `asset` && chunkOrAsset.names.includes(`entry.client.jsx`)) { delete bundle[chunkOrAsset.fileName] } } } }, onLog(_, message) { if (isRadixModuleLevelDirective(message)) return if (isKitUnusedExternalImport(message)) return }, config() { return { environments: { client: { build: { manifest: true, rollupOptions: { input: [config.paths.framework.template.absolute.client.entrypoint], external: id => id.startsWith(`node:`), onwarn(message) { if (isKitUnusedExternalImport(message)) return }, }, }, }, }, } }, }, { name: `polen-ssr-build`, apply: `build`, applyToEnvironment: Vite.isEnvironmentSsr, config() { return { // Have to configure this here?? // @see https://github.com/vitejs/vite/issues/20098 ssr: { noExternal: true, }, environments: { ssr: { build: { // NO EFFECT (see above) // Bundle all dependencies instead of externalizing them // noExternal: true, // The SSR build will follow the client build, and emptying the dir would lose the output of the client build. emptyOutDir: false, rollupOptions: { input: [config.paths.framework.template.absolute.server.entrypoint], output: { entryFileNames: config.paths.project.relative.build.relative.serverEntrypoint, }, }, }, }, }, } }, onLog(_, message) { if (isKitUnusedExternalImport(message)) return }, // generateBundle(_, bundle, isWrite) { // if (isWrite) { // for (const chunkOrAsset of Object.values(bundle)) { // console.log(chunkOrAsset) // if (chunkOrAsset.type === `chunk`) { // if (chunkOrAsset.facadeModuleId === viClientManifest.resolved) { // delete bundle[chunkOrAsset.fileName] // } // } // } // } // }, async closeBundle() { /** * clean up the manifest. Was generated by client. For server build. Not needed after (unless debugging). */ if (!config.advanced.debug) { await Fs.remove(Path.join(config.paths.project.absolute.build.root, `.vite`)) } }, }, ] } const viClientManifest = polenVirtual([`vite`, `client`, `manifest`]) const Manifest = (config: Config.Config): Vite.Plugin => { let configEnv: Vite.ConfigEnv return { name: `polen-manifest`, config(_, configEnv_) { configEnv = configEnv_ }, ...ViteVirtual.IdentifiedLoader.toHooks( { identifier: viClientManifest, loader: async () => { // In development just return an empty manifest if (configEnv.mode === Vite.ModeName.development) { return `export default {}` } const manifestPath = Path.join(config.paths.project.absolute.build.root, `.vite`, `manifest.json`) const module = await import(manifestPath, { with: { type: `json` } }) as { default: Vite.Manifest } return `export default ${JSON.stringify(module.default)}` }, }, ), } } const BuildManifest = (config: Config.Config): Vite.Plugin => { return { name: `polen:build-manifest`, apply: `build`, applyToEnvironment: Vite.isEnvironmentClient, async generateBundle() { const manifest: PolenBuildManifest = { type: config.build.architecture === `ssr` ? `ssr` : `ssg`, version: packageJson.version, basePath: config.build.base ?? `/`, } // Emit the manifest as an asset this.emitFile({ type: `asset`, fileName: `.polen/build.json`, source: JSON.stringify(manifest, null, 2), }) }, } }