@lomray/vite-ssr-boost 6.4.1 → 7.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/browser/entry.js.map +1 -1
  2. package/cli/helpers/keyboard-input.js.map +1 -1
  3. package/cli.js.map +1 -1
  4. package/components/navigate.js.map +1 -1
  5. package/components/only-client.js.map +1 -1
  6. package/components/render-client.js.map +1 -1
  7. package/components/scroll-to-top.js.map +1 -1
  8. package/components/with-suspense.js.map +1 -1
  9. package/constants/cli-actions.js.map +1 -1
  10. package/constants/cli-shortcuts.js.map +1 -1
  11. package/constants/stream-error.js.map +1 -1
  12. package/context/server.js.map +1 -1
  13. package/helpers/create-focus-only.js.map +1 -1
  14. package/helpers/dev-marker.js.map +1 -1
  15. package/helpers/get-server-state.js.map +1 -1
  16. package/helpers/handle-response.js.map +1 -1
  17. package/helpers/import-route.js.map +1 -1
  18. package/helpers/print-server-info.js.map +1 -1
  19. package/helpers/process-stop.js.map +1 -1
  20. package/helpers/resolve-server-urls.js.map +1 -1
  21. package/helpers/serialize-errors.js.map +1 -1
  22. package/helpers/vite-aliases.js.map +1 -1
  23. package/interfaces/fc-route.js.map +1 -1
  24. package/node/render.js.map +1 -1
  25. package/node/server.js +1 -1
  26. package/node/server.js.map +1 -1
  27. package/node/write-response.js.map +1 -1
  28. package/package.json +29 -21
  29. package/plugins/create-spa-index.js.map +1 -1
  30. package/plugins/handle-custom-entrypoint.js.map +1 -1
  31. package/plugins/make-aliases.js.map +1 -1
  32. package/plugins/normalize-route.js.map +1 -1
  33. package/services/build.js.map +1 -1
  34. package/services/logger.js.map +1 -1
  35. package/services/parse-routes.js.map +1 -1
  36. package/services/path-normalize.js.map +1 -1
  37. package/services/prepare-server.js.map +1 -1
  38. package/services/server-api.js.map +1 -1
  39. package/services/server-config.js.map +1 -1
  40. package/services/ssr-manifest.js.map +1 -1
  41. package/workflow/Dockerfile +1 -1
  42. package/workflow/amplify-manifest.json +1 -1
  43. package/workflow/vercel.vc-config.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-manifest.js","sources":["../../src/services/ssr-manifest.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { Socket } from 'node:net';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport type { RouterState } from 'react-router';\nimport type { Alias, ModuleNode, RenderBuiltAssetUrl } from 'vite';\nimport type { IAsyncRoute } from '@helpers/import-route';\nimport type { IRequestContext } from '@node/render';\nimport type { TRoutesTree } from '@services/parse-routes';\nimport ParseRoutes from '@services/parse-routes';\nimport PathNormalize from '@services/path-normalize';\nimport type ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n buildDir?: string;\n viteAliases?: Alias[];\n basename?: string;\n renderBuiltUrl?: RenderBuiltAssetUrl;\n}\n\ninterface IManifest {\n [path: string]: {\n assets: string[];\n css: string[];\n file: string;\n isEntry?: boolean;\n imports: string[];\n };\n}\n\nenum AssetType {\n style = 'style',\n script = 'script',\n image = 'image',\n font = 'font',\n}\n\ninterface IAsset {\n type: AssetType;\n url: string;\n weight: number;\n isNested: boolean;\n isPreload: boolean;\n content?: string;\n}\n\ntype TAssets = { [id: string]: IAsset };\n\nconst CRLF = '\\r\\n';\n\n/**\n * Working with SSR Manifest file\n */\nclass SsrManifest {\n /**\n * Singleton\n */\n protected static instance: SsrManifest | null = null;\n\n /**\n * Server config\n */\n protected readonly config: ServerConfig;\n\n /**\n * Path normalize service\n */\n protected readonly pathNormalize: PathNormalize;\n\n /**\n * Project root path\n */\n protected readonly root: string;\n\n /**\n * Build dir\n */\n protected readonly buildDir?: string;\n\n /**\n * Client manifest file name\n */\n protected readonly manifestName = 'manifest.json';\n\n /**\n * Assets manifest file name\n */\n protected readonly assetsManifest = 'assets-manifest.json';\n\n /**\n * Vite resolve aliases\n */\n protected readonly viteAliases?: Alias[];\n\n /**\n * Vite base\n */\n protected readonly basename?: string;\n\n /**\n * Vite renderBuiltUrl config func\n */\n protected readonly renderBuiltUrl?: RenderBuiltAssetUrl;\n\n /**\n * Loaded assets manifest file\n */\n protected routesAssets: Record<string, IAsset[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(\n config: ServerConfig,\n { buildDir, viteAliases, basename, renderBuiltUrl }: ISsrManifestParams = {},\n ) {\n this.config = config;\n this.root = config.getParams().root;\n this.buildDir = buildDir;\n this.viteAliases = viteAliases ?? config.getVite()?.config?.resolve.alias;\n this.pathNormalize = new PathNormalize(config, viteAliases);\n this.basename = basename;\n this.renderBuiltUrl = renderBuiltUrl;\n }\n\n /**\n * Get singleton instance\n */\n public static get(config: ServerConfig, params: ISsrManifestParams = {}): SsrManifest {\n if (SsrManifest.instance === null) {\n SsrManifest.instance = new SsrManifest(config, params);\n }\n\n return SsrManifest.instance;\n }\n\n /**\n * Get output dir\n */\n protected getOutDir() {\n return path.resolve(this.root, this.buildDir || '');\n }\n\n /**\n * Get assets manifest file name\n */\n protected getAssetsManifestFile(): string {\n return `${this.getOutDir()}/server/${this.assetsManifest}`;\n }\n\n /**\n * Load client ssr manifest\n */\n protected loadClientManifest(): IManifest {\n const clientManifestDir = path.resolve(this.root, `${this.buildDir || ''}/client/.vite`);\n const clientSsrManifest = `${clientManifestDir}/${this.manifestName}`;\n\n if (!fs.existsSync(clientSsrManifest)) {\n return {};\n }\n\n const result = JSON.parse(\n fs.readFileSync(clientSsrManifest, { encoding: 'utf-8' }),\n ) as IManifest;\n\n fs.rmSync(clientSsrManifest);\n\n // try to remove empty .vite dir\n if (fs.readdirSync(clientManifestDir).length === 0) {\n fs.rmSync(clientManifestDir, { recursive: true });\n }\n\n return result;\n }\n\n /**\n * Load assets manifest\n */\n protected loadAssetsManifest(): Record<string, IAsset[]> {\n if (this.routesAssets !== null) {\n return this.routesAssets;\n }\n\n const manifestFile = this.getAssetsManifestFile();\n\n if (!fs.existsSync(manifestFile)) {\n return {};\n }\n\n this.routesAssets = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' })) as Record<\n string,\n IAsset[]\n >;\n\n return this.routesAssets;\n }\n\n /**\n * Same as 'getAsyncRoutesIds' but for routes tree from 'ParseRoutes'\n */\n protected getRoutesTreeIds(\n routes: TRoutesTree[],\n index?: string,\n ): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n\n routes.forEach((route, routeIndex) => {\n const routeId = [index, String(routeIndex)].filter(Boolean).join('-');\n\n if (route.import) {\n result[routeId] = this.pathNormalize.getAppPath(route.import);\n }\n\n if (route.children.length > 0) {\n Object.assign(result, this.getRoutesTreeIds(route.children, routeId));\n }\n });\n\n return result;\n }\n\n /**\n * Sort assets\n */\n protected sortAssets(assets: IAsset[]): IAsset[] {\n return assets.sort((a, b) =>\n a.weight === b.weight ? Number(a.isNested) - Number(b.isNested) : a.weight - b.weight,\n );\n }\n\n /**\n * Get recursive module assets\n */\n protected getRouteAssets(\n manifest: IManifest,\n module: IManifest[string],\n isNested = false,\n ): Record<string, IAsset> {\n const rootAssets = [...(module?.assets ?? []), ...(module?.css ?? []), module?.file];\n\n const assets = rootAssets.reduce(\n (res, asset) => {\n if (asset) {\n const type = this.getAssetType(asset);\n const isEntry = module.isEntry && module.file === asset;\n\n // keep only js,css,image,fonts files\n if (type) {\n const filename = path.posix.normalize(`${this.basename}/${asset}`);\n const modifiedFilename = this.renderBuiltUrl?.(filename, {\n type: 'asset',\n ssr: true,\n hostId: '',\n hostType: filename.split('.').at(-1)?.toLowerCase() as 'js',\n });\n\n res[asset] = {\n url: typeof modifiedFilename === 'string' ? modifiedFilename : filename,\n weight: isEntry ? 1.9 : this.getAssetWeight(asset),\n type,\n isNested,\n isPreload: !isEntry,\n };\n }\n }\n\n return res;\n },\n {} as Record<string, IAsset>,\n );\n\n // nested assets\n if (module?.imports?.length) {\n module.imports.forEach((nestedAsset) => {\n const nestedModule = manifest[nestedAsset];\n\n if (nestedModule) {\n Object.assign(assets, this.getRouteAssets(manifest, nestedModule, true));\n }\n });\n }\n\n return assets;\n }\n\n /**\n * Build routes manifest file\n */\n public buildRoutesManifest(): void {\n const manifest = this.loadClientManifest();\n const routesService = new ParseRoutes(this.config, this.viteAliases);\n const routesPaths = this.getRoutesTreeIds(routesService.parse());\n\n const postfixes = this.pathNormalize.getImportPostfix();\n const result: Record<string, IAsset[]> = {};\n\n // find route assets\n Object.entries(routesPaths).forEach(([routeId, routePath]) => {\n const routePostfix = postfixes.find((postfix) => {\n const filePath = `${routePath}${postfix}`;\n\n return manifest[filePath] !== undefined;\n });\n const routeFile = `${routePath}${routePostfix || ''}`;\n const routeMeta = manifest[routeFile];\n\n result[routeId] = this.sortAssets(Object.values(this.getRouteAssets(manifest, routeMeta)));\n });\n\n fs.writeFileSync(this.getAssetsManifestFile(), JSON.stringify(result, null, 2), {\n encoding: 'utf-8',\n });\n }\n\n /**\n * Get route assets\n */\n protected getAssets(routes?: RouterState['matches']): IAsset[] {\n if (this.config.getVite()) {\n return this.getAssetsDev(routes);\n }\n\n const routeIds = routes?.map(({ route }) => route.id).filter(Boolean) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n const routesAssets = this.loadAssetsManifest();\n\n return this.sortAssets(\n routeIds\n .map((routeId) => routesAssets[routeId])\n .flat()\n .filter(Boolean),\n );\n }\n\n /**\n * Get development route assets\n */\n protected getAssetsDev(routes?: RouterState['matches']): IAsset[] {\n const routeIds =\n (routes\n ?.map(({ route }) => this.pathNormalize.getAppPath((route as IAsyncRoute)?.pathId, true))\n .filter(Boolean) as string[]) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n let assets: TAssets = {};\n const postfixes = this.pathNormalize.getImportPostfix();\n const rootId = path.resolve(\n this.root,\n this.config.getPluginConfig()?.clientFile ?? 'client.ts',\n );\n\n [rootId, ...routeIds].forEach((moduleId) => {\n for (const ext of postfixes) {\n const module = this.config.getVite()?.moduleGraph.getModuleById(`${moduleId}${ext}`);\n\n if (module) {\n assets = { ...assets, ...this.getModuleAssets(module) };\n break;\n }\n }\n });\n\n return Object.values(assets);\n }\n\n /**\n * Get module assets\n */\n protected getModuleAssets(module?: ModuleNode, skipModules: Set<string> = new Set()): TAssets {\n if (!module?.clientImportedModules.size || skipModules.has(module.file!)) {\n return {};\n }\n\n let assets: TAssets = {};\n\n skipModules.add(module.file!);\n\n module.clientImportedModules.forEach((subModule) => {\n const { file, clientImportedModules, transformResult } = subModule;\n const ext = file?.split('.').at(-1);\n\n if (file && ext && ['css', 'scss'].includes(ext)) {\n // @TODO investigate better method?\n const code = transformResult?.code.match(/__vite__css\\s+=\\s+\"(?<css>.+)\"/)?.groups?.css;\n\n if (code) {\n try {\n assets[file] = {\n type: AssetType.style,\n url: file,\n weight: this.getAssetWeight(file),\n content: (JSON.parse(`{\"style\": \"${code}\"}`) as { style: string }).style,\n isNested: Boolean(skipModules.size),\n isPreload: false,\n };\n } catch (e) {\n console.warn(chalk.yellowBright('Failed to parse style: ', file));\n }\n }\n } else if (clientImportedModules.size) {\n assets = {\n ...assets,\n ...this.getModuleAssets(subModule, skipModules),\n };\n }\n });\n\n return assets;\n }\n\n /**\n * Get asset weight\n */\n protected getAssetWeight(asset: string): number {\n const type = this.getAssetType(asset);\n\n switch (type) {\n case AssetType.style:\n return 1;\n\n case AssetType.script:\n return 2;\n\n default:\n return 3;\n }\n }\n\n /**\n * Get asset type\n */\n protected getAssetType(asset: string): AssetType | null {\n const ext = asset.split('.').at(-1)?.toLowerCase();\n\n switch (ext) {\n case 'css':\n case 'scss':\n return AssetType.style;\n\n case 'js':\n return AssetType.script;\n\n case 'svg':\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'webp':\n case 'gif':\n case 'ico':\n return AssetType.image;\n\n case 'ttf':\n case 'otf':\n case 'woff':\n case 'woff2':\n return AssetType.font;\n\n default:\n return null;\n }\n }\n\n /**\n * Write 103 Early Hits header\n */\n public writeEarlyHits(assets: IAsset[], socket: Socket): void {\n socket.write(`HTTP/1.1 103 Early Hints${CRLF}`);\n assets.forEach(({ type, url }) => {\n if (!type || !['style', 'script'].includes(type)) {\n return;\n }\n\n socket.write(`Link: <${url}>; rel=preload; as=${type}${CRLF}`);\n });\n socket.write(CRLF);\n }\n\n /**\n * Inject route assets to head html\n */\n public injectAssets({ routerContext, html, res, hasEarlyHints = false }: IRequestContext): void {\n const assets = this.getAssets(routerContext?.matches);\n const htmlAssets = assets\n .map(({ type, url, isPreload, content = '' }) => {\n switch (type) {\n case AssetType.style:\n return this.config.getVite()\n ? `<style data-vite-dev-id=\"${url}\">${content}</style>`\n : `<link rel=\"stylesheet\" href=\"${url}\">`;\n\n case AssetType.script:\n return isPreload\n ? this.config.isModulePreload\n ? // can reduce lighthouse performance\n `<link rel=\"modulepreload\" as=\"script\" crossorigin href=\"${url}\">`\n : null\n : `<script async type=\"module\" crossorigin src=\"${url}\"></script>`;\n }\n\n return null;\n })\n .filter(Boolean);\n\n html.header = html.header.replace('</head>', `${htmlAssets.join('\\n')}</head>`);\n\n if (hasEarlyHints && htmlAssets.length && res.socket) {\n this.writeEarlyHits(assets, res.socket);\n }\n }\n}\n\nexport default SsrManifest;\n"],"names":["AssetType","CRLF","SsrManifest","static","config","pathNormalize","root","buildDir","manifestName","assetsManifest","viteAliases","basename","renderBuiltUrl","routesAssets","constructor","this","getParams","getVite","resolve","alias","PathNormalize","params","instance","getOutDir","path","getAssetsManifestFile","loadClientManifest","clientManifestDir","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","readdirSync","length","recursive","loadAssetsManifest","manifestFile","getRoutesTreeIds","routes","index","forEach","route","routeIndex","routeId","String","filter","Boolean","join","import","getAppPath","children","Object","assign","sortAssets","assets","sort","a","b","weight","Number","isNested","getRouteAssets","manifest","module","css","file","reduce","res","asset","type","getAssetType","isEntry","filename","posix","normalize","modifiedFilename","ssr","hostId","hostType","split","at","toLowerCase","url","getAssetWeight","isPreload","imports","nestedAsset","nestedModule","buildRoutesManifest","routesService","ParseRoutes","routesPaths","postfixes","getImportPostfix","entries","routePath","routePostfix","find","postfix","undefined","routeMeta","values","writeFileSync","stringify","getAssets","getAssetsDev","routeIds","map","id","flat","pathId","getPluginConfig","clientFile","moduleId","ext","moduleGraph","getModuleById","getModuleAssets","skipModules","Set","clientImportedModules","size","has","add","subModule","transformResult","includes","code","match","groups","style","content","e","console","warn","chalk","yellowBright","script","image","font","writeEarlyHits","socket","write","injectAssets","routerContext","html","hasEarlyHints","matches","htmlAssets","isModulePreload","header","replace"],"mappings":"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"}
1
+ {"version":3,"file":"ssr-manifest.js","sources":["../../src/services/ssr-manifest.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { Socket } from 'node:net';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport type { RouterState } from 'react-router';\nimport type { Alias, ModuleNode, RenderBuiltAssetUrl } from 'vite';\nimport type { IAsyncRoute } from '@helpers/import-route';\nimport type { IRequestContext } from '@node/render';\nimport type { TRoutesTree } from '@services/parse-routes';\nimport ParseRoutes from '@services/parse-routes';\nimport PathNormalize from '@services/path-normalize';\nimport type ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n buildDir?: string;\n viteAliases?: Alias[];\n basename?: string;\n renderBuiltUrl?: RenderBuiltAssetUrl;\n}\n\ninterface IManifest {\n [path: string]: {\n assets: string[];\n css: string[];\n file: string;\n isEntry?: boolean;\n imports: string[];\n };\n}\n\nenum AssetType {\n style = 'style',\n script = 'script',\n image = 'image',\n font = 'font',\n}\n\ninterface IAsset {\n type: AssetType;\n url: string;\n weight: number;\n isNested: boolean;\n isPreload: boolean;\n content?: string;\n}\n\ntype TAssets = { [id: string]: IAsset };\n\nconst CRLF = '\\r\\n';\n\n/**\n * Working with SSR Manifest file\n */\nclass SsrManifest {\n /**\n * Singleton\n */\n protected static instance: SsrManifest | null = null;\n\n /**\n * Server config\n */\n protected readonly config: ServerConfig;\n\n /**\n * Path normalize service\n */\n protected readonly pathNormalize: PathNormalize;\n\n /**\n * Project root path\n */\n protected readonly root: string;\n\n /**\n * Build dir\n */\n protected readonly buildDir?: string;\n\n /**\n * Client manifest file name\n */\n protected readonly manifestName = 'manifest.json';\n\n /**\n * Assets manifest file name\n */\n protected readonly assetsManifest = 'assets-manifest.json';\n\n /**\n * Vite resolve aliases\n */\n protected readonly viteAliases?: Alias[];\n\n /**\n * Vite base\n */\n protected readonly basename?: string;\n\n /**\n * Vite renderBuiltUrl config func\n */\n protected readonly renderBuiltUrl?: RenderBuiltAssetUrl;\n\n /**\n * Loaded assets manifest file\n */\n protected routesAssets: Record<string, IAsset[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(\n config: ServerConfig,\n { buildDir, viteAliases, basename, renderBuiltUrl }: ISsrManifestParams = {},\n ) {\n this.config = config;\n this.root = config.getParams().root;\n this.buildDir = buildDir;\n this.viteAliases = viteAliases ?? config.getVite()?.config?.resolve.alias;\n this.pathNormalize = new PathNormalize(config, viteAliases);\n this.basename = basename;\n this.renderBuiltUrl = renderBuiltUrl;\n }\n\n /**\n * Get singleton instance\n */\n public static get(config: ServerConfig, params: ISsrManifestParams = {}): SsrManifest {\n if (SsrManifest.instance === null) {\n SsrManifest.instance = new SsrManifest(config, params);\n }\n\n return SsrManifest.instance;\n }\n\n /**\n * Get output dir\n */\n protected getOutDir() {\n return path.resolve(this.root, this.buildDir || '');\n }\n\n /**\n * Get assets manifest file name\n */\n protected getAssetsManifestFile(): string {\n return `${this.getOutDir()}/server/${this.assetsManifest}`;\n }\n\n /**\n * Load client ssr manifest\n */\n protected loadClientManifest(): IManifest {\n const clientManifestDir = path.resolve(this.root, `${this.buildDir || ''}/client/.vite`);\n const clientSsrManifest = `${clientManifestDir}/${this.manifestName}`;\n\n if (!fs.existsSync(clientSsrManifest)) {\n return {};\n }\n\n const result = JSON.parse(\n fs.readFileSync(clientSsrManifest, { encoding: 'utf-8' }),\n ) as IManifest;\n\n fs.rmSync(clientSsrManifest);\n\n // try to remove empty .vite dir\n if (fs.readdirSync(clientManifestDir).length === 0) {\n fs.rmSync(clientManifestDir, { recursive: true });\n }\n\n return result;\n }\n\n /**\n * Load assets manifest\n */\n protected loadAssetsManifest(): Record<string, IAsset[]> {\n if (this.routesAssets !== null) {\n return this.routesAssets;\n }\n\n const manifestFile = this.getAssetsManifestFile();\n\n if (!fs.existsSync(manifestFile)) {\n return {};\n }\n\n this.routesAssets = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' })) as Record<\n string,\n IAsset[]\n >;\n\n return this.routesAssets;\n }\n\n /**\n * Same as 'getAsyncRoutesIds' but for routes tree from 'ParseRoutes'\n */\n protected getRoutesTreeIds(\n routes: TRoutesTree[],\n index?: string,\n ): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n\n routes.forEach((route, routeIndex) => {\n const routeId = [index, String(routeIndex)].filter(Boolean).join('-');\n\n if (route.import) {\n result[routeId] = this.pathNormalize.getAppPath(route.import);\n }\n\n if (route.children.length > 0) {\n Object.assign(result, this.getRoutesTreeIds(route.children, routeId));\n }\n });\n\n return result;\n }\n\n /**\n * Sort assets\n */\n protected sortAssets(assets: IAsset[]): IAsset[] {\n return assets.sort((a, b) =>\n a.weight === b.weight ? Number(a.isNested) - Number(b.isNested) : a.weight - b.weight,\n );\n }\n\n /**\n * Get recursive module assets\n */\n protected getRouteAssets(\n manifest: IManifest,\n module: IManifest[string],\n isNested = false,\n ): Record<string, IAsset> {\n const rootAssets = [...(module?.assets ?? []), ...(module?.css ?? []), module?.file];\n\n const assets = rootAssets.reduce(\n (res, asset) => {\n if (asset) {\n const type = this.getAssetType(asset);\n const isEntry = module.isEntry && module.file === asset;\n\n // keep only js,css,image,fonts files\n if (type) {\n const filename = path.posix.normalize(`${this.basename}/${asset}`);\n const modifiedFilename = this.renderBuiltUrl?.(filename, {\n type: 'asset',\n ssr: true,\n hostId: '',\n hostType: filename.split('.').at(-1)?.toLowerCase() as 'js',\n });\n\n res[asset] = {\n url: typeof modifiedFilename === 'string' ? modifiedFilename : filename,\n weight: isEntry ? 1.9 : this.getAssetWeight(asset),\n type,\n isNested,\n isPreload: !isEntry,\n };\n }\n }\n\n return res;\n },\n {} as Record<string, IAsset>,\n );\n\n // nested assets\n if (module?.imports?.length) {\n module.imports.forEach((nestedAsset) => {\n const nestedModule = manifest[nestedAsset];\n\n if (nestedModule) {\n Object.assign(assets, this.getRouteAssets(manifest, nestedModule, true));\n }\n });\n }\n\n return assets;\n }\n\n /**\n * Build routes manifest file\n */\n public buildRoutesManifest(): void {\n const manifest = this.loadClientManifest();\n const routesService = new ParseRoutes(this.config, this.viteAliases);\n const routesPaths = this.getRoutesTreeIds(routesService.parse());\n\n const postfixes = this.pathNormalize.getImportPostfix();\n const result: Record<string, IAsset[]> = {};\n\n // find route assets\n Object.entries(routesPaths).forEach(([routeId, routePath]) => {\n const routePostfix = postfixes.find((postfix) => {\n const filePath = `${routePath}${postfix}`;\n\n return manifest[filePath] !== undefined;\n });\n const routeFile = `${routePath}${routePostfix || ''}`;\n const routeMeta = manifest[routeFile];\n\n result[routeId] = this.sortAssets(Object.values(this.getRouteAssets(manifest, routeMeta)));\n });\n\n fs.writeFileSync(this.getAssetsManifestFile(), JSON.stringify(result, null, 2), {\n encoding: 'utf-8',\n });\n }\n\n /**\n * Get route assets\n */\n protected getAssets(routes?: RouterState['matches']): IAsset[] {\n if (this.config.getVite()) {\n return this.getAssetsDev(routes);\n }\n\n const routeIds = routes?.map(({ route }) => route.id).filter(Boolean) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n const routesAssets = this.loadAssetsManifest();\n\n return this.sortAssets(\n routeIds\n .map((routeId) => routesAssets[routeId])\n .flat()\n .filter(Boolean),\n );\n }\n\n /**\n * Get development route assets\n */\n protected getAssetsDev(routes?: RouterState['matches']): IAsset[] {\n const routeIds =\n (routes\n ?.map(({ route }) => this.pathNormalize.getAppPath((route as IAsyncRoute)?.pathId, true))\n .filter(Boolean) as string[]) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n let assets: TAssets = {};\n const postfixes = this.pathNormalize.getImportPostfix();\n const rootId = path.resolve(\n this.root,\n this.config.getPluginConfig()?.clientFile ?? 'client.ts',\n );\n\n [rootId, ...routeIds].forEach((moduleId) => {\n for (const ext of postfixes) {\n const module = this.config.getVite()?.moduleGraph.getModuleById(`${moduleId}${ext}`);\n\n if (module) {\n assets = { ...assets, ...this.getModuleAssets(module) };\n break;\n }\n }\n });\n\n return Object.values(assets);\n }\n\n /**\n * Get module assets\n */\n protected getModuleAssets(module?: ModuleNode, skipModules: Set<string> = new Set()): TAssets {\n if (!module?.clientImportedModules.size || skipModules.has(module.file!)) {\n return {};\n }\n\n let assets: TAssets = {};\n\n skipModules.add(module.file!);\n\n module.clientImportedModules.forEach((subModule) => {\n const { file, clientImportedModules, transformResult } = subModule;\n const ext = file?.split('.').at(-1);\n\n if (file && ext && ['css', 'scss'].includes(ext)) {\n // @TODO investigate better method?\n const code = transformResult?.code.match(/__vite__css\\s+=\\s+\"(?<css>.+)\"/)?.groups?.css;\n\n if (code) {\n try {\n assets[file] = {\n type: AssetType.style,\n url: file,\n weight: this.getAssetWeight(file),\n content: (JSON.parse(`{\"style\": \"${code}\"}`) as { style: string }).style,\n isNested: Boolean(skipModules.size),\n isPreload: false,\n };\n } catch (e) {\n console.warn(chalk.yellowBright('Failed to parse style: ', file));\n }\n }\n } else if (clientImportedModules.size) {\n assets = {\n ...assets,\n ...this.getModuleAssets(subModule, skipModules),\n };\n }\n });\n\n return assets;\n }\n\n /**\n * Get asset weight\n */\n protected getAssetWeight(asset: string): number {\n const type = this.getAssetType(asset);\n\n switch (type) {\n case AssetType.style:\n return 1;\n\n case AssetType.script:\n return 2;\n\n default:\n return 3;\n }\n }\n\n /**\n * Get asset type\n */\n protected getAssetType(asset: string): AssetType | null {\n const ext = asset.split('.').at(-1)?.toLowerCase();\n\n switch (ext) {\n case 'css':\n case 'scss':\n return AssetType.style;\n\n case 'js':\n return AssetType.script;\n\n case 'svg':\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'webp':\n case 'gif':\n case 'ico':\n return AssetType.image;\n\n case 'ttf':\n case 'otf':\n case 'woff':\n case 'woff2':\n return AssetType.font;\n\n default:\n return null;\n }\n }\n\n /**\n * Write 103 Early Hits header\n */\n public writeEarlyHits(assets: IAsset[], socket: Socket): void {\n socket.write(`HTTP/1.1 103 Early Hints${CRLF}`);\n assets.forEach(({ type, url }) => {\n if (!type || !['style', 'script'].includes(type)) {\n return;\n }\n\n socket.write(`Link: <${url}>; rel=preload; as=${type}${CRLF}`);\n });\n socket.write(CRLF);\n }\n\n /**\n * Inject route assets to head html\n */\n public injectAssets({ routerContext, html, res, hasEarlyHints = false }: IRequestContext): void {\n const assets = this.getAssets(routerContext?.matches);\n const htmlAssets = assets\n .map(({ type, url, isPreload, content = '' }) => {\n switch (type) {\n case AssetType.style:\n return this.config.getVite()\n ? `<style data-vite-dev-id=\"${url}\">${content}</style>`\n : `<link rel=\"stylesheet\" href=\"${url}\">`;\n\n case AssetType.script:\n return isPreload\n ? this.config.isModulePreload\n ? // can reduce lighthouse performance\n `<link rel=\"modulepreload\" as=\"script\" crossorigin href=\"${url}\">`\n : null\n : `<script async type=\"module\" crossorigin src=\"${url}\"></script>`;\n }\n\n return null;\n })\n .filter(Boolean);\n\n html.header = html.header.replace('</head>', `${htmlAssets.join('\\n')}</head>`);\n\n if (hasEarlyHints && htmlAssets.length && res.socket) {\n this.writeEarlyHits(assets, res.socket);\n }\n }\n}\n\nexport default SsrManifest;\n"],"names":["AssetType","CRLF","SsrManifest","static","config","pathNormalize","root","buildDir","manifestName","assetsManifest","viteAliases","basename","renderBuiltUrl","routesAssets","constructor","this","getParams","getVite","resolve","alias","PathNormalize","params","instance","getOutDir","path","getAssetsManifestFile","loadClientManifest","clientManifestDir","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","readdirSync","length","recursive","loadAssetsManifest","manifestFile","getRoutesTreeIds","routes","index","forEach","route","routeIndex","routeId","String","filter","Boolean","join","import","getAppPath","children","Object","assign","sortAssets","assets","sort","a","b","weight","Number","isNested","getRouteAssets","manifest","module","css","file","reduce","res","asset","type","getAssetType","isEntry","filename","posix","normalize","modifiedFilename","ssr","hostId","hostType","split","at","toLowerCase","url","getAssetWeight","isPreload","imports","nestedAsset","nestedModule","buildRoutesManifest","routesService","ParseRoutes","routesPaths","postfixes","getImportPostfix","entries","routePath","routePostfix","find","postfix","undefined","routeMeta","values","writeFileSync","stringify","getAssets","getAssetsDev","routeIds","map","id","flat","pathId","getPluginConfig","clientFile","moduleId","ext","moduleGraph","getModuleById","getModuleAssets","skipModules","Set","clientImportedModules","size","has","add","subModule","transformResult","includes","code","match","groups","style","content","e","console","warn","chalk","yellowBright","script","image","font","writeEarlyHits","socket","write","injectAssets","routerContext","html","hasEarlyHints","matches","htmlAssets","isModulePreload","header","replace"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- FROM node:20.10.0-alpine
1
+ FROM node:22.21.0-alpine
2
2
 
3
3
  LABEL org.opencontainers.image.title="vite-ssr-boost"
4
4
  LABEL org.opencontainers.image.description="Container to run pre-built 'vite-ssr-boost' applications"
@@ -24,7 +24,7 @@
24
24
  "computeResources": [
25
25
  {
26
26
  "name": "default",
27
- "runtime": "nodejs18.x",
27
+ "runtime": "nodejs22.x",
28
28
  "entrypoint": "build/server/start.js"
29
29
  }
30
30
  ]
@@ -1,5 +1,5 @@
1
1
  {
2
- "runtime": "nodejs18.x",
2
+ "runtime": "nodejs22.x",
3
3
  "handler": "index.js",
4
4
  "launcherType": "Nodejs",
5
5
  "shouldAddHelpers": true