@lomray/vite-ssr-boost 2.0.3 → 2.1.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.
- package/README.md +2 -3
- package/cli/run-prod.d.ts +2 -1
- package/cli/run-prod.js +1 -1
- package/cli/run-prod.js.map +1 -1
- package/cli.js +1 -1
- package/cli.js.map +1 -1
- package/package.json +11 -15
- package/plugin.d.ts +2 -2
- package/plugin.js +1 -1
- package/plugin.js.map +1 -1
- package/services/prepare-server.js +1 -1
- package/services/prepare-server.js.map +1 -1
- package/services/server-config.d.ts +4 -0
- package/services/server-config.js +1 -1
- package/services/server-config.js.map +1 -1
- package/services/ssr-manifest.d.ts +7 -0
- package/services/ssr-manifest.js +1 -1
- package/services/ssr-manifest.js.map +1 -1
- package/plugins/make-aliases.d.ts +0 -11
- package/plugins/make-aliases.js +0 -2
- package/plugins/make-aliases.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,9 +22,8 @@
|
|
|
22
22
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=vulnerabilities" alt="Vulnerabilities">
|
|
23
23
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=bugs" alt="Bugs">
|
|
24
24
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=ncloc" alt="Lines of Code">
|
|
25
|
-
<img src="https://img.shields.io/npm/l/@lomray/vite-ssr-boost" alt="size">
|
|
26
|
-
<img src="https://img.shields.io/npm/v/@lomray/vite-ssr-boost?label=semantic%20release&logo=semantic-release" alt="semantic version">
|
|
27
25
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=coverage" alt="code coverage">
|
|
26
|
+
<img src="https://img.shields.io/npm/v/@lomray/vite-ssr-boost?label=semantic%20release&logo=semantic-release" alt="semantic version">
|
|
28
27
|
</p>
|
|
29
28
|
|
|
30
29
|
## Table of contents
|
|
@@ -265,4 +264,4 @@ Bug or a feature request, [please open a new issue](https://github.com/Lomray-So
|
|
|
265
264
|
## License
|
|
266
265
|
Made with 💚
|
|
267
266
|
|
|
268
|
-
Published under [
|
|
267
|
+
Published under [MIT License](./LICENSE).
|
package/cli/run-prod.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ interface IRunProdParams {
|
|
|
9
9
|
onlyClient?: boolean;
|
|
10
10
|
mode?: string;
|
|
11
11
|
modulePreload?: boolean;
|
|
12
|
+
buildDir?: string;
|
|
12
13
|
}
|
|
13
14
|
interface IRunProdOut {
|
|
14
15
|
server: Server;
|
|
@@ -17,5 +18,5 @@ interface IRunProdOut {
|
|
|
17
18
|
/**
|
|
18
19
|
* Run production server
|
|
19
20
|
*/
|
|
20
|
-
declare function runProd({ version, isHost, isPrintInfo, port, onlyClient, modulePreload, }: IRunProdParams): Promise<IRunProdOut>;
|
|
21
|
+
declare function runProd({ version, isHost, isPrintInfo, port, buildDir, onlyClient, modulePreload, }: IRunProdParams): Promise<IRunProdOut>;
|
|
21
22
|
export { runProd as default };
|
package/cli/run-prod.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{performance as o}from"node:perf_hooks";import r from"../node/server.js";import i from"../services/server-config.js";async function
|
|
1
|
+
import{performance as o}from"node:perf_hooks";import r from"../node/server.js";import i from"../services/server-config.js";async function t({version:t,isHost:e,isPrintInfo:s,port:n,buildDir:l,onlyClient:a=!1,modulePreload:f=!1}){global.viteBoostStartTime||(global.viteBoostStartTime=o.now());const d=i.init({isHost:e,isProd:!0,isOnlyClient:a,isModulePreload:f},{port:n,root:l}),{run:m}=await r(d);return{server:m({version:t,isPrintInfo:s}),config:d}}export{t as default};
|
|
2
2
|
//# sourceMappingURL=run-prod.js.map
|
package/cli/run-prod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-prod.js","sources":["../../src/cli/run-prod.ts"],"sourcesContent":["import type { Server } from 'node:net';\nimport { performance } from 'node:perf_hooks';\nimport createServer from '@node/server';\nimport ServerConfig from '@services/server-config';\n\ninterface IRunProdParams {\n version: string;\n port?: number;\n isHost?: boolean;\n isPrintInfo?: boolean;\n onlyClient?: boolean; // SPA mode\n mode?: string;\n modulePreload?: boolean;\n}\n\ninterface IRunProdOut {\n server: Server;\n config: ServerConfig;\n}\n\n/**\n * Run production server\n */\nasync function runProd({\n version,\n isHost,\n isPrintInfo,\n port,\n onlyClient = false,\n modulePreload = false,\n}: IRunProdParams): Promise<IRunProdOut> {\n if (!global.viteBoostStartTime) {\n global.viteBoostStartTime = performance.now();\n }\n\n const config = ServerConfig.init(\n { isHost, isProd: true, isOnlyClient: onlyClient, isModulePreload: modulePreload },\n { port },\n );\n const { run } = await createServer(config);\n\n return {\n server: run({ version, isPrintInfo }),\n config,\n };\n}\n\nexport default runProd;\n"],"names":["async","runProd","version","isHost","isPrintInfo","port","onlyClient","modulePreload","global","viteBoostStartTime","performance","now","config","ServerConfig","init","isProd","isOnlyClient","isModulePreload","run","createServer","server"],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-prod.js","sources":["../../src/cli/run-prod.ts"],"sourcesContent":["import type { Server } from 'node:net';\nimport { performance } from 'node:perf_hooks';\nimport createServer from '@node/server';\nimport ServerConfig from '@services/server-config';\n\ninterface IRunProdParams {\n version: string;\n port?: number;\n isHost?: boolean;\n isPrintInfo?: boolean;\n onlyClient?: boolean; // SPA mode\n mode?: string;\n modulePreload?: boolean;\n buildDir?: string;\n}\n\ninterface IRunProdOut {\n server: Server;\n config: ServerConfig;\n}\n\n/**\n * Run production server\n */\nasync function runProd({\n version,\n isHost,\n isPrintInfo,\n port,\n buildDir,\n onlyClient = false,\n modulePreload = false,\n}: IRunProdParams): Promise<IRunProdOut> {\n if (!global.viteBoostStartTime) {\n global.viteBoostStartTime = performance.now();\n }\n\n const config = ServerConfig.init(\n { isHost, isProd: true, isOnlyClient: onlyClient, isModulePreload: modulePreload },\n { port, root: buildDir },\n );\n const { run } = await createServer(config);\n\n return {\n server: run({ version, isPrintInfo }),\n config,\n };\n}\n\nexport default runProd;\n"],"names":["async","runProd","version","isHost","isPrintInfo","port","buildDir","onlyClient","modulePreload","global","viteBoostStartTime","performance","now","config","ServerConfig","init","isProd","isOnlyClient","isModulePreload","root","run","createServer","server"],"mappings":"2HAwBAA,eAAeC,GAAQC,QACrBA,EAAOC,OACPA,EAAMC,YACNA,EAAWC,KACXA,EAAIC,SACJA,EAAQC,WACRA,GAAa,EAAKC,cAClBA,GAAgB,IAEXC,OAAOC,qBACVD,OAAOC,mBAAqBC,EAAYC,OAG1C,MAAMC,EAASC,EAAaC,KAC1B,CAAEZ,SAAQa,QAAQ,EAAMC,aAAcV,EAAYW,gBAAiBV,GACnE,CAAEH,OAAMc,KAAMb,KAEVc,IAAEA,SAAcC,EAAaR,GAEnC,MAAO,CACLS,OAAQF,EAAI,CAAElB,UAASE,gBACvBS,SAEJ"}
|
package/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as e}from"fs";import o from"chalk";import{Command as i,Option as n}from"commander";import t from"./cli/build.js";import r from"./cli/helpers/keyboard-input.js";import s from"./cli/helpers/vite-reset-cache.js";import d from"./cli/run-amplify-build.js";import a from"./cli/run-dev.js";import l from"./cli/run-docker-build.js";import c from"./cli/run-prod.js";import p from"./cli/run-vercel-build.js";import m from"./constants/cli-actions.js";import f from"./constants/cli-context.js";import u from"./constants/cli-name.js";const{description:w,version:
|
|
2
|
+
import{readFileSync as e}from"fs";import o from"chalk";import{Command as i,Option as n}from"commander";import t from"./cli/build.js";import r from"./cli/helpers/keyboard-input.js";import s from"./cli/helpers/vite-reset-cache.js";import d from"./cli/run-amplify-build.js";import a from"./cli/run-dev.js";import l from"./cli/run-docker-build.js";import c from"./cli/run-prod.js";import p from"./cli/run-vercel-build.js";import m from"./constants/cli-actions.js";import f from"./constants/cli-context.js";import u from"./constants/cli-name.js";const{description:w,version:O}=JSON.parse(e(new URL("./package.json",import.meta.url),"utf8")),v=()=>{process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.on("data",r).setEncoding("utf8").resume())},g=new i;g.name(u).description(w).version(O).hook("preAction",((e,o)=>{global.viteBoostAction=o.name()}));const b=new n("--host","Ability to access the local instance on other devices under the same network.").default(!1),h=new n("--only-client","Build/run only client side part.").default(!1),y=new n("--port [port]","Server port.").default(3e3),k=new n("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("production"),P=new n("--build-dir [buildDir]","Build directory output.");g.command(m.dev).description("Run development server.").addOption(b).addOption(new n("--reset-cache","Clear vite cache before run.").default(!1)).addOption(new n("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("development")).action((async({host:e,resetCache:i,mode:n})=>{i&&await s();const t=async i=>{console.info(o.cyan("Starting the development server..."));const{server:t,config:r}=await a({version:O,isHost:e,isPrintInfo:i,mode:n});f.server=t,f.config=r};return f.reboot=t,v(),t()})),g.command(m.build).description("Create production build.").addOption(h).addOption(k).addOption(new n("--client-options [client-options]",'Pass vite build options for client. Example: --client-options="--ssrManifest"').env("VITE_BUILD_CLIENT_OPTIONS").default("")).addOption(new n("--server-options [server-options]","Pass vite build options for server.").env("VITE_BUILD_SERVER_OPTIONS").default("")).addOption(new n("--unlock-robots","Change general directive Disallow to Allow in robots.txt").default(!1)).addOption(new n("--eject","Produces entrypoint file to run app without cli").default(!1)).addOption(new n("--serverless","Produces entrypoint file to run app like serverless function").default(!1)).addOption(new n("--throw-warnings","The build will abort with an error if warnings occur in the process.").default(!1)).action((async({onlyClient:e,clientOptions:o,serverOptions:i,mode:n,unlockRobots:r,eject:s,serverless:d,throwWarnings:a})=>{await t({isOnlyClient:e,isUnlockRobots:r,isNoWarnings:a,isEject:s,isServerless:d,clientOptions:o,serverOptions:i,mode:n})})),g.command(m.start).description("Run production server.").addOption(b).addOption(y).addOption(h).addOption(P).addOption(new n("--module-preload","Add module preload scripts to server output.").default(!1)).action((({host:e,port:o,onlyClient:i,modulePreload:n,buildDir:t})=>{const r=async r=>{const{server:s,config:d}=await c({version:O,isHost:e,isPrintInfo:r,port:o,onlyClient:i,modulePreload:n,buildDir:t});f.server=s,f.config=d};return f.reboot=r,v(),r()})),g.command(m.preview).description("Build and preview production.").addOption(h).addOption(b).addOption(y).addOption(k).addOption(P).action((async({host:e,port:i,onlyClient:n,mode:r,buildDir:s})=>{global.viteBoostStartTime=performance.now();const d=async t=>{const{server:r,config:d}=await c({version:O,isHost:e,isPrintInfo:t,port:i,onlyClient:n,buildDir:s});r.on("listening",(()=>{setTimeout((()=>{d.getLogger().info(o.yellow("\n Running preview mode... \n"))}),0)})),f.server=r,f.config=d};f.reboot=d,v();await t({mode:r,isWatch:!0,isOnlyClient:n,clientOptions:"-w",serverOptions:"-w",onFinish:()=>{d()}})})),g.command(m.buildDocker).description("Create docker image with production build.").requiredOption("--image-name <image-name>","Docker image name.").addOption(new n("--docker-options [docker-options]","Extra docker options which pass to docker build command.")).addOption(new n("--docker-file [docker-file]","Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).")).addOption(h).addOption(k).action((async({imageName:e,dockerOptions:o,dockerFile:i,onlyClient:n,mode:t})=>{await l({imageName:e,dockerOptions:o,dockerFile:i,isOnlyClient:n,mode:t})})),g.command(m.buildAmplify).description("Create AWS Amplify production build.").addOption(new n("--manifest-file [manifest-file]","Path to the Amplify manifest file (Default is PLUGIN_PATH/workflow/amplify-manifest.json).")).addOption(new n("--is-optimize","Optimize node_modules folder.").default(!1)).addOption(k).action((async({manifestFile:e,mode:o,isOptimize:i})=>{await d({manifestFile:e,mode:o,isOptimize:i})})),g.command(m.buildVercel).description("Create Vercel serverless production build.").addOption(new n("--config-file [config-file]","Path to the Vercel config.json file (Default is PLUGIN_PATH/workflow/vercel.config.json).")).addOption(new n("--config-vc-file [config-vc-file]","Path to the Vercel vc-config.json file (Default is PLUGIN_PATH/workflow/vercel.vc-config.json).")).addOption(new n("--is-optimize","Optimize node_modules folder.").default(!1)).addOption(k).action((async({configFile:e,configVcFile:o,mode:i,isOptimize:n})=>{await p({configFile:e,configVcFile:o,mode:i,isOptimize:n})})),g.parse();
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
package/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'fs';\nimport chalk from 'chalk';\nimport { Command, Option } from 'commander';\nimport runBuild from '@cli/build';\nimport onKeyPress from '@cli/helpers/keyboard-input';\nimport viteResetCache from '@cli/helpers/vite-reset-cache';\nimport runAmplifyBuild from '@cli/run-amplify-build';\nimport runDev from '@cli/run-dev';\nimport runDockerBuild from '@cli/run-docker-build';\nimport runProd from '@cli/run-prod';\nimport runVercelBuild from '@cli/run-vercel-build';\nimport CliActions from '@constants/cli-actions';\nimport cliContext from '@constants/cli-context';\nimport cliName from '@constants/cli-name';\n\n/**\n * Parse package meta\n */\nconst { description, version } = JSON.parse(\n readFileSync(new URL('./package.json', import.meta.url), 'utf8'),\n) as { name: string; description: string; version: string };\n\n/**\n * Enable shortcuts\n * listen keyboard command\n */\nconst enableShortcuts = (): void => {\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.on('data', onKeyPress).setEncoding('utf8').resume();\n }\n};\n\nconst program = new Command();\n\nprogram\n .name(cliName)\n .description(description)\n .version(version)\n .hook('preAction', (_, actionCommand) => {\n // pass cli action to plugin config\n global.viteBoostAction = actionCommand.name();\n });\n\n/**\n * Common options\n */\nconst hostOption = new Option(\n '--host',\n 'Ability to access the local instance on other devices under the same network.',\n).default(false);\nconst onlyClientOption = new Option('--only-client', 'Build/run only client side part.').default(\n false,\n);\nconst portOption = new Option('--port [port]', 'Server port.').default(3000);\nconst envModeOption = new Option('--mode [mode]', 'Env mode.')\n .env('VITE_ENV_MODE')\n .default('production');\n\n/**\n * Cli commands\n */\n\nprogram\n .command(CliActions.dev)\n .description('Run development server.')\n .addOption(hostOption)\n .addOption(new Option('--reset-cache', 'Clear vite cache before run.').default(false))\n .addOption(new Option('--mode [mode]', 'Env mode.').env('VITE_ENV_MODE').default('development'))\n .action(async ({ host, resetCache, mode }) => {\n if (resetCache) {\n await viteResetCache();\n }\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n console.info(chalk.cyan('Starting the development server...'));\n\n const { server, config } = await runDev({ version, isHost: host, isPrintInfo, mode });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.build)\n .description('Create production build.')\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .addOption(\n new Option(\n '--client-options [client-options]',\n 'Pass vite build options for client. Example: --client-options=\"--ssrManifest\"',\n )\n .env('VITE_BUILD_CLIENT_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option('--server-options [server-options]', 'Pass vite build options for server.')\n .env('VITE_BUILD_SERVER_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option(\n '--unlock-robots',\n 'Change general directive Disallow to Allow in robots.txt',\n ).default(false),\n )\n .addOption(\n new Option('--eject', 'Produces entrypoint file to run app without cli').default(false),\n )\n .addOption(\n new Option(\n '--serverless',\n 'Produces entrypoint file to run app like serverless function',\n ).default(false),\n )\n .addOption(\n new Option(\n '--throw-warnings',\n 'The build will abort with an error if warnings occur in the process.',\n ).default(false),\n )\n .action(\n async ({\n onlyClient,\n clientOptions,\n serverOptions,\n mode,\n unlockRobots,\n eject,\n serverless,\n throwWarnings,\n }) => {\n await runBuild({\n isOnlyClient: onlyClient,\n isUnlockRobots: unlockRobots,\n isNoWarnings: throwWarnings,\n isEject: eject,\n isServerless: serverless,\n clientOptions,\n serverOptions,\n mode,\n });\n },\n );\n\nprogram\n .command(CliActions.start)\n .description('Run production server.')\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(onlyClientOption)\n .addOption(\n new Option('--module-preload', 'Add module preload scripts to server output.').default(false),\n )\n .action(({ host, port, onlyClient, modulePreload }) => {\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n modulePreload,\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.preview)\n .description('Build and preview production.')\n .addOption(onlyClientOption)\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(envModeOption)\n .action(async ({ host, port, onlyClient, mode }) => {\n global.viteBoostStartTime = performance.now();\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n });\n\n server.on('listening', () => {\n setTimeout(() => {\n config.getLogger().info(chalk.yellow('\\n Running preview mode... \\n'));\n }, 0);\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n const buildOptions = '-w';\n\n await runBuild({\n mode,\n isWatch: true,\n isOnlyClient: onlyClient,\n clientOptions: buildOptions,\n serverOptions: buildOptions,\n onFinish: () => {\n void command();\n },\n });\n });\n\nprogram\n .command(CliActions.buildDocker)\n .description('Create docker image with production build.')\n .requiredOption('--image-name <image-name>', 'Docker image name.')\n .addOption(\n new Option(\n '--docker-options [docker-options]',\n 'Extra docker options which pass to docker build command.',\n ),\n )\n .addOption(\n new Option(\n '--docker-file [docker-file]',\n 'Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).',\n ),\n )\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .action(async ({ imageName, dockerOptions, dockerFile, onlyClient, mode }) => {\n await runDockerBuild({\n imageName,\n dockerOptions,\n dockerFile,\n isOnlyClient: onlyClient,\n mode,\n });\n });\n\nprogram\n .command(CliActions.buildAmplify)\n .description('Create AWS Amplify production build.')\n .addOption(\n new Option(\n '--manifest-file [manifest-file]',\n 'Path to the Amplify manifest file (Default is PLUGIN_PATH/workflow/amplify-manifest.json).',\n ),\n )\n .addOption(new Option('--is-optimize', 'Optimize node_modules folder.').default(false))\n .addOption(envModeOption)\n .action(async ({ manifestFile, mode, isOptimize }) => {\n await runAmplifyBuild({\n manifestFile,\n mode,\n isOptimize,\n });\n });\n\nprogram\n .command(CliActions.buildVercel)\n .description('Create Vercel serverless production build.')\n .addOption(\n new Option(\n '--config-file [config-file]',\n 'Path to the Vercel config.json file (Default is PLUGIN_PATH/workflow/vercel.config.json).',\n ),\n )\n .addOption(\n new Option(\n '--config-vc-file [config-vc-file]',\n 'Path to the Vercel vc-config.json file (Default is PLUGIN_PATH/workflow/vercel.vc-config.json).',\n ),\n )\n .addOption(new Option('--is-optimize', 'Optimize node_modules folder.').default(false))\n .addOption(envModeOption)\n .action(async ({ configFile, configVcFile, mode, isOptimize }) => {\n await runVercelBuild({\n configFile,\n configVcFile,\n mode,\n isOptimize,\n });\n });\n\nprogram.parse();\n"],"names":["description","version","JSON","parse","readFileSync","URL","url","enableShortcuts","process","stdin","isTTY","setRawMode","on","onKeyPress","setEncoding","resume","program","Command","name","cliName","hook","_","actionCommand","global","viteBoostAction","hostOption","Option","default","onlyClientOption","portOption","envModeOption","env","command","CliActions","dev","addOption","action","async","host","resetCache","mode","viteResetCache","isPrintInfo","console","info","chalk","cyan","server","config","runDev","isHost","cliContext","reboot","build","onlyClient","clientOptions","serverOptions","unlockRobots","eject","serverless","throwWarnings","runBuild","isOnlyClient","isUnlockRobots","isNoWarnings","isEject","isServerless","start","port","modulePreload","runProd","preview","viteBoostStartTime","performance","now","setTimeout","getLogger","yellow","isWatch","onFinish","buildDocker","requiredOption","imageName","dockerOptions","dockerFile","runDockerBuild","buildAmplify","manifestFile","isOptimize","runAmplifyBuild","buildVercel","configFile","configVcFile","runVercelBuild"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'fs';\nimport chalk from 'chalk';\nimport { Command, Option } from 'commander';\nimport runBuild from '@cli/build';\nimport onKeyPress from '@cli/helpers/keyboard-input';\nimport viteResetCache from '@cli/helpers/vite-reset-cache';\nimport runAmplifyBuild from '@cli/run-amplify-build';\nimport runDev from '@cli/run-dev';\nimport runDockerBuild from '@cli/run-docker-build';\nimport runProd from '@cli/run-prod';\nimport runVercelBuild from '@cli/run-vercel-build';\nimport CliActions from '@constants/cli-actions';\nimport cliContext from '@constants/cli-context';\nimport cliName from '@constants/cli-name';\n\n/**\n * Parse package meta\n */\nconst { description, version } = JSON.parse(\n readFileSync(new URL('./package.json', import.meta.url), 'utf8'),\n) as { name: string; description: string; version: string };\n\n/**\n * Enable shortcuts\n * listen keyboard command\n */\nconst enableShortcuts = (): void => {\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.on('data', onKeyPress).setEncoding('utf8').resume();\n }\n};\n\nconst program = new Command();\n\nprogram\n .name(cliName)\n .description(description)\n .version(version)\n .hook('preAction', (_, actionCommand) => {\n // pass cli action to plugin config\n global.viteBoostAction = actionCommand.name();\n });\n\n/**\n * Common options\n */\nconst hostOption = new Option(\n '--host',\n 'Ability to access the local instance on other devices under the same network.',\n).default(false);\nconst onlyClientOption = new Option('--only-client', 'Build/run only client side part.').default(\n false,\n);\nconst portOption = new Option('--port [port]', 'Server port.').default(3000);\nconst envModeOption = new Option('--mode [mode]', 'Env mode.')\n .env('VITE_ENV_MODE')\n .default('production');\nconst buildDirOption = new Option('--build-dir [buildDir]', 'Build directory output.');\n\n/**\n * Cli commands\n */\n\nprogram\n .command(CliActions.dev)\n .description('Run development server.')\n .addOption(hostOption)\n .addOption(new Option('--reset-cache', 'Clear vite cache before run.').default(false))\n .addOption(new Option('--mode [mode]', 'Env mode.').env('VITE_ENV_MODE').default('development'))\n .action(async ({ host, resetCache, mode }) => {\n if (resetCache) {\n await viteResetCache();\n }\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n console.info(chalk.cyan('Starting the development server...'));\n\n const { server, config } = await runDev({ version, isHost: host, isPrintInfo, mode });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.build)\n .description('Create production build.')\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .addOption(\n new Option(\n '--client-options [client-options]',\n 'Pass vite build options for client. Example: --client-options=\"--ssrManifest\"',\n )\n .env('VITE_BUILD_CLIENT_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option('--server-options [server-options]', 'Pass vite build options for server.')\n .env('VITE_BUILD_SERVER_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option(\n '--unlock-robots',\n 'Change general directive Disallow to Allow in robots.txt',\n ).default(false),\n )\n .addOption(\n new Option('--eject', 'Produces entrypoint file to run app without cli').default(false),\n )\n .addOption(\n new Option(\n '--serverless',\n 'Produces entrypoint file to run app like serverless function',\n ).default(false),\n )\n .addOption(\n new Option(\n '--throw-warnings',\n 'The build will abort with an error if warnings occur in the process.',\n ).default(false),\n )\n .action(\n async ({\n onlyClient,\n clientOptions,\n serverOptions,\n mode,\n unlockRobots,\n eject,\n serverless,\n throwWarnings,\n }) => {\n await runBuild({\n isOnlyClient: onlyClient,\n isUnlockRobots: unlockRobots,\n isNoWarnings: throwWarnings,\n isEject: eject,\n isServerless: serverless,\n clientOptions,\n serverOptions,\n mode,\n });\n },\n );\n\nprogram\n .command(CliActions.start)\n .description('Run production server.')\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(onlyClientOption)\n .addOption(buildDirOption)\n .addOption(\n new Option('--module-preload', 'Add module preload scripts to server output.').default(false),\n )\n .action(({ host, port, onlyClient, modulePreload, buildDir }) => {\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n modulePreload,\n buildDir,\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.preview)\n .description('Build and preview production.')\n .addOption(onlyClientOption)\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(envModeOption)\n .addOption(buildDirOption)\n .action(async ({ host, port, onlyClient, mode, buildDir }) => {\n global.viteBoostStartTime = performance.now();\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n buildDir,\n });\n\n server.on('listening', () => {\n setTimeout(() => {\n config.getLogger().info(chalk.yellow('\\n Running preview mode... \\n'));\n }, 0);\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n const buildOptions = '-w';\n\n await runBuild({\n mode,\n isWatch: true,\n isOnlyClient: onlyClient,\n clientOptions: buildOptions,\n serverOptions: buildOptions,\n onFinish: () => {\n void command();\n },\n });\n });\n\nprogram\n .command(CliActions.buildDocker)\n .description('Create docker image with production build.')\n .requiredOption('--image-name <image-name>', 'Docker image name.')\n .addOption(\n new Option(\n '--docker-options [docker-options]',\n 'Extra docker options which pass to docker build command.',\n ),\n )\n .addOption(\n new Option(\n '--docker-file [docker-file]',\n 'Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).',\n ),\n )\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .action(async ({ imageName, dockerOptions, dockerFile, onlyClient, mode }) => {\n await runDockerBuild({\n imageName,\n dockerOptions,\n dockerFile,\n isOnlyClient: onlyClient,\n mode,\n });\n });\n\nprogram\n .command(CliActions.buildAmplify)\n .description('Create AWS Amplify production build.')\n .addOption(\n new Option(\n '--manifest-file [manifest-file]',\n 'Path to the Amplify manifest file (Default is PLUGIN_PATH/workflow/amplify-manifest.json).',\n ),\n )\n .addOption(new Option('--is-optimize', 'Optimize node_modules folder.').default(false))\n .addOption(envModeOption)\n .action(async ({ manifestFile, mode, isOptimize }) => {\n await runAmplifyBuild({\n manifestFile,\n mode,\n isOptimize,\n });\n });\n\nprogram\n .command(CliActions.buildVercel)\n .description('Create Vercel serverless production build.')\n .addOption(\n new Option(\n '--config-file [config-file]',\n 'Path to the Vercel config.json file (Default is PLUGIN_PATH/workflow/vercel.config.json).',\n ),\n )\n .addOption(\n new Option(\n '--config-vc-file [config-vc-file]',\n 'Path to the Vercel vc-config.json file (Default is PLUGIN_PATH/workflow/vercel.vc-config.json).',\n ),\n )\n .addOption(new Option('--is-optimize', 'Optimize node_modules folder.').default(false))\n .addOption(envModeOption)\n .action(async ({ configFile, configVcFile, mode, isOptimize }) => {\n await runVercelBuild({\n configFile,\n configVcFile,\n mode,\n isOptimize,\n });\n });\n\nprogram.parse();\n"],"names":["description","version","JSON","parse","readFileSync","URL","url","enableShortcuts","process","stdin","isTTY","setRawMode","on","onKeyPress","setEncoding","resume","program","Command","name","cliName","hook","_","actionCommand","global","viteBoostAction","hostOption","Option","default","onlyClientOption","portOption","envModeOption","env","buildDirOption","command","CliActions","dev","addOption","action","async","host","resetCache","mode","viteResetCache","isPrintInfo","console","info","chalk","cyan","server","config","runDev","isHost","cliContext","reboot","build","onlyClient","clientOptions","serverOptions","unlockRobots","eject","serverless","throwWarnings","runBuild","isOnlyClient","isUnlockRobots","isNoWarnings","isEject","isServerless","start","port","modulePreload","buildDir","runProd","preview","viteBoostStartTime","performance","now","setTimeout","getLogger","yellow","isWatch","onFinish","buildDocker","requiredOption","imageName","dockerOptions","dockerFile","runDockerBuild","buildAmplify","manifestFile","isOptimize","runAmplifyBuild","buildVercel","configFile","configVcFile","runVercelBuild"],"mappings":";6hBAoBA,MAAMA,YAAEA,EAAWC,QAAEA,GAAYC,KAAKC,MACpCC,EAAa,IAAIC,IAAI,6BAA8BC,KAAM,SAOrDC,EAAkB,KAClBC,QAAQC,MAAMC,QAChBF,QAAQC,MAAME,YAAW,GACzBH,QAAQC,MAAMG,GAAG,OAAQC,GAAYC,YAAY,QAAQC,SAC1D,EAGGC,EAAU,IAAIC,EAEpBD,EACGE,KAAKC,GACLnB,YAAYA,GACZC,QAAQA,GACRmB,KAAK,aAAa,CAACC,EAAGC,KAErBC,OAAOC,gBAAkBF,EAAcJ,MAAM,IAMjD,MAAMO,EAAa,IAAIC,EACrB,SACA,iFACAC,SAAQ,GACJC,EAAmB,IAAIF,EAAO,gBAAiB,oCAAoCC,SACvF,GAEIE,EAAa,IAAIH,EAAO,gBAAiB,gBAAgBC,QAAQ,KACjEG,EAAgB,IAAIJ,EAAO,gBAAiB,aAC/CK,IAAI,iBACJJ,QAAQ,cACLK,EAAiB,IAAIN,EAAO,yBAA0B,2BAM5DV,EACGiB,QAAQC,EAAWC,KACnBnC,YAAY,2BACZoC,UAAUX,GACVW,UAAU,IAAIV,EAAO,gBAAiB,gCAAgCC,SAAQ,IAC9ES,UAAU,IAAIV,EAAO,gBAAiB,aAAaK,IAAI,iBAAiBJ,QAAQ,gBAChFU,QAAOC,OAASC,OAAMC,aAAYC,WAC7BD,SACIE,IAGR,MAAMT,EAAUK,MAAOK,IACrBC,QAAQC,KAAKC,EAAMC,KAAK,uCAExB,MAAMC,OAAEA,EAAMC,OAAEA,SAAiBC,EAAO,CAAEjD,UAASkD,OAAQZ,EAAMI,cAAaF,SAE9EW,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAO5B,OAJAG,EAAWC,OAASpB,EAEpB1B,IAEO0B,GAAS,IAGpBjB,EACGiB,QAAQC,EAAWoB,OACnBtD,YAAY,4BACZoC,UAAUR,GACVQ,UAAUN,GACVM,UACC,IAAIV,EACF,oCACA,iFAECK,IAAI,6BACJJ,QAAQ,KAEZS,UACC,IAAIV,EAAO,oCAAqC,uCAC7CK,IAAI,6BACJJ,QAAQ,KAEZS,UACC,IAAIV,EACF,kBACA,4DACAC,SAAQ,IAEXS,UACC,IAAIV,EAAO,UAAW,mDAAmDC,SAAQ,IAElFS,UACC,IAAIV,EACF,eACA,gEACAC,SAAQ,IAEXS,UACC,IAAIV,EACF,mBACA,wEACAC,SAAQ,IAEXU,QACCC,OACEiB,aACAC,gBACAC,gBACAhB,OACAiB,eACAC,QACAC,aACAC,0BAEMC,EAAS,CACbC,aAAcR,EACdS,eAAgBN,EAChBO,aAAcJ,EACdK,QAASP,EACTQ,aAAcP,EACdJ,gBACAC,gBACAhB,QACA,IAIRzB,EACGiB,QAAQC,EAAWkC,OACnBpE,YAAY,0BACZoC,UAAUX,GACVW,UAAUP,GACVO,UAAUR,GACVQ,UAAUJ,GACVI,UACC,IAAIV,EAAO,mBAAoB,gDAAgDC,SAAQ,IAExFU,QAAO,EAAGE,OAAM8B,OAAMd,aAAYe,gBAAeC,eAChD,MAAMtC,EAAUK,MAAOK,IACrB,MAAMK,OAAEA,EAAMC,OAAEA,SAAiBuB,EAAQ,CACvCvE,UACAkD,OAAQZ,EACRI,cACA0B,OACAd,aACAe,gBACAC,aAGFnB,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAO5B,OAJAG,EAAWC,OAASpB,EAEpB1B,IAEO0B,GAAS,IAGpBjB,EACGiB,QAAQC,EAAWuC,SACnBzE,YAAY,iCACZoC,UAAUR,GACVQ,UAAUX,GACVW,UAAUP,GACVO,UAAUN,GACVM,UAAUJ,GACVK,QAAOC,OAASC,OAAM8B,OAAMd,aAAYd,OAAM8B,eAC7ChD,OAAOmD,mBAAqBC,YAAYC,MAExC,MAAM3C,EAAUK,MAAOK,IACrB,MAAMK,OAAEA,EAAMC,OAAEA,SAAiBuB,EAAQ,CACvCvE,UACAkD,OAAQZ,EACRI,cACA0B,OACAd,aACAgB,aAGFvB,EAAOpC,GAAG,aAAa,KACrBiE,YAAW,KACT5B,EAAO6B,YAAYjC,KAAKC,EAAMiC,OAAO,kCAAkC,GACtE,EAAE,IAGP3B,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAG5BG,EAAWC,OAASpB,EAEpB1B,UAIMuD,EAAS,CACbrB,OACAuC,SAAS,EACTjB,aAAcR,EACdC,cANmB,KAOnBC,cAPmB,KAQnBwB,SAAU,KACHhD,GAAS,GAEhB,IAGNjB,EACGiB,QAAQC,EAAWgD,aACnBlF,YAAY,8CACZmF,eAAe,4BAA6B,sBAC5C/C,UACC,IAAIV,EACF,oCACA,6DAGHU,UACC,IAAIV,EACF,8BACA,yEAGHU,UAAUR,GACVQ,UAAUN,GACVO,QAAOC,OAAS8C,YAAWC,gBAAeC,aAAY/B,aAAYd,iBAC3D8C,EAAe,CACnBH,YACAC,gBACAC,aACAvB,aAAcR,EACdd,QACA,IAGNzB,EACGiB,QAAQC,EAAWsD,cACnBxF,YAAY,wCACZoC,UACC,IAAIV,EACF,kCACA,+FAGHU,UAAU,IAAIV,EAAO,gBAAiB,iCAAiCC,SAAQ,IAC/ES,UAAUN,GACVO,QAAOC,OAASmD,eAAchD,OAAMiD,uBAC7BC,EAAgB,CACpBF,eACAhD,OACAiD,cACA,IAGN1E,EACGiB,QAAQC,EAAW0D,aACnB5F,YAAY,8CACZoC,UACC,IAAIV,EACF,8BACA,8FAGHU,UACC,IAAIV,EACF,oCACA,oGAGHU,UAAU,IAAIV,EAAO,gBAAiB,iCAAiCC,SAAQ,IAC/ES,UAAUN,GACVO,QAAOC,OAASuD,aAAYC,eAAcrD,OAAMiD,uBACzCK,EAAe,CACnBF,aACAC,eACArD,OACAiD,cACA,IAGN1E,EAAQb"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lomray/vite-ssr-boost",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-beta.2",
|
|
4
4
|
"description": "Vite plugin for create awesome SSR or SPA applications on React.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -30,33 +30,30 @@
|
|
|
30
30
|
"lint:check": "eslint --ext \".ts,.tsx\" \"src/**/*.{ts,tsx,*.ts,*tsx}\"",
|
|
31
31
|
"lint:format": "eslint --fix --ext \".ts,.tsx\" \"src/**/*.{ts,tsx,*.ts,*tsx}\"",
|
|
32
32
|
"ts:check": "tsc --project ./tsconfig.json --skipLibCheck --noemit",
|
|
33
|
-
"test": "
|
|
33
|
+
"test": "vitest run"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"chalk": "^5.3.0",
|
|
37
37
|
"commander": "^11.1.0",
|
|
38
38
|
"compression": "^1.7.4",
|
|
39
39
|
"express": "^4.18.2",
|
|
40
|
-
"hjson": "^3.2.2",
|
|
41
40
|
"hoist-non-react-statics": "^3.3.2"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
|
-
"@commitlint/cli": "^18.
|
|
45
|
-
"@commitlint/config-conventional": "^18.
|
|
43
|
+
"@commitlint/cli": "^18.5.0",
|
|
44
|
+
"@commitlint/config-conventional": "^18.5.0",
|
|
46
45
|
"@lomray/eslint-config": "^4.0.1",
|
|
47
46
|
"@lomray/prettier-config": "^2.0.1",
|
|
48
47
|
"@rollup/plugin-terser": "^0.4.4",
|
|
49
48
|
"@types/chai": "^4.3.11",
|
|
50
49
|
"@types/compression": "^1.7.5",
|
|
51
|
-
"@types/hjson": "^2.4.6",
|
|
52
50
|
"@types/hoist-non-react-statics": "^3.3.5",
|
|
53
|
-
"@types/mocha": "^10.0.6",
|
|
54
51
|
"@types/react-dom": "^18.2.17",
|
|
55
|
-
"@types/sinon": "^17.0.
|
|
52
|
+
"@types/sinon": "^17.0.3",
|
|
56
53
|
"@types/sinon-chai": "^3.2.12",
|
|
57
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
55
|
+
"@vitest/coverage-v8": "^1.2.1",
|
|
58
56
|
"@zerollup/ts-transform-paths": "^1.7.18",
|
|
59
|
-
"c8": "^8.0.1",
|
|
60
57
|
"chai": "^4.3.10",
|
|
61
58
|
"eslint": "^8.55.0",
|
|
62
59
|
"eslint-config-prettier": "^9.1.0",
|
|
@@ -65,7 +62,6 @@
|
|
|
65
62
|
"eslint-plugin-prettier": "^5.0.1",
|
|
66
63
|
"husky": "^8.0.3",
|
|
67
64
|
"lint-staged": "^15.2.0",
|
|
68
|
-
"mocha": "^10.2.0",
|
|
69
65
|
"prettier": "^3.1.1",
|
|
70
66
|
"rollup": "^4.9.0",
|
|
71
67
|
"rollup-plugin-copy": "^3.5.0",
|
|
@@ -76,15 +72,15 @@
|
|
|
76
72
|
"semantic-release": "^21.1.2",
|
|
77
73
|
"sinon": "^17.0.1",
|
|
78
74
|
"sinon-chai": "^3.7.0",
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"typescript": "^5.3.3"
|
|
75
|
+
"typescript": "^5.3.3",
|
|
76
|
+
"vitest": "^1.2.1"
|
|
82
77
|
},
|
|
83
78
|
"peerDependencies": {
|
|
84
79
|
"@types/express": ">=4.17.21",
|
|
85
80
|
"react-dom": ">=18.2.0",
|
|
86
81
|
"react-router-dom": ">=6.12.1",
|
|
87
|
-
"vite": ">=5"
|
|
82
|
+
"vite": ">=5",
|
|
83
|
+
"vite-tsconfig-paths": ">=4"
|
|
88
84
|
},
|
|
89
85
|
"bin": {
|
|
90
86
|
"ssr-boost": "cli.js"
|
package/plugin.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
+
import { PluginOptions as ITsconfigPathsOptions } from 'vite-tsconfig-paths';
|
|
2
3
|
import { ICliContext } from "./constants/cli-context.js";
|
|
3
|
-
import { IPluginOptions as IMakeAliasesPluginOptions } from "./plugins/make-aliases.js";
|
|
4
4
|
interface IPluginOptions {
|
|
5
5
|
indexFile?: string;
|
|
6
6
|
serverFile?: string;
|
|
7
7
|
clientFile?: string;
|
|
8
8
|
routesPath?: string;
|
|
9
|
-
|
|
9
|
+
tsconfigPaths?: boolean | ITsconfigPathsOptions;
|
|
10
10
|
customShortcuts?: {
|
|
11
11
|
key: string;
|
|
12
12
|
description: string;
|
package/plugin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import i from"node:path";import
|
|
1
|
+
import i from"node:path";import t from"vite-tsconfig-paths";import e from"./constants/cli-actions.js";import o from"./constants/plugin-name.js";import n from"./plugins/normalize-route.js";const s={indexFile:"index.html",serverFile:"server.ts",clientFile:"client.ts",tsconfigPaths:!0};function r(r={}){const p=new URL(import.meta.url),a=global.viteBoostAction||process.env.SSR_BOOST_ACTION,l={...s,...r},u="1"===process.env.SSR_BOOST_IS_SSR||a===e.dev,c=a===e.build,m=[{name:o,enforce:"pre",pluginOptions:{...l,pluginPath:i.dirname(p.pathname),action:a,isDev:a===e.dev},config:(i,{isSsrBuild:t})=>(i.define={...i.define??{},__IS_SSR__:u},i.build={...i.build??{}},t?{...i,...c?{appType:"custom"}:{},publicDir:!1}:(u&&c&&(i.build.manifest=!0),i))}],{tsconfigPaths:d,routesPath:f}=l;return d&&m.push(t("boolean"==typeof d?void 0:d)),m.push(n({isSSR:u,isBuild:c,routesPath:f})),m}export{r as default};
|
|
2
2
|
//# sourceMappingURL=plugin.js.map
|
package/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../src/plugin.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Plugin } from 'vite';\nimport
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../src/plugin.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Plugin } from 'vite';\nimport type { PluginOptions as ITsconfigPathsOptions } from 'vite-tsconfig-paths';\nimport tsconfigPathsPlugin from 'vite-tsconfig-paths';\nimport CliActions from '@constants/cli-actions';\nimport type { ICliContext } from '@constants/cli-context';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport ViteNormalizeRouterPlugin from '@plugins/normalize-route';\n\nexport interface IPluginOptions {\n // default: index.html\n indexFile?: string;\n // default: server.ts\n serverFile?: string;\n // default: client.ts\n clientFile?: string;\n // Path contains routes declaration files (need to detect route files). default: undefined, e.g.: /routes/\n routesPath?: string;\n // Enable and configure tsconfig path plugin\n tsconfigPaths?: boolean | ITsconfigPathsOptions;\n customShortcuts?: {\n key: string;\n description: string;\n action: (cliContext: ICliContext) => Promise<void> | void;\n isOnlyDev?: boolean;\n }[];\n}\n\nconst defaultOptions: IPluginOptions = {\n indexFile: 'index.html',\n serverFile: 'server.ts',\n clientFile: 'client.ts',\n tsconfigPaths: true,\n};\n\n/**\n * Init plugin\n * @constructor\n */\nfunction ViteSsrBoostPlugin(options: IPluginOptions = {}): Plugin[] {\n const dirInfo = new URL(import.meta.url);\n const action = (global.viteBoostAction || process.env.SSR_BOOST_ACTION) as CliActions;\n const mergedOptions: IPluginOptions = { ...defaultOptions, ...options };\n const isSSR = process.env.SSR_BOOST_IS_SSR === '1' || action === CliActions.dev;\n const isBuild = action === CliActions.build;\n\n const plugins: Plugin[] = [\n {\n name: PLUGIN_NAME,\n enforce: 'pre',\n // @ts-ignore save custom options\n pluginOptions: {\n ...mergedOptions,\n pluginPath: path.dirname(dirInfo.pathname),\n action,\n isDev: action === CliActions.dev,\n },\n\n config(config, { isSsrBuild }) {\n config.define = {\n ...(config.define ?? {}),\n __IS_SSR__: isSSR,\n };\n\n config.build = {\n ...(config.build ?? {}),\n };\n\n if (!isSsrBuild) {\n if (isSSR && isBuild) {\n config.build!.manifest = true;\n }\n\n return config;\n }\n\n return {\n ...config,\n ...(isBuild ? { appType: 'custom' } : {}),\n publicDir: false,\n };\n },\n },\n ];\n\n const { tsconfigPaths, routesPath } = mergedOptions;\n\n if (tsconfigPaths) {\n plugins.push(\n tsconfigPathsPlugin(typeof tsconfigPaths === 'boolean' ? undefined : tsconfigPaths),\n );\n }\n\n plugins.push(ViteNormalizeRouterPlugin({ isSSR, isBuild, routesPath }));\n\n return plugins;\n}\n\nexport default ViteSsrBoostPlugin;\n"],"names":["defaultOptions","indexFile","serverFile","clientFile","tsconfigPaths","ViteSsrBoostPlugin","options","dirInfo","URL","url","action","global","viteBoostAction","process","env","SSR_BOOST_ACTION","mergedOptions","isSSR","SSR_BOOST_IS_SSR","CliActions","dev","isBuild","build","plugins","name","PLUGIN_NAME","enforce","pluginOptions","pluginPath","path","dirname","pathname","isDev","config","isSsrBuild","define","__IS_SSR__","appType","publicDir","manifest","routesPath","push","tsconfigPathsPlugin","undefined","ViteNormalizeRouterPlugin"],"mappings":"4LA4BA,MAAMA,EAAiC,CACrCC,UAAW,aACXC,WAAY,YACZC,WAAY,YACZC,eAAe,GAOjB,SAASC,EAAmBC,EAA0B,IACpD,MAAMC,EAAU,IAAIC,gBAAgBC,KAC9BC,EAAUC,OAAOC,iBAAmBC,QAAQC,IAAIC,iBAChDC,EAAgC,IAAKhB,KAAmBM,GACxDW,EAAyC,MAAjCJ,QAAQC,IAAII,kBAA4BR,IAAWS,EAAWC,IACtEC,EAAUX,IAAWS,EAAWG,MAEhCC,EAAoB,CACxB,CACEC,KAAMC,EACNC,QAAS,MAETC,cAAe,IACVX,EACHY,WAAYC,EAAKC,QAAQvB,EAAQwB,UACjCrB,SACAsB,MAAOtB,IAAWS,EAAWC,KAG/Ba,OAAM,CAACA,GAAQC,WAAEA,MACfD,EAAOE,OAAS,IACVF,EAAOE,QAAU,CAAE,EACvBC,WAAYnB,GAGdgB,EAAOX,MAAQ,IACTW,EAAOX,OAAS,CAAE,GAGnBY,EAQE,IACFD,KACCZ,EAAU,CAAEgB,QAAS,UAAa,CAAE,EACxCC,WAAW,IAVPrB,GAASI,IACXY,EAAOX,MAAOiB,UAAW,GAGpBN,OAYT7B,cAAEA,EAAaoC,WAAEA,GAAexB,EAUtC,OARIZ,GACFmB,EAAQkB,KACNC,EAA6C,kBAAlBtC,OAA8BuC,EAAYvC,IAIzEmB,EAAQkB,KAAKG,EAA0B,CAAE3B,QAAOI,UAASmB,gBAElDjB,CACT"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"fs";import e from"node:process";import{pathToFileURL as r}from"node:url";import i from"path";import o from"chalk";class
|
|
1
|
+
import t from"fs";import e from"node:process";import{pathToFileURL as r}from"node:url";import i from"path";import o from"chalk";class s{config;entrypoint;onServerCreated;html;constructor(t){this.config=t}static init(t){return new s(t)}async loadEntrypoint(t=!0){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:s,isProd:n,serverFile:a}=this.config.getParams(),l=i.resolve(`${s}/${a}`);let d;try{d=n?(await import(r(l).toString())).default:(await this.config.getVite().ssrLoadModule(l,{fixStacktrace:!0})).default}catch(t){if(t.message.includes("Cannot find module")&&t.message.includes("/build/"))return this.config.getLogger().error(o.red(`Before starting the server, you need to create a build: ${o.yellow("ssr-boost build")} or provide path to build dir: ${o.yellow("ssr-boost start --build-dir build")}`)),e.exit(1);throw t}!t&&d.init&&delete d.init;const{render:c,init:h,routes:f,abortDelay:u}=d,{onServerCreated:p,...g}=await(h?.({config:this.config}))??{};return this.entrypoint={render:c,routes:f,abortDelay:u,...g},this.onServerCreated=p,this.entrypoint}async loadHtml(e){const{isProd:r,root:o,indexFile:s}=this.config.getParams();this.html&&r||(this.html=t.readFileSync(i.resolve(`${o}/${s}`),"utf-8"));let n=this.html;return r||(n=(await this.config.getVite().transformIndexHtml(e.originalUrl,this.html)).replace(/(<script.+)(>[\s\S]+injectIntoGlobalHook.+)/,"$1async$2")),n.split("\x3c!--ssr-outlet--\x3e")}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp())),this}}export{s as default};
|
|
2
2
|
//# sourceMappingURL=prepare-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport path from 'path';\nimport chalk from 'chalk';\nimport type { Request } from 'express';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IEntrypointOptions, IPrepareRenderOut } from '@node/entry';\nimport type { TRender } from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n routes: TRouteObject[];\n abortDelay?: number;\n onRequest?: IEntrypointOptions<TAppProps>['onRequest'];\n onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];\n onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];\n onShellError?: IEntrypointOptions<TAppProps>['onShellError'];\n onResponse?: IEntrypointOptions<TAppProps>['onResponse'];\n onError?: IEntrypointOptions<TAppProps>['onError'];\n getState?: IEntrypointOptions<TAppProps>['getState'];\n}\n\n/**\n * Load server entrypoint and template\n * DEV MODE: refresh entrypoint and template\n */\nclass PrepareServer {\n /**\n * Server configuration\n */\n protected readonly config: ServerConfig;\n\n /**\n * Entrypoint resolved params\n */\n protected entrypoint?: IPrepareServerEntrypointLoadOut;\n\n /**\n * Hook which calls after express server created\n */\n protected onServerCreated?: IEntrypointOptions['onServerCreated'];\n\n /**\n * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\n }\n\n /**\n * Resolve and return entrypoint params\n */\n public async loadEntrypoint(shouldInit = true): Promise<IPrepareServerEntrypointLoadOut> {\n // load server entrypoint each time only in development mode (for fast refresh)\n if (this.entrypoint && this.config.isProd) {\n return this.entrypoint;\n }\n\n const { root, isProd, serverFile } = this.config.getParams();\n const entrypointPath = path.resolve(`${root}/${serverFile}`);\n\n let resolvedEntrypoint: IPrepareRenderOut;\n\n try {\n if (!isProd) {\n resolvedEntrypoint = (\n await this.config.getVite()!.ssrLoadModule(entrypointPath, {\n fixStacktrace: true,\n })\n ).default;\n } else {\n resolvedEntrypoint = (await import(pathToFileURL(entrypointPath).toString())).default;\n }\n } catch (e) {\n if (e.message.includes('Cannot find module') && e.message.includes('/build/')) {\n this.config\n .getLogger()\n .error(\n chalk.red(\n `Before starting the server, you need to create a build: ${chalk.yellow(\n 'ssr-boost build',\n )}`,\n ),\n );\n\n return process.exit(1);\n }\n\n throw e;\n }\n\n if (!shouldInit && resolvedEntrypoint.init) {\n delete resolvedEntrypoint.init;\n }\n\n const { render, init, routes, abortDelay } = resolvedEntrypoint;\n const { onServerCreated, ...renderParams } =\n (await init?.({\n config: this.config,\n })) ?? {};\n\n this.entrypoint = {\n render,\n routes,\n abortDelay,\n ...renderParams,\n };\n this.onServerCreated = onServerCreated;\n\n return this.entrypoint;\n }\n\n /**\n * Load and return html shell\n */\n public async loadHtml(req: Request): Promise<[string, string]> {\n const { isProd, root, indexFile } = this.config.getParams();\n\n if (!this.html || !isProd) {\n this.html = fs.readFileSync(path.resolve(`${root}/${indexFile}`), 'utf-8');\n }\n\n let modifiedHtml = this.html;\n\n if (!isProd) {\n // Apply Vite HTML transforms. This injects the Vite HMR client,\n // and also applies HTML transforms from Vite plugins, e.g. global\n // preambles from @vitejs/plugin-react\n modifiedHtml = (await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html))\n // Make vite script 'async'\n .replace(/(<script.+)(>[\\s\\S]+injectIntoGlobalHook.+)/, '$1async$2');\n }\n\n return modifiedHtml.split('<!--ssr-outlet-->') as [string, string];\n }\n\n /**\n * Run server created hook\n */\n public async onAppCreated(): Promise<PrepareServer> {\n await this.loadEntrypoint();\n await this.onServerCreated?.(this.config.getApp()!);\n\n return this;\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","entrypoint","onServerCreated","html","constructor","this","static","async","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","pathToFileURL","toString","default","getVite","ssrLoadModule","fixStacktrace","e","message","includes","getLogger","error","chalk","red","yellow","process","exit","init","render","routes","abortDelay","renderParams","req","indexFile","fs","readFileSync","modifiedHtml","transformIndexHtml","originalUrl","replace","split","loadEntrypoint","getApp"],"mappings":"gIA4BA,MAAMA,EAIeC,OAKTC,WAKAC,gBAKAC,KAKVC,YAAsBJ,GACpBK,KAAKL,OAASA,CACf,CAKMM,YAAYN,GACjB,OAAO,IAAID,EAAcC,EAC1B,CAKMO,qBAAqBC,GAAa,GAEvC,GAAIH,KAAKJ,YAAcI,KAAKL,OAAOS,OACjC,OAAOJ,KAAKJ,WAGd,MAAMS,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeN,KAAKL,OAAOY,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,SAOyBQ,OAAOC,EAAcL,GAAgBM,aAAaC,eALtEf,KAAKL,OAAOqB,UAAWC,cAAcT,EAAgB,CACzDU,eAAe,KAEjBH,OAIL,CAAC,MAAOI,GACP,GAAIA,EAAEC,QAAQC,SAAS,uBAAyBF,EAAEC,QAAQC,SAAS,
|
|
1
|
+
{"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport path from 'path';\nimport chalk from 'chalk';\nimport type { Request } from 'express';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IEntrypointOptions, IPrepareRenderOut } from '@node/entry';\nimport type { TRender } from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n routes: TRouteObject[];\n abortDelay?: number;\n onRequest?: IEntrypointOptions<TAppProps>['onRequest'];\n onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];\n onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];\n onShellError?: IEntrypointOptions<TAppProps>['onShellError'];\n onResponse?: IEntrypointOptions<TAppProps>['onResponse'];\n onError?: IEntrypointOptions<TAppProps>['onError'];\n getState?: IEntrypointOptions<TAppProps>['getState'];\n}\n\n/**\n * Load server entrypoint and template\n * DEV MODE: refresh entrypoint and template\n */\nclass PrepareServer {\n /**\n * Server configuration\n */\n protected readonly config: ServerConfig;\n\n /**\n * Entrypoint resolved params\n */\n protected entrypoint?: IPrepareServerEntrypointLoadOut;\n\n /**\n * Hook which calls after express server created\n */\n protected onServerCreated?: IEntrypointOptions['onServerCreated'];\n\n /**\n * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\n }\n\n /**\n * Resolve and return entrypoint params\n */\n public async loadEntrypoint(shouldInit = true): Promise<IPrepareServerEntrypointLoadOut> {\n // load server entrypoint each time only in development mode (for fast refresh)\n if (this.entrypoint && this.config.isProd) {\n return this.entrypoint;\n }\n\n const { root, isProd, serverFile } = this.config.getParams();\n const entrypointPath = path.resolve(`${root}/${serverFile}`);\n\n let resolvedEntrypoint: IPrepareRenderOut;\n\n try {\n if (!isProd) {\n resolvedEntrypoint = (\n await this.config.getVite()!.ssrLoadModule(entrypointPath, {\n fixStacktrace: true,\n })\n ).default;\n } else {\n resolvedEntrypoint = (await import(pathToFileURL(entrypointPath).toString())).default;\n }\n } catch (e) {\n if (e.message.includes('Cannot find module') && e.message.includes('/build/')) {\n this.config\n .getLogger()\n .error(\n chalk.red(\n `Before starting the server, you need to create a build: ${chalk.yellow(\n 'ssr-boost build',\n )} or provide path to build dir: ${chalk.yellow(\n 'ssr-boost start --build-dir build',\n )}`,\n ),\n );\n\n return process.exit(1);\n }\n\n throw e;\n }\n\n if (!shouldInit && resolvedEntrypoint.init) {\n delete resolvedEntrypoint.init;\n }\n\n const { render, init, routes, abortDelay } = resolvedEntrypoint;\n const { onServerCreated, ...renderParams } =\n (await init?.({\n config: this.config,\n })) ?? {};\n\n this.entrypoint = {\n render,\n routes,\n abortDelay,\n ...renderParams,\n };\n this.onServerCreated = onServerCreated;\n\n return this.entrypoint;\n }\n\n /**\n * Load and return html shell\n */\n public async loadHtml(req: Request): Promise<[string, string]> {\n const { isProd, root, indexFile } = this.config.getParams();\n\n if (!this.html || !isProd) {\n this.html = fs.readFileSync(path.resolve(`${root}/${indexFile}`), 'utf-8');\n }\n\n let modifiedHtml = this.html;\n\n if (!isProd) {\n // Apply Vite HTML transforms. This injects the Vite HMR client,\n // and also applies HTML transforms from Vite plugins, e.g. global\n // preambles from @vitejs/plugin-react\n modifiedHtml = (await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html))\n // Make vite script 'async'\n .replace(/(<script.+)(>[\\s\\S]+injectIntoGlobalHook.+)/, '$1async$2');\n }\n\n return modifiedHtml.split('<!--ssr-outlet-->') as [string, string];\n }\n\n /**\n * Run server created hook\n */\n public async onAppCreated(): Promise<PrepareServer> {\n await this.loadEntrypoint();\n await this.onServerCreated?.(this.config.getApp()!);\n\n return this;\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","entrypoint","onServerCreated","html","constructor","this","static","async","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","pathToFileURL","toString","default","getVite","ssrLoadModule","fixStacktrace","e","message","includes","getLogger","error","chalk","red","yellow","process","exit","init","render","routes","abortDelay","renderParams","req","indexFile","fs","readFileSync","modifiedHtml","transformIndexHtml","originalUrl","replace","split","loadEntrypoint","getApp"],"mappings":"gIA4BA,MAAMA,EAIeC,OAKTC,WAKAC,gBAKAC,KAKVC,YAAsBJ,GACpBK,KAAKL,OAASA,CACf,CAKMM,YAAYN,GACjB,OAAO,IAAID,EAAcC,EAC1B,CAKMO,qBAAqBC,GAAa,GAEvC,GAAIH,KAAKJ,YAAcI,KAAKL,OAAOS,OACjC,OAAOJ,KAAKJ,WAGd,MAAMS,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeN,KAAKL,OAAOY,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,SAOyBQ,OAAOC,EAAcL,GAAgBM,aAAaC,eALtEf,KAAKL,OAAOqB,UAAWC,cAAcT,EAAgB,CACzDU,eAAe,KAEjBH,OAIL,CAAC,MAAOI,GACP,GAAIA,EAAEC,QAAQC,SAAS,uBAAyBF,EAAEC,QAAQC,SAAS,WAajE,OAZArB,KAAKL,OACF2B,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,oDACiCF,EAAME,OACvC,yCAKDC,EAAQC,KAAK,GAGtB,MAAMT,CACP,EAEIhB,GAAcQ,EAAmBkB,aAC7BlB,EAAmBkB,KAG5B,MAAMC,OAAEA,EAAMD,KAAEA,EAAIE,OAAEA,EAAMC,WAAEA,GAAerB,GACvCd,gBAAEA,KAAoBoC,SACnBJ,IAAO,CACZlC,OAAQK,KAAKL,WACR,CAAA,EAUT,OARAK,KAAKJ,WAAa,CAChBkC,SACAC,SACAC,gBACGC,GAELjC,KAAKH,gBAAkBA,EAEhBG,KAAKJ,UACb,CAKMM,eAAegC,GACpB,MAAM9B,OAAEA,EAAMC,KAAEA,EAAI8B,UAAEA,GAAcnC,KAAKL,OAAOY,YAE3CP,KAAKF,MAASM,IACjBJ,KAAKF,KAAOsC,EAAGC,aAAa5B,EAAKC,QAAQ,GAAGL,KAAQ8B,KAAc,UAGpE,IAAIG,EAAetC,KAAKF,KAWxB,OATKM,IAIHkC,SAAsBtC,KAAKL,OAAOqB,UAAWuB,mBAAmBL,EAAIM,YAAaxC,KAAKF,OAEnF2C,QAAQ,8CAA+C,cAGrDH,EAAaI,MAAM,0BAC3B,CAKMxC,qBAIL,aAHMF,KAAK2C,uBACL3C,KAAKH,kBAAkBG,KAAKL,OAAOiD,WAElC5C,IACR"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import i from"node:path";import
|
|
1
|
+
import i from"node:path";import t from"../helpers/plugin-config.js";import s from"./logger.js";class r{isProd;isHost;isModulePreload;isSPA;mode;vite;app;params;prodParams;logger;defaultRoot="./build";constructor({isProd:i=!1,isHost:t=!1,isOnlyClient:s=!1,isModulePreload:r=!1,mode:e="production"},o){this.isProd=i,this.isHost=t,this.isSPA=s,this.isModulePreload=r,this.mode=e,this.prodParams={root:this.defaultRoot,publicDir:"/client",indexFile:"/client/index.html",serverFile:"/server/server.js",host:"127.0.0.1",port:3e3,...o},this.makeParams()}static init(i={},t={}){return new r(i,t)}makeParams(){const t=this.getPluginConfig()??{},{config:r}=this.vite??{},e=r?.root??this.prodParams.root??this.defaultRoot,o=r?.publicDir??this.prodParams.publicDir,a=new URL(import.meta.url),h=t.pluginPath??i.resolve(i.dirname(a.pathname),"../"),l=t.indexFile??this.prodParams.indexFile,p=t.serverFile??this.prodParams.serverFile,d="boolean"==typeof r?.server.host||this.isHost?"0.0.0.0":r?.server.host??this.prodParams.host,n=r?.server.port??(this.isProd?this.prodParams.port:5173);this.params={root:e,publicDir:o,pluginPath:h,indexFile:l,serverFile:p,host:d,port:n,isSPA:this.isSPA,isProd:this.isProd},this.logger=this.vite?.config.logger??new s}setVite(i){this.vite=i,this.makeParams()}setApp(i){this.app=i}getVite(){return this.vite}getApp(){return this.app}getPluginConfig(){return this.vite?t(this.vite.config):void 0}getParams(){return this.params}getLogger(){return this.logger}}export{r as default};
|
|
2
2
|
//# sourceMappingURL=server-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.js","sources":["../../src/services/server-config.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Express } from 'express';\nimport type { Logger, ViteDevServer } from 'vite';\nimport type { IPluginConfig } from '@helpers/plugin-config';\nimport getPluginConfig from '@helpers/plugin-config';\nimport DefaultLogger from '@services/logger';\n\ninterface IConfigOptions {\n isProd?: boolean;\n isHost?: boolean;\n isOnlyClient?: boolean; // SPA mode\n isModulePreload?: boolean;\n mode?: string;\n}\n\ninterface IConfigParams {\n root: string;\n publicDir: string;\n pluginPath: string;\n isProd: boolean;\n isSPA: boolean;\n indexFile: string;\n serverFile: string;\n host: string;\n port: number;\n}\n\n/**\n * Server config\n */\nclass ServerConfig {\n /**\n * Production build\n */\n public readonly isProd: boolean;\n\n /**\n * Server host mode\n */\n public readonly isHost: boolean;\n\n /**\n * Add module preload scripts to server output\n */\n public readonly isModulePreload: boolean;\n\n /**\n * SPA mode\n */\n public readonly isSPA: boolean;\n\n /**\n * Env mode\n */\n public readonly mode: string;\n\n /**\n * Vite config - only for development\n */\n protected vite?: ViteDevServer;\n\n /**\n * Express application\n */\n protected app?: Express;\n\n /**\n * Config params\n */\n protected params: IConfigParams;\n\n /**\n * Default production params\n */\n protected prodParams: Partial<IConfigParams>;\n\n /**\n * Vite logger for dev mode or console for production\n */\n protected logger: Logger;\n\n /**\n * @constructor\n */\n protected constructor(\n {\n isProd = false,\n isHost = false,\n isOnlyClient = false,\n isModulePreload = false,\n mode = 'production',\n }: IConfigOptions,\n prodParams: Partial<IConfigParams>,\n ) {\n this.isProd = isProd;\n this.isHost = isHost;\n this.isSPA = isOnlyClient;\n this.isModulePreload = isModulePreload;\n this.mode = mode;\n this.prodParams = {\n root:
|
|
1
|
+
{"version":3,"file":"server-config.js","sources":["../../src/services/server-config.ts"],"sourcesContent":["import path from 'node:path';\nimport type { Express } from 'express';\nimport type { Logger, ViteDevServer } from 'vite';\nimport type { IPluginConfig } from '@helpers/plugin-config';\nimport getPluginConfig from '@helpers/plugin-config';\nimport DefaultLogger from '@services/logger';\n\ninterface IConfigOptions {\n isProd?: boolean;\n isHost?: boolean;\n isOnlyClient?: boolean; // SPA mode\n isModulePreload?: boolean;\n mode?: string;\n}\n\ninterface IConfigParams {\n root: string;\n publicDir: string;\n pluginPath: string;\n isProd: boolean;\n isSPA: boolean;\n indexFile: string;\n serverFile: string;\n host: string;\n port: number;\n}\n\n/**\n * Server config\n */\nclass ServerConfig {\n /**\n * Production build\n */\n public readonly isProd: boolean;\n\n /**\n * Server host mode\n */\n public readonly isHost: boolean;\n\n /**\n * Add module preload scripts to server output\n */\n public readonly isModulePreload: boolean;\n\n /**\n * SPA mode\n */\n public readonly isSPA: boolean;\n\n /**\n * Env mode\n */\n public readonly mode: string;\n\n /**\n * Vite config - only for development\n */\n protected vite?: ViteDevServer;\n\n /**\n * Express application\n */\n protected app?: Express;\n\n /**\n * Config params\n */\n protected params: IConfigParams;\n\n /**\n * Default production params\n */\n protected prodParams: Partial<IConfigParams>;\n\n /**\n * Vite logger for dev mode or console for production\n */\n protected logger: Logger;\n\n /**\n * Default root dir\n */\n protected defaultRoot = './build';\n\n /**\n * @constructor\n */\n protected constructor(\n {\n isProd = false,\n isHost = false,\n isOnlyClient = false,\n isModulePreload = false,\n mode = 'production',\n }: IConfigOptions,\n prodParams: Partial<IConfigParams>,\n ) {\n this.isProd = isProd;\n this.isHost = isHost;\n this.isSPA = isOnlyClient;\n this.isModulePreload = isModulePreload;\n this.mode = mode;\n this.prodParams = {\n root: this.defaultRoot,\n publicDir: '/client', // default for production,\n indexFile: '/client/index.html',\n serverFile: '/server/server.js',\n host: '127.0.0.1',\n port: 3000,\n ...prodParams,\n };\n\n this.makeParams();\n }\n\n /**\n * Initialize service\n */\n public static init(\n options: IConfigOptions = {},\n prodOptions: Partial<IConfigParams> = {},\n ): ServerConfig {\n return new ServerConfig(options, prodOptions);\n }\n\n /**\n * Make config params\n */\n protected makeParams(): void {\n const pluginConfig = (this.getPluginConfig() ?? {}) as Partial<IPluginConfig>;\n const { config } = this.vite ?? {};\n\n const root = config?.root ?? this.prodParams.root ?? this.defaultRoot;\n const publicDir = config?.publicDir ?? this.prodParams.publicDir!;\n const dirInfo = new URL(import.meta.url);\n const pluginPath =\n pluginConfig.pluginPath ?? path.resolve(path.dirname(dirInfo.pathname), '../');\n const indexFile = pluginConfig.indexFile ?? this.prodParams.indexFile!;\n const serverFile = pluginConfig.serverFile ?? this.prodParams.serverFile!;\n const host =\n typeof config?.server.host === 'boolean' || this.isHost\n ? '0.0.0.0'\n : config?.server.host ?? this.prodParams.host!;\n const port = config?.server.port ?? (this.isProd ? this.prodParams.port! : 5173);\n\n this.params = {\n root,\n publicDir,\n pluginPath,\n indexFile,\n serverFile,\n host,\n port,\n isSPA: this.isSPA,\n isProd: this.isProd,\n };\n this.logger = this.vite?.config.logger ?? new DefaultLogger();\n }\n\n /**\n * Set vite server\n */\n public setVite(vite: ViteDevServer): void {\n this.vite = vite;\n\n this.makeParams();\n }\n\n /**\n * Set express server\n */\n public setApp(express: Express): void {\n this.app = express;\n }\n\n /**\n * Return vite dev server\n * NOTE: only on development mode\n */\n public getVite(): ViteDevServer | undefined {\n return this.vite;\n }\n\n /**\n * Return express server\n */\n public getApp(): Express | undefined {\n return this.app;\n }\n\n /**\n * return plugin config\n * NOTE: only on development mode\n */\n public getPluginConfig(): IPluginConfig | undefined {\n return this.vite ? getPluginConfig(this.vite.config) : undefined;\n }\n\n /**\n * Return config params\n */\n public getParams(): IConfigParams {\n return this.params;\n }\n\n /**\n * Get server logger\n */\n public getLogger(): Logger {\n return this.logger;\n }\n}\n\nexport default ServerConfig;\n"],"names":["ServerConfig","isProd","isHost","isModulePreload","isSPA","mode","vite","app","params","prodParams","logger","defaultRoot","constructor","isOnlyClient","this","root","publicDir","indexFile","serverFile","host","port","makeParams","static","options","prodOptions","pluginConfig","getPluginConfig","config","dirInfo","URL","url","pluginPath","path","resolve","dirname","pathname","server","DefaultLogger","setVite","setApp","express","getVite","getApp","undefined","getParams","getLogger"],"mappings":"+FA8BA,MAAMA,EAIYC,OAKAC,OAKAC,gBAKAC,MAKAC,KAKNC,KAKAC,IAKAC,OAKAC,WAKAC,OAKAC,YAAc,UAKxBC,aACEX,OACEA,GAAS,EAAKC,OACdA,GAAS,EAAKW,aACdA,GAAe,EAAKV,gBACpBA,GAAkB,EAAKE,KACvBA,EAAO,cAETI,GAEAK,KAAKb,OAASA,EACda,KAAKZ,OAASA,EACdY,KAAKV,MAAQS,EACbC,KAAKX,gBAAkBA,EACvBW,KAAKT,KAAOA,EACZS,KAAKL,WAAa,CAChBM,KAAMD,KAAKH,YACXK,UAAW,UACXC,UAAW,qBACXC,WAAY,oBACZC,KAAM,YACNC,KAAM,OACHX,GAGLK,KAAKO,YACN,CAKMC,YACLC,EAA0B,GAC1BC,EAAsC,CAAA,GAEtC,OAAO,IAAIxB,EAAauB,EAASC,EAClC,CAKSH,aACR,MAAMI,EAAgBX,KAAKY,mBAAqB,CAAE,GAC5CC,OAAEA,GAAWb,KAAKR,MAAQ,CAAA,EAE1BS,EAAOY,GAAQZ,MAAQD,KAAKL,WAAWM,MAAQD,KAAKH,YACpDK,EAAYW,GAAQX,WAAaF,KAAKL,WAAWO,UACjDY,EAAU,IAAIC,gBAAgBC,KAC9BC,EACJN,EAAaM,YAAcC,EAAKC,QAAQD,EAAKE,QAAQN,EAAQO,UAAW,OACpElB,EAAYQ,EAAaR,WAAaH,KAAKL,WAAWQ,UACtDC,EAAaO,EAAaP,YAAcJ,KAAKL,WAAWS,WACxDC,EAC2B,kBAAxBQ,GAAQS,OAAOjB,MAAsBL,KAAKZ,OAC7C,UACAyB,GAAQS,OAAOjB,MAAQL,KAAKL,WAAWU,KACvCC,EAAOO,GAAQS,OAAOhB,OAASN,KAAKb,OAASa,KAAKL,WAAWW,KAAQ,MAE3EN,KAAKN,OAAS,CACZO,OACAC,YACAe,aACAd,YACAC,aACAC,OACAC,OACAhB,MAAOU,KAAKV,MACZH,OAAQa,KAAKb,QAEfa,KAAKJ,OAASI,KAAKR,MAAMqB,OAAOjB,QAAU,IAAI2B,CAC/C,CAKMC,QAAQhC,GACbQ,KAAKR,KAAOA,EAEZQ,KAAKO,YACN,CAKMkB,OAAOC,GACZ1B,KAAKP,IAAMiC,CACZ,CAMMC,UACL,OAAO3B,KAAKR,IACb,CAKMoC,SACL,OAAO5B,KAAKP,GACb,CAMMmB,kBACL,OAAOZ,KAAKR,KAAOoB,EAAgBZ,KAAKR,KAAKqB,aAAUgB,CACxD,CAKMC,YACL,OAAO9B,KAAKN,MACb,CAKMqC,YACL,OAAO/B,KAAKJ,MACb"}
|
|
@@ -85,6 +85,13 @@ declare class SsrManifest {
|
|
|
85
85
|
* Get singleton instance
|
|
86
86
|
*/
|
|
87
87
|
static get(config: ServerConfig, params?: ISsrManifestParams): SsrManifest;
|
|
88
|
+
/**
|
|
89
|
+
* Get output dir
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* Get output dir
|
|
93
|
+
*/
|
|
94
|
+
protected getOutDir(): string;
|
|
88
95
|
/**
|
|
89
96
|
* Get assets manifest file name
|
|
90
97
|
*/
|
package/services/ssr-manifest.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"node:fs";import e from"node:path";import s from"chalk";import i from"./prepare-server.js";import r from"./server-config.js";var o;!function(t){t.style="style",t.script="script",t.image="image",t.font="font"}(o||(o={}));const n="\r\n";class a{static instance=null;config;root;buildDir;manifestName="manifest.json";assetsManifest="assets-manifest.json";viteAliases;routesAssets=null;constructor(t,{buildDir:e,viteAliases:s}={}){this.config=t,this.root=t.getParams().root,this.buildDir=e,this.viteAliases=s??t.getVite()?.config?.resolve.alias}static get(t,e={}){return null===a.instance&&(a.instance=new a(t,e)),a.instance}
|
|
1
|
+
import t from"node:fs";import e from"node:path";import s from"chalk";import i from"./prepare-server.js";import r from"./server-config.js";var o;!function(t){t.style="style",t.script="script",t.image="image",t.font="font"}(o||(o={}));const n="\r\n";class a{static instance=null;config;root;buildDir;manifestName="manifest.json";assetsManifest="assets-manifest.json";viteAliases;routesAssets=null;constructor(t,{buildDir:e,viteAliases:s}={}){this.config=t,this.root=t.getParams().root,this.buildDir=e,this.viteAliases=s??t.getVite()?.config?.resolve.alias}static get(t,e={}){return null===a.instance&&(a.instance=new a(t,e)),a.instance}getOutDir(){return e.resolve(this.root,this.buildDir||"")}getAssetsManifestFile(){return`${this.getOutDir()}/server/${this.assetsManifest}`}loadClientManifest(){const s=e.resolve(this.root,`${this.buildDir||""}/client/.vite`),i=`${s}/${this.manifestName}`;if(!t.existsSync(i))return{};const r=JSON.parse(t.readFileSync(i,{encoding:"utf-8"}));return t.rmSync(i),0===t.readdirSync(s).length&&t.rmSync(s,{recursive:!0}),r}loadAssetsManifest(){if(null!==this.routesAssets)return this.routesAssets;const e=this.getAssetsManifestFile();return t.existsSync(e)?(this.routesAssets=JSON.parse(t.readFileSync(e,{encoding:"utf-8"})),this.routesAssets):{}}async getRoutesIds(t,e){const i={};for(const r in t){const o=t[r],n=[e,r].filter(Boolean).join("-");if(o.lazy)try{const t=await o.lazy();i[n]=this.normalizeRoutePath(t?.pathId)}catch(t){console.error(s.red("Failed to load route:"),o.path,t)}else o.children&&Object.assign(i,await this.getRoutesIds(o.children,n))}return i}sortAssets(t){return t.sort(((t,e)=>t.weight===e.weight?Number(t.isNested)-Number(e.isNested):t.weight-e.weight))}getRouteAssets(t,e,s=!1){const i=[...e?.assets??[],...e?.css??[],e?.file].reduce(((t,i)=>{if(i){const r=this.getAssetType(i),o=e.isEntry&&e.file===i;r&&(t[i]={url:`/${i}`,weight:o?1.9:this.getAssetWeight(i),type:r,isNested:s,isPreload:!o})}return t}),{});return e?.imports?.length&&e.imports.forEach((e=>{const s=t[e];s&&Object.assign(i,this.getRouteAssets(t,s,!0))})),i}async buildRoutesManifest(){const e=i.init(r.init({isProd:!0},{root:this.getOutDir()})),s=this.loadClientManifest(),{routes:o}=await e.loadEntrypoint(!1),n=await this.getRoutesIds(o),a=this.getRouteImportPostfix(),l={};Object.entries(n).forEach((([t,e])=>{const i=a.find((t=>void 0!==s[`${e}${t}`])),r=s[`${e}${i||""}`];l[t]=this.sortAssets(Object.values(this.getRouteAssets(s,r)))})),t.writeFileSync(this.getAssetsManifestFile(),JSON.stringify(l,null,2),{encoding:"utf-8"})}getAliases(){const t={};return this.viteAliases?.forEach((({find:e,replacement:s})=>{"string"==typeof e&&(t[e]=s)})),t}getRouteImportPostfix(){return["","/index"].map((t=>["",".js",".ts",".tsx"].map((e=>`${t}${e}`)))).flat()}normalizeRoutePath(t,s=!1){if(!t)return;let i="";if(t.startsWith("./")||t.startsWith("../"))i=e.resolve(this.root,t);else{const e=this.getAliases(),[s]=t.split("/");e[s]&&(i=t.replace(s,e[s]))}return i=i.split(e.win32.sep).join(e.posix.sep),s?i:i.replace(this.root,"").replace(/^\/|\/$/g,"")}getAssets(t){if(this.config.getVite())return this.getAssetsDev(t);const e=t?.map((({route:t})=>t.id)).filter(Boolean)??[];if(!e.length)return[];const s=this.loadAssetsManifest();return this.sortAssets(e.map((t=>s[t])).flat().filter(Boolean))}getAssetsDev(t){const e=t?.map((({route:t})=>this.normalizeRoutePath(t?.pathId,!0))).filter(Boolean)??[];if(!e.length)return[];let s={};const i=this.getRouteImportPostfix();return[`${this.root}/${this.config.getPluginConfig()?.clientFile??"client.ts"}`,...e].forEach((t=>{for(const e of i){const i=this.config.getVite()?.moduleGraph.getModuleById(`${t}${e}`);if(i){s={...s,...this.getModuleAssets(i)};break}}})),Object.values(s)}getModuleAssets(t,e=new Set){if(!t?.clientImportedModules.size||e.has(t.file))return{};let i={};return e.add(t.file),t.clientImportedModules.forEach((t=>{const{file:r,clientImportedModules:n,transformResult:a}=t,l=r?.split(".").at(-1);if(r&&l&&["css","scss"].includes(l)){const t=a?.code.match(/__vite__css\s+=\s+"(?<css>.+)"/)?.groups?.css;if(t)try{i[r]={type:o.style,url:r,weight:this.getAssetWeight(r),content:JSON.parse(`{"style": "${t}"}`).style,isNested:Boolean(e.size),isPreload:!1}}catch(t){console.warn(s.yellowBright("Failed to parse style: ",r))}}else n.size&&(i={...i,...this.getModuleAssets(t,e)})})),i}getAssetWeight(t){switch(this.getAssetType(t)){case o.style:return 1;case o.script:return 2;default:return 3}}getAssetType(t){const e=t.split(".").at(-1)?.toLowerCase();switch(e){case"css":case"scss":return o.style;case"js":return o.script;case"svg":case"jpg":case"jpeg":case"png":case"webp":case"gif":case"ico":return o.image;case"ttf":case"otf":case"woff":case"woff2":return o.font;default:return null}}writeEarlyHits(t,e){e.write(`HTTP/1.1 103 Early Hints${n}`),t.forEach((({type:t,url:s})=>{t&&["style","script"].includes(t)&&e.write(`Link: <${s}>; rel=preload; as=${t}${n}`)})),e.write(n)}injectAssets({routerContext:t,html:e,res:s,hasEarlyHints:i=!1}){const r=this.getAssets(t?.matches),n=r.map((({type:t,url:e,isPreload:s,content:i=""})=>{switch(t){case o.style:return this.config.getVite()?`<style data-vite-dev-id="${e}">${i}</style>`:`<link rel="stylesheet" href="${e}">`;case o.script:return s?this.config.isModulePreload?`<link rel="modulepreload" as="script" crossorigin href="${e}">`:null:`<script async type="module" crossorigin src="${e}"><\/script>`}return null})).filter(Boolean);e.header=e.header.replace("</head>",`${n.join("\n")}</head>`),i&&n.length&&s.socket&&this.writeEarlyHits(r,s.socket)}}export{a as default};
|
|
2
2
|
//# sourceMappingURL=ssr-manifest.js.map
|
|
@@ -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 type { AgnosticDataRouteMatch } from '@remix-run/router/dist/utils';\nimport chalk from 'chalk';\nimport type { RouteObject } from 'react-router-dom';\nimport type { Alias, ModuleNode } from 'vite';\nimport type { IAsyncRoute } from '@helpers/import-route';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n buildDir?: string;\n viteAliases?: Alias[];\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 * 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 * Loaded assets manifest file\n */\n protected routesAssets: Record<string, IAsset[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig, { buildDir, viteAliases }: ISsrManifestParams = {}) {\n this.config = config;\n this.root = config.getParams().root;\n this.buildDir = buildDir;\n this.viteAliases = viteAliases ?? config.getVite()?.config?.resolve.alias;\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 assets manifest file name\n */\n protected getAssetsManifestFile(): string {\n const outDir = path.resolve(this.root, this.buildDir || '');\n\n return `${outDir}/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 * Recursive walk routes and return id's with route import path\n */\n protected async getRoutesIds(\n routes: RouteObject[],\n index?: string,\n ): Promise<Record<string, string | undefined>> {\n const result: Record<string, string | undefined> = {};\n\n for (const routeIndex in routes) {\n const route = routes[routeIndex];\n const routeId = [index, routeIndex].filter(Boolean).join('-');\n\n if (route.lazy) {\n try {\n const resolvedRoute: IAsyncRoute = await route.lazy();\n\n result[routeId] = this.normalizeRoutePath(resolvedRoute?.pathId);\n } catch (e) {\n console.error(chalk.red('Failed to load route:'), route.path, e);\n }\n } else if (route.children) {\n Object.assign(result, await this.getRoutesIds(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 res[asset] = {\n url: `/${asset}`,\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 async buildRoutesManifest(): Promise<void> {\n const prepareServer = PrepareServer.init(ServerConfig.init({ isProd: true }));\n const manifest = this.loadClientManifest();\n const { routes } = await prepareServer.loadEntrypoint(false);\n const routesPaths = await this.getRoutesIds(routes as RouteObject[]);\n const postfixes = this.getRouteImportPostfix();\n\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 vite aliases\n */\n protected getAliases(): Record<string, string> {\n const aliases: Record<string, string> = {};\n\n this.viteAliases?.forEach(({ find, replacement }) => {\n if (typeof find !== 'string') {\n return;\n }\n\n aliases[find] = replacement;\n });\n\n return aliases;\n }\n\n /**\n * Return route postfix\n */\n protected getRouteImportPostfix(): string[] {\n return ['', '/index']\n .map((prefix) => ['', '.js', '.ts', '.tsx'].map((ext) => `${prefix}${ext}`))\n .flat();\n }\n\n /**\n * Normalized route path\n */\n protected normalizeRoutePath(routePath?: string, withRoot = false): string | undefined {\n if (!routePath) {\n return;\n }\n\n let fullPath = '';\n\n // relative import\n if (routePath.startsWith('./') || routePath.startsWith('../')) {\n fullPath = path.resolve(this.root, routePath);\n } else {\n // alias import\n const aliases = this.getAliases();\n // get alias\n const [routeAlias] = routePath.split('/');\n\n if (aliases[routeAlias]) {\n fullPath = routePath.replace(routeAlias, aliases[routeAlias]);\n }\n }\n\n // normalize slashes\n fullPath = fullPath.split(path.win32.sep).join(path.posix.sep);\n\n if (withRoot) {\n return fullPath;\n }\n\n return fullPath.replace(this.root, '').replace(/^\\/|\\/$/g, '');\n }\n\n /**\n * Get route assets\n */\n protected getAssets(routes?: AgnosticDataRouteMatch[]): 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?: AgnosticDataRouteMatch[]): IAsset[] {\n const routeIds =\n (routes\n ?.map(({ route }) => this.normalizeRoutePath((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.getRouteImportPostfix();\n const rootId = `${this.root}/${this.config.getPluginConfig()?.clientFile ?? 'client.ts'}`;\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}\"}`).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","root","buildDir","manifestName","assetsManifest","viteAliases","routesAssets","constructor","this","getParams","getVite","resolve","alias","params","instance","getAssetsManifestFile","path","loadClientManifest","clientManifestDir","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","readdirSync","length","recursive","loadAssetsManifest","manifestFile","async","routes","index","routeIndex","route","routeId","filter","Boolean","join","lazy","resolvedRoute","normalizeRoutePath","pathId","e","console","error","chalk","red","children","Object","assign","getRoutesIds","sortAssets","assets","sort","a","b","weight","Number","isNested","getRouteAssets","manifest","module","css","file","reduce","res","asset","type","getAssetType","isEntry","url","getAssetWeight","isPreload","imports","forEach","nestedAsset","nestedModule","prepareServer","PrepareServer","init","ServerConfig","isProd","loadEntrypoint","routesPaths","postfixes","getRouteImportPostfix","entries","routePath","routePostfix","find","postfix","undefined","routeMeta","values","writeFileSync","stringify","getAliases","aliases","replacement","map","prefix","ext","flat","withRoot","fullPath","startsWith","routeAlias","split","replace","win32","sep","posix","getAssets","getAssetsDev","routeIds","id","getPluginConfig","clientFile","moduleId","moduleGraph","getModuleById","getModuleAssets","skipModules","Set","clientImportedModules","size","has","add","subModule","transformResult","at","includes","code","match","groups","style","content","warn","yellowBright","script","toLowerCase","image","font","writeEarlyHits","socket","write","injectAssets","routerContext","html","hasEarlyHints","matches","htmlAssets","isModulePreload","header"],"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 type { AgnosticDataRouteMatch } from '@remix-run/router/dist/utils';\nimport chalk from 'chalk';\nimport type { RouteObject } from 'react-router-dom';\nimport type { Alias, ModuleNode } from 'vite';\nimport type { IAsyncRoute } from '@helpers/import-route';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n buildDir?: string;\n viteAliases?: Alias[];\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 * 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 * Loaded assets manifest file\n */\n protected routesAssets: Record<string, IAsset[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig, { buildDir, viteAliases }: ISsrManifestParams = {}) {\n this.config = config;\n this.root = config.getParams().root;\n this.buildDir = buildDir;\n this.viteAliases = viteAliases ?? config.getVite()?.config?.resolve.alias;\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 * Recursive walk routes and return id's with route import path\n */\n protected async getRoutesIds(\n routes: RouteObject[],\n index?: string,\n ): Promise<Record<string, string | undefined>> {\n const result: Record<string, string | undefined> = {};\n\n for (const routeIndex in routes) {\n const route = routes[routeIndex];\n const routeId = [index, routeIndex].filter(Boolean).join('-');\n\n if (route.lazy) {\n try {\n const resolvedRoute: IAsyncRoute = await route.lazy();\n\n result[routeId] = this.normalizeRoutePath(resolvedRoute?.pathId);\n } catch (e) {\n console.error(chalk.red('Failed to load route:'), route.path, e);\n }\n } else if (route.children) {\n Object.assign(result, await this.getRoutesIds(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 res[asset] = {\n url: `/${asset}`,\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 async buildRoutesManifest(): Promise<void> {\n const prepareServer = PrepareServer.init(\n ServerConfig.init({ isProd: true }, { root: this.getOutDir() }),\n );\n const manifest = this.loadClientManifest();\n const { routes } = await prepareServer.loadEntrypoint(false);\n const routesPaths = await this.getRoutesIds(routes as RouteObject[]);\n const postfixes = this.getRouteImportPostfix();\n\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 vite aliases\n */\n protected getAliases(): Record<string, string> {\n const aliases: Record<string, string> = {};\n\n this.viteAliases?.forEach(({ find, replacement }) => {\n if (typeof find !== 'string') {\n return;\n }\n\n aliases[find] = replacement;\n });\n\n return aliases;\n }\n\n /**\n * Return route postfix\n */\n protected getRouteImportPostfix(): string[] {\n return ['', '/index']\n .map((prefix) => ['', '.js', '.ts', '.tsx'].map((ext) => `${prefix}${ext}`))\n .flat();\n }\n\n /**\n * Normalized route path\n */\n protected normalizeRoutePath(routePath?: string, withRoot = false): string | undefined {\n if (!routePath) {\n return;\n }\n\n let fullPath = '';\n\n // relative import\n if (routePath.startsWith('./') || routePath.startsWith('../')) {\n fullPath = path.resolve(this.root, routePath);\n } else {\n // alias import\n const aliases = this.getAliases();\n // get alias\n const [routeAlias] = routePath.split('/');\n\n if (aliases[routeAlias]) {\n fullPath = routePath.replace(routeAlias, aliases[routeAlias]);\n }\n }\n\n // normalize slashes\n fullPath = fullPath.split(path.win32.sep).join(path.posix.sep);\n\n if (withRoot) {\n return fullPath;\n }\n\n return fullPath.replace(this.root, '').replace(/^\\/|\\/$/g, '');\n }\n\n /**\n * Get route assets\n */\n protected getAssets(routes?: AgnosticDataRouteMatch[]): 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?: AgnosticDataRouteMatch[]): IAsset[] {\n const routeIds =\n (routes\n ?.map(({ route }) => this.normalizeRoutePath((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.getRouteImportPostfix();\n const rootId = `${this.root}/${this.config.getPluginConfig()?.clientFile ?? 'client.ts'}`;\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}\"}`).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","root","buildDir","manifestName","assetsManifest","viteAliases","routesAssets","constructor","this","getParams","getVite","resolve","alias","params","instance","getOutDir","path","getAssetsManifestFile","loadClientManifest","clientManifestDir","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","readdirSync","length","recursive","loadAssetsManifest","manifestFile","async","routes","index","routeIndex","route","routeId","filter","Boolean","join","lazy","resolvedRoute","normalizeRoutePath","pathId","e","console","error","chalk","red","children","Object","assign","getRoutesIds","sortAssets","assets","sort","a","b","weight","Number","isNested","getRouteAssets","manifest","module","css","file","reduce","res","asset","type","getAssetType","isEntry","url","getAssetWeight","isPreload","imports","forEach","nestedAsset","nestedModule","prepareServer","PrepareServer","init","ServerConfig","isProd","loadEntrypoint","routesPaths","postfixes","getRouteImportPostfix","entries","routePath","routePostfix","find","postfix","undefined","routeMeta","values","writeFileSync","stringify","getAliases","aliases","replacement","map","prefix","ext","flat","withRoot","fullPath","startsWith","routeAlias","split","replace","win32","sep","posix","getAssets","getAssetsDev","routeIds","id","getPluginConfig","clientFile","moduleId","moduleGraph","getModuleById","getModuleAssets","skipModules","Set","clientImportedModules","size","has","add","subModule","transformResult","at","includes","code","match","groups","style","content","warn","yellowBright","script","toLowerCase","image","font","writeEarlyHits","socket","write","injectAssets","routerContext","html","hasEarlyHints","matches","htmlAssets","isModulePreload","header"],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Plugin } from 'vite';
|
|
2
|
-
interface IPluginOptions {
|
|
3
|
-
root?: string;
|
|
4
|
-
tsconfig?: string;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Read tsconfig file and set vite aliases
|
|
8
|
-
* @constructor
|
|
9
|
-
*/
|
|
10
|
-
declare function ViteMakeAliasesPlugin(options?: IPluginOptions): Plugin;
|
|
11
|
-
export { ViteMakeAliasesPlugin as default, IPluginOptions };
|
package/plugins/make-aliases.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import e from"node:fs";import o from"node:path";import s from"node:process";import r from"hjson";import t from"../constants/plugin-name.js";import n from"../helpers/vite-aliases.js";const i=`${t}-make-aliases`,a=e=>e.replace("/*","");function c(t={}){const{root:c,tsconfig:p}=t,f=c??s.cwd(),m=o.resolve(f,p??"tsconfig.json"),l=[];if(e.existsSync(m)){const o=r.parse(e.readFileSync(m,{encoding:"utf-8"})),s=o?.compilerOptions?.paths??{};Object.entries(s).forEach((([e,o])=>{l.push([a(e),a(o[0])])}))}else console.error(`${i}: tsconfig not exist in "${m}"`);return{name:i,config(e){if(l.length){const o=e.resolve??{},s=o.alias??[],r=Array.isArray(s)?s:Object.entries(s).map((([e,o])=>({find:e,replacement:o})));r.push(...n(l,`${f}/${e?.root??""}`)),e.resolve={...o,alias:r}}return e}}}export{c as default};
|
|
2
|
-
//# sourceMappingURL=make-aliases.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"make-aliases.js","sources":["../../src/plugins/make-aliases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport process from 'node:process';\nimport Hjson from 'hjson';\nimport type { Plugin } from 'vite';\nimport PLUGIN_NAME from '@constants/plugin-name';\nimport ViteAliases from '@helpers/vite-aliases';\n\nexport interface IPluginOptions {\n root?: string; // default: cwd()\n tsconfig?: string; // default: tsconfig.json\n}\n\nconst pluginName = `${PLUGIN_NAME}-make-aliases`;\nconst cleanupAlias = (str: string): string => str.replace('/*', '');\n\n/**\n * Read tsconfig file and set vite aliases\n * @constructor\n */\nfunction ViteMakeAliasesPlugin(options: IPluginOptions = {}): Plugin {\n const { root, tsconfig } = options;\n const projectRoot = root ?? process.cwd();\n const tsconfigPath = path.resolve(projectRoot, tsconfig ?? 'tsconfig.json');\n const aliases: [string, string][] = [];\n\n if (!fs.existsSync(tsconfigPath)) {\n console.error(`${pluginName}: tsconfig not exist in \"${tsconfigPath}\"`);\n } else {\n const tsJson = Hjson.parse(fs.readFileSync(tsconfigPath, { encoding: 'utf-8' }));\n const paths: Record<string, string[]> = tsJson?.compilerOptions?.paths ?? {};\n\n Object.entries(paths).forEach(([alias, aliasPaths]) => {\n aliases.push([cleanupAlias(alias), cleanupAlias(aliasPaths[0])]);\n });\n }\n\n return {\n name: pluginName,\n config(config) {\n if (aliases.length) {\n const resolveConfig = config.resolve ?? {};\n const defaultAliases = resolveConfig.alias ?? [];\n const normalizedAliases = Array.isArray(defaultAliases)\n ? defaultAliases\n : Object.entries(defaultAliases).map(([find, val]) => ({ find, replacement: val }));\n\n normalizedAliases.push(...ViteAliases(aliases, `${projectRoot}/${config?.root ?? ''}`));\n\n config.resolve = {\n ...resolveConfig,\n alias: normalizedAliases,\n };\n }\n\n return config;\n },\n };\n}\n\nexport default ViteMakeAliasesPlugin;\n"],"names":["pluginName","PLUGIN_NAME","cleanupAlias","str","replace","ViteMakeAliasesPlugin","options","root","tsconfig","projectRoot","process","cwd","tsconfigPath","path","resolve","aliases","fs","existsSync","tsJson","Hjson","parse","readFileSync","encoding","paths","compilerOptions","Object","entries","forEach","alias","aliasPaths","push","console","error","name","config","length","resolveConfig","defaultAliases","normalizedAliases","Array","isArray","map","find","val","replacement","ViteAliases"],"mappings":"sLAaA,MAAMA,EAAa,GAAGC,iBAChBC,EAAgBC,GAAwBA,EAAIC,QAAQ,KAAM,IAMhE,SAASC,EAAsBC,EAA0B,IACvD,MAAMC,KAAEA,EAAIC,SAAEA,GAAaF,EACrBG,EAAcF,GAAQG,EAAQC,MAC9BC,EAAeC,EAAKC,QAAQL,EAAaD,GAAY,iBACrDO,EAA8B,GAEpC,GAAKC,EAAGC,WAAWL,GAEZ,CACL,MAAMM,EAASC,EAAMC,MAAMJ,EAAGK,aAAaT,EAAc,CAAEU,SAAU,WAC/DC,EAAkCL,GAAQM,iBAAiBD,OAAS,CAAA,EAE1EE,OAAOC,QAAQH,GAAOI,SAAQ,EAAEC,EAAOC,MACrCd,EAAQe,KAAK,CAAC5B,EAAa0B,GAAQ1B,EAAa2B,EAAW,KAAK,GAEnE,MARCE,QAAQC,MAAM,GAAGhC,6BAAsCY,MAUzD,MAAO,CACLqB,KAAMjC,EACNkC,OAAOA,GACL,GAAInB,EAAQoB,OAAQ,CAClB,MAAMC,EAAgBF,EAAOpB,SAAW,GAClCuB,EAAiBD,EAAcR,OAAS,GACxCU,EAAoBC,MAAMC,QAAQH,GACpCA,EACAZ,OAAOC,QAAQW,GAAgBI,KAAI,EAAEC,EAAMC,MAAU,CAAED,OAAME,YAAaD,MAE9EL,EAAkBR,QAAQe,EAAY9B,EAAS,GAAGN,KAAeyB,GAAQ3B,MAAQ,OAEjF2B,EAAOpB,QAAU,IACZsB,EACHR,MAAOU,EAEV,CAED,OAAOJ,CACR,EAEL"}
|