@lomray/vite-ssr-boost 8.0.0-beta.6 → 8.1.0-beta.1
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 +43 -38
- package/node/production.d.ts +19 -0
- package/node/production.js +2 -0
- package/node/production.js.map +1 -0
- package/package.json +9 -1
- package/services/route-assets.d.ts +64 -0
- package/services/route-assets.js +2 -0
- package/services/route-assets.js.map +1 -0
- package/services/ssr-manifest.d.ts +11 -52
- package/services/ssr-manifest.js +1 -1
- package/services/ssr-manifest.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,60 +1,65 @@
|
|
|
1
1
|
# Vite SSR BOOST
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
<img src="https://raw.githubusercontent.com/Lomray-Software/vite-ssr-boost/prod/logo.png" alt="Vite SSR BOOST logo" width="250" height="250">
|
|
5
|
-
</p>
|
|
3
|
+
SSR for React Router apps in [Data mode](https://reactrouter.com/start/modes), without moving to Framework mode and without rewriting the app. `@lomray/vite-ssr-boost` adds server rendering to your Vite project while keeping your route objects and components. Build SSR and SPA output from the same app, and choose a managed Express server or a Fetch handler for your own transport.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
## Who this is for
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
- Teams adding SSR to a Vite SPA with React Router route objects.
|
|
8
|
+
- Teams that need server rendering and SPA output from one application.
|
|
9
|
+
- Teams that want to control request hooks, response headers and deployment.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## What you keep
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
- React Router
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- response-aware helpers such as redirects and status codes
|
|
19
|
-
- custom entrypoints for mobile, embedded and service-worker-friendly shells
|
|
13
|
+
- Your Vite configuration and plugins, with the SSR plugin added.
|
|
14
|
+
- Your React Router route objects.
|
|
15
|
+
- Your components, after removing browser globals from server execution.
|
|
16
|
+
- Your React version within the package's peer range: React and React DOM `>=18.2.0`.
|
|
17
|
+
- Your hosting choice, provided it can run the selected SSR transport or serve SPA files.
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</p>
|
|
19
|
+
## What you add
|
|
20
|
+
|
|
21
|
+
Add `SsrBoost()` to the Vite plugins, wire `client.ts` and `server.ts`, and replace the Vite scripts with `ssr-boost` commands. The [migration guide](./docs/guide/migrate-existing-spa.md) includes these entries and the HTML outlet, copied from the minimal example.
|
|
22
|
+
|
|
23
|
+
## Choose your server
|
|
24
|
+
|
|
25
|
+
**Managed CLI (default).** Use `ssr-boost dev` for Express with Vite development and HMR, then `ssr-boost build` and `ssr-boost start` for production assets and SSR. The server entry is `@lomray/vite-ssr-boost/adapters/express/entry`, with hooks for requests, rendering and responses.
|
|
26
|
+
|
|
27
|
+
**Fetch handler.** Import `createHandler` from `@lomray/vite-ssr-boost/core/handler` and connect it through `adapters/node`, `adapters/express`, `adapters/fastify`, `adapters/hono` or `adapters/edge`. Your transport owns the development server, static assets and route-asset injection; follow [Runtime adapters](./docs/guide/runtime-adapters.md) when you need this control.
|
|
31
28
|
|
|
32
|
-
##
|
|
29
|
+
## Not a fit when
|
|
30
|
+
|
|
31
|
+
- You need an implementation of React Server Components and Server Actions.
|
|
32
|
+
- You want the package to impose file-system routing conventions.
|
|
33
|
+
- You want zero server ownership for SSR.
|
|
34
|
+
|
|
35
|
+
## Install and template quick start
|
|
33
36
|
|
|
34
37
|
```bash
|
|
35
38
|
npm i @lomray/vite-ssr-boost
|
|
36
39
|
```
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
Start with the [React template](https://github.com/Lomray-Software/vite-template):
|
|
41
|
+
The package declares `engines.node: ">=22.12.0"`. The example uses Node 22.23.2; React Router and build tools can raise the required Node version.
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
git clone https://github.com/Lomray-Software/vite-template.git
|
|
43
|
-
cd vite-template
|
|
44
|
-
npm ci
|
|
45
|
-
npm run develop
|
|
46
|
-
```
|
|
43
|
+
Start with the [minimal template](https://github.com/Lomray-Software/vite-template/tree/example/minimal): run `git clone --branch example/minimal https://github.com/Lomray-Software/vite-template.git`, then `cd vite-template`, `npm ci` and `npm run develop`. Its six direct runtime dependencies are React, React DOM, React Router, vite-ssr-boost, `@lomray/react-head-manager` and `isbot`.
|
|
47
44
|
|
|
48
|
-
For production, run `npm run build` and `npm run start:ssr`. For a
|
|
49
|
-
|
|
45
|
+
For production, run `npm run build` and `npm run start:ssr`. For a SPA build, run `npm run build:spa` and `npm run start:spa`. See [Example projects](./docs/examples/index.md) for the `prod` template with state management and deployment workflows.
|
|
46
|
+
|
|
47
|
+
Already running this in production? Point our [free performance audit](https://audit.lomray.com/?utm_source=github&utm_medium=readme-vite-ssr-boost&utm_campaign=owned-surface-github) at the URL. It reports Core Web Vitals, JavaScript bundle weight and whether the HTML really arrives server-rendered. No signup.
|
|
50
48
|
|
|
51
49
|
## Documentation
|
|
52
50
|
|
|
53
|
-
|
|
51
|
+
Read the [documentation site](https://lomray-software.github.io/vite-ssr-boost/), the [comparison guide](./docs/guide/choosing.md) and the [FAQ](./docs/reference/faq.md).
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
<p align="center">
|
|
54
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=reliability_rating" alt="reliability">
|
|
55
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=security_rating" alt="Security Rating">
|
|
56
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=sqale_rating" alt="Maintainability Rating">
|
|
57
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=vulnerabilities" alt="Vulnerabilities">
|
|
58
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=bugs" alt="Bugs">
|
|
59
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=ncloc" alt="Lines of Code">
|
|
60
|
+
<img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=coverage" alt="code coverage">
|
|
61
|
+
<img src="https://img.shields.io/npm/v/@lomray/vite-ssr-boost?label=semantic%20release&logo=semantic-release" alt="semantic version">
|
|
62
|
+
</p>
|
|
58
63
|
|
|
59
64
|
## License
|
|
60
65
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ICreateHandlerOptions, IHtmlShell } from '../core/handler.js';
|
|
2
|
+
interface ILoadHtmlShellOptions {
|
|
3
|
+
indexFile: string;
|
|
4
|
+
outlet?: string;
|
|
5
|
+
}
|
|
6
|
+
interface IRouteAssetPreparerOptions {
|
|
7
|
+
buildDir: string;
|
|
8
|
+
modulePreload?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Read a built document once and supply a fresh shell for each request.
|
|
12
|
+
*/
|
|
13
|
+
declare const loadHtmlShell: ({ indexFile, outlet, }: ILoadHtmlShellOptions) => Promise<() => IHtmlShell>;
|
|
14
|
+
/**
|
|
15
|
+
* Inject matched route assets using a manifest cache owned by this preparer.
|
|
16
|
+
*/
|
|
17
|
+
declare const createRouteAssetPreparer: <TAppProps = Record<string, any>>({ buildDir, modulePreload, }: IRouteAssetPreparerOptions) => NonNullable<ICreateHandlerOptions<TAppProps>["prepare"]>;
|
|
18
|
+
export { createRouteAssetPreparer, loadHtmlShell };
|
|
19
|
+
export type { IHtmlShell, ILoadHtmlShellOptions, IRouteAssetPreparerOptions };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{readFile as t}from"node:fs/promises";import e from"../services/route-assets.js";const o=async({indexFile:e,outlet:o="\x3c!--ssr-outlet--\x3e"})=>{const n=(await t(e,"utf8")).split(o);if(!o||2!==n.length)throw new Error(`Invalid HTML shell in "${e}": expected exactly one non-empty outlet ${JSON.stringify(o)}.`);const[s,r]=n;return()=>({header:s,footer:r})},n=({buildDir:t,modulePreload:o=!1})=>{const n=new e(t,o);return async({context:t,executionContext:e})=>{const o=n.injectAssets(t);o.has("Link")&&await(e?.onEarlyHints?.(o))}};export{n as createRouteAssetPreparer,o as loadHtmlShell};
|
|
2
|
+
//# sourceMappingURL=production.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"production.js","sources":["../../src/node/production.ts"],"sourcesContent":[null],"names":["loadHtmlShell","async","indexFile","outlet","parts","readFile","split","length","Error","JSON","stringify","header","footer","createRouteAssetPreparer","buildDir","modulePreload","assets","RouteAssets","context","executionContext","hints","injectAssets","has","onEarlyHints"],"mappings":"uFAiBA,MAAMA,EAAgBC,OACpBC,YACAC,SAAS,8BAET,MACMC,SADaC,EAASH,EAAW,SACpBI,MAAMH,GAEzB,IAAKA,GAA2B,IAAjBC,EAAMG,OACnB,MAAM,IAAIC,MACR,0BAA0BN,6CAAqDO,KAAKC,UAAUP,OAIlG,MAAOQ,EAAQC,GAAUR,EAEzB,MAAO,KAAA,CAASO,SAAQC,YAMpBC,EAA2B,EAC/BC,WACAC,iBAAgB,MAEhB,MAAMC,EAAS,IAAIC,EAAYH,EAAUC,GAEzC,OAAOd,OAASiB,UAASC,uBACvB,MAAMC,EAAQJ,EAAOK,aAAaH,GAE9BE,EAAME,IAAI,eACNH,GAAkBI,eAAeH"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lomray/vite-ssr-boost",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.1.0-beta.1",
|
|
4
4
|
"description": "Vite plugin for create awesome SSR or SPA applications on React.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
|
+
"./node/production": {
|
|
8
|
+
"types": "./node/production.d.ts",
|
|
9
|
+
"default": "./node/production.js"
|
|
10
|
+
},
|
|
11
|
+
"./node/production.js": {
|
|
12
|
+
"types": "./node/production.d.ts",
|
|
13
|
+
"default": "./node/production.js"
|
|
14
|
+
},
|
|
7
15
|
"./*.js": {
|
|
8
16
|
"types": "./*.d.ts",
|
|
9
17
|
"default": "./*.js"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { RouterState, StaticHandlerContext } from 'react-router';
|
|
2
|
+
declare enum AssetType {
|
|
3
|
+
style = "style",
|
|
4
|
+
script = "script",
|
|
5
|
+
image = "image",
|
|
6
|
+
font = "font"
|
|
7
|
+
}
|
|
8
|
+
interface IAsset {
|
|
9
|
+
type: AssetType;
|
|
10
|
+
url: string;
|
|
11
|
+
weight: number;
|
|
12
|
+
isNested: boolean;
|
|
13
|
+
isPreload: boolean;
|
|
14
|
+
content?: string;
|
|
15
|
+
}
|
|
16
|
+
type TAssets = {
|
|
17
|
+
[id: string]: IAsset;
|
|
18
|
+
};
|
|
19
|
+
interface IInjectAssetsContext {
|
|
20
|
+
html: {
|
|
21
|
+
header: string;
|
|
22
|
+
};
|
|
23
|
+
routerContext?: StaticHandlerContext;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load and inject route assets with an independent cache for one build.
|
|
27
|
+
*/
|
|
28
|
+
declare class RouteAssets {
|
|
29
|
+
protected readonly outputDir: string;
|
|
30
|
+
protected readonly modulePreload: boolean;
|
|
31
|
+
protected routesAssets: Record<string, IAsset[]> | null;
|
|
32
|
+
constructor(buildDir: string, modulePreload?: boolean);
|
|
33
|
+
/**
|
|
34
|
+
* Development manifests override this to inject inline styles.
|
|
35
|
+
*/
|
|
36
|
+
protected get isDev(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get assets manifest file name.
|
|
39
|
+
*/
|
|
40
|
+
protected getAssetsManifestFile(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Load assets manifest
|
|
43
|
+
*/
|
|
44
|
+
protected loadAssetsManifest(): Record<string, IAsset[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Sort assets
|
|
47
|
+
*/
|
|
48
|
+
protected sortAssets(assets: IAsset[]): IAsset[];
|
|
49
|
+
/**
|
|
50
|
+
* Get route assets
|
|
51
|
+
*/
|
|
52
|
+
protected getAssets(routes?: RouterState['matches']): IAsset[];
|
|
53
|
+
/**
|
|
54
|
+
* Build preload hints without depending on a particular HTTP transport.
|
|
55
|
+
*/
|
|
56
|
+
getEarlyHints(assets: IAsset[]): Headers;
|
|
57
|
+
/**
|
|
58
|
+
* Inject route assets to head html
|
|
59
|
+
*/
|
|
60
|
+
injectAssets({ routerContext, html }: IInjectAssetsContext): Headers;
|
|
61
|
+
}
|
|
62
|
+
export { AssetType };
|
|
63
|
+
export type { IAsset, TAssets };
|
|
64
|
+
export default RouteAssets;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:fs";import t from"node:path";var s;!function(e){e.style="style",e.script="script",e.image="image",e.font="font"}(s||(s={}));class r{outputDir;modulePreload;routesAssets=null;constructor(e,s=!1){this.outputDir=t.resolve(e),this.modulePreload=s}get isDev(){return!1}getAssetsManifestFile(){return t.join(this.outputDir,"server","assets-manifest.json")}loadAssetsManifest(){if(null!==this.routesAssets)return this.routesAssets;const t=this.getAssetsManifestFile();return e.existsSync(t)?(this.routesAssets=JSON.parse(e.readFileSync(t,{encoding:"utf-8"})),this.routesAssets):{}}sortAssets(e){return e.sort((e,t)=>e.weight===t.weight?Number(e.isNested)-Number(t.isNested):e.weight-t.weight)}getAssets(e){const t=e?.map(({route:e})=>e.id).filter(Boolean)??[];if(!t.length)return[];const s=this.loadAssetsManifest();return this.sortAssets(t.map(e=>s[e]).flat().filter(Boolean))}getEarlyHints(e){const t=new Headers;return e.forEach(({type:e,url:s})=>{e&&["style","script"].includes(e)&&t.append("Link",`<${s}>; rel=preload; as=${e}`)}),t}injectAssets({routerContext:e,html:t}){const r=this.getAssets(e?.matches),i=r.map(({type:e,url:t,isPreload:r,content:i=""})=>{switch(e){case s.style:return this.isDev?`<style data-vite-dev-id="${t}">${i}</style>`:`<link rel="stylesheet" href="${t}">`;case s.script:return r?this.modulePreload?`<link rel="modulepreload" as="script" crossorigin href="${t}">`:null:`<script async type="module" crossorigin src="${t}"><\/script>`}return null}).filter(Boolean);return t.header=t.header.replace("</head>",`${i.join("\n")}</head>`),this.getEarlyHints(r)}}export{s as AssetType,r as default};
|
|
2
|
+
//# sourceMappingURL=route-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-assets.js","sources":["../../src/services/route-assets.ts"],"sourcesContent":[null],"names":["AssetType","RouteAssets","outputDir","modulePreload","routesAssets","constructor","buildDir","this","path","resolve","isDev","getAssetsManifestFile","join","loadAssetsManifest","manifestFile","fs","existsSync","JSON","parse","readFileSync","encoding","sortAssets","assets","sort","a","b","weight","Number","isNested","getAssets","routes","routeIds","map","route","id","filter","Boolean","length","routeId","flat","getEarlyHints","headers","Headers","forEach","type","url","includes","append","injectAssets","routerContext","html","matches","htmlAssets","isPreload","content","style","script","header","replace"],"mappings":"gDAIA,IAAKA,GAAL,SAAKA,GACHA,EAAA,MAAA,QACAA,EAAA,OAAA,SACAA,EAAA,MAAA,QACAA,EAAA,KAAA,MACD,CALD,CAAKA,IAAAA,EAAS,CAAA,IA4Bd,MAAMC,EACeC,UAEAC,cAETC,aAAgD,KAE1D,WAAAC,CAAYC,EAAkBH,GAAgB,GAC5CI,KAAKL,UAAYM,EAAKC,QAAQH,GAC9BC,KAAKJ,cAAgBA,CACvB,CAKA,SAAcO,GACZ,OAAO,CACT,CAKU,qBAAAC,GACR,OAAOH,EAAKI,KAAKL,KAAKL,UAAW,SAAU,uBAC7C,CAKU,kBAAAW,GACR,GAA0B,OAAtBN,KAAKH,aACP,OAAOG,KAAKH,aAGd,MAAMU,EAAeP,KAAKI,wBAE1B,OAAKI,EAAGC,WAAWF,IAInBP,KAAKH,aAAea,KAAKC,MAAMH,EAAGI,aAAaL,EAAc,CAAEM,SAAU,WAKlEb,KAAKH,cARH,CAAA,CASX,CAKU,UAAAiB,CAAWC,GACnB,OAAOA,EAAOC,KAAK,CAACC,EAAGC,IACrBD,EAAEE,SAAWD,EAAEC,OAASC,OAAOH,EAAEI,UAAYD,OAAOF,EAAEG,UAAYJ,EAAEE,OAASD,EAAEC,OAEnF,CAKU,SAAAG,CAAUC,GAClB,MAAMC,EAAWD,GAAQE,IAAI,EAAGC,WAAYA,EAAMC,IAAIC,OAAOC,UAAY,GAEzE,IAAKL,EAASM,OACZ,MAAO,GAGT,MAAMjC,EAAeG,KAAKM,qBAE1B,OAAON,KAAKc,WACVU,EACGC,IAAKM,GAAYlC,EAAakC,IAC9BC,OACAJ,OAAOC,SAEd,CAKO,aAAAI,CAAclB,GACnB,MAAMmB,EAAU,IAAIC,QAUpB,OARApB,EAAOqB,QAAQ,EAAGC,OAAMC,UACjBD,GAAS,CAAC,QAAS,UAAUE,SAASF,IAI3CH,EAAQM,OAAO,OAAQ,IAAIF,uBAAyBD,OAG/CH,CACT,CAKO,YAAAO,EAAaC,cAAEA,EAAaC,KAAEA,IACnC,MAAM5B,EAASf,KAAKsB,UAAUoB,GAAeE,SACvCC,EAAa9B,EAChBU,IAAI,EAAGY,OAAMC,MAAKQ,YAAWC,UAAU,OACtC,OAAQV,GACN,KAAK5C,EAAUuD,MACb,OAAOhD,KAAKG,MACR,4BAA4BmC,MAAQS,YACpC,gCAAgCT,MAEtC,KAAK7C,EAAUwD,OACb,OAAOH,EACH9C,KAAKJ,cAEH,2DAA2D0C,MAC3D,KACF,gDAAgDA,gBAGxD,OAAO,OAERV,OAAOC,SAIV,OAFAc,EAAKO,OAASP,EAAKO,OAAOC,QAAQ,UAAW,GAAGN,EAAWxC,KAAK,gBAEzDL,KAAKiC,cAAclB,EAC5B"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type { RouterState
|
|
1
|
+
import type { RouterState } from 'react-router';
|
|
2
2
|
import type { Alias, ModuleNode, RenderBuiltAssetUrl } from 'vite';
|
|
3
3
|
import type { TRoutesTree } from './parse-routes.js';
|
|
4
4
|
import PathNormalize from './path-normalize.js';
|
|
5
|
+
import type { IAsset, TAssets } from './route-assets.js';
|
|
6
|
+
import RouteAssets, { AssetType } from './route-assets.js';
|
|
5
7
|
import type ServerConfig from './server-config.js';
|
|
6
8
|
interface ISsrManifestParams {
|
|
7
9
|
buildDir?: string;
|
|
@@ -18,33 +20,10 @@ interface IManifest {
|
|
|
18
20
|
imports: string[];
|
|
19
21
|
};
|
|
20
22
|
}
|
|
21
|
-
declare enum AssetType {
|
|
22
|
-
style = "style",
|
|
23
|
-
script = "script",
|
|
24
|
-
image = "image",
|
|
25
|
-
font = "font"
|
|
26
|
-
}
|
|
27
|
-
interface IAsset {
|
|
28
|
-
type: AssetType;
|
|
29
|
-
url: string;
|
|
30
|
-
weight: number;
|
|
31
|
-
isNested: boolean;
|
|
32
|
-
isPreload: boolean;
|
|
33
|
-
content?: string;
|
|
34
|
-
}
|
|
35
|
-
type TAssets = {
|
|
36
|
-
[id: string]: IAsset;
|
|
37
|
-
};
|
|
38
|
-
interface IInjectAssetsContext {
|
|
39
|
-
html: {
|
|
40
|
-
header: string;
|
|
41
|
-
};
|
|
42
|
-
routerContext?: StaticHandlerContext;
|
|
43
|
-
}
|
|
44
23
|
/**
|
|
45
24
|
* Working with SSR Manifest file
|
|
46
25
|
*/
|
|
47
|
-
declare class SsrManifest {
|
|
26
|
+
declare class SsrManifest extends RouteAssets {
|
|
48
27
|
/**
|
|
49
28
|
* Singleton
|
|
50
29
|
*/
|
|
@@ -69,10 +48,6 @@ declare class SsrManifest {
|
|
|
69
48
|
* Client manifest file name
|
|
70
49
|
*/
|
|
71
50
|
protected readonly manifestName = "manifest.json";
|
|
72
|
-
/**
|
|
73
|
-
* Assets manifest file name
|
|
74
|
-
*/
|
|
75
|
-
protected readonly assetsManifest = "assets-manifest.json";
|
|
76
51
|
/**
|
|
77
52
|
* Vite resolve aliases
|
|
78
53
|
*/
|
|
@@ -85,10 +60,6 @@ declare class SsrManifest {
|
|
|
85
60
|
* Vite renderBuiltUrl config func
|
|
86
61
|
*/
|
|
87
62
|
protected readonly renderBuiltUrl?: RenderBuiltAssetUrl;
|
|
88
|
-
/**
|
|
89
|
-
* Loaded assets manifest file
|
|
90
|
-
*/
|
|
91
|
-
protected routesAssets: Record<string, IAsset[]> | null;
|
|
92
63
|
/**
|
|
93
64
|
* @constructor
|
|
94
65
|
*/
|
|
@@ -98,29 +69,25 @@ declare class SsrManifest {
|
|
|
98
69
|
*/
|
|
99
70
|
static get(config: ServerConfig, params?: ISsrManifestParams): SsrManifest;
|
|
100
71
|
/**
|
|
101
|
-
*
|
|
72
|
+
* Use inline styles while the managed Vite server is running.
|
|
73
|
+
*/
|
|
74
|
+
protected get isDev(): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Get output dir.
|
|
102
77
|
*/
|
|
103
78
|
protected getOutDir(): string;
|
|
104
79
|
/**
|
|
105
|
-
*
|
|
80
|
+
* Keep the managed server's build path resolution.
|
|
106
81
|
*/
|
|
107
82
|
protected getAssetsManifestFile(): string;
|
|
108
83
|
/**
|
|
109
84
|
* Load client ssr manifest
|
|
110
85
|
*/
|
|
111
86
|
protected loadClientManifest(): IManifest;
|
|
112
|
-
/**
|
|
113
|
-
* Load assets manifest
|
|
114
|
-
*/
|
|
115
|
-
protected loadAssetsManifest(): Record<string, IAsset[]>;
|
|
116
87
|
/**
|
|
117
88
|
* Same as 'getAsyncRoutesIds' but for routes tree from 'ParseRoutes'
|
|
118
89
|
*/
|
|
119
90
|
protected getRoutesTreeIds(routes: TRoutesTree[], index?: string): Record<string, string | undefined>;
|
|
120
|
-
/**
|
|
121
|
-
* Sort assets
|
|
122
|
-
*/
|
|
123
|
-
protected sortAssets(assets: IAsset[]): IAsset[];
|
|
124
91
|
/**
|
|
125
92
|
* Get recursive module assets
|
|
126
93
|
*/
|
|
@@ -130,7 +97,7 @@ declare class SsrManifest {
|
|
|
130
97
|
*/
|
|
131
98
|
buildRoutesManifest(): void;
|
|
132
99
|
/**
|
|
133
|
-
* Get route assets
|
|
100
|
+
* Get route assets from Vite in development or the built manifest in production.
|
|
134
101
|
*/
|
|
135
102
|
protected getAssets(routes?: RouterState['matches']): IAsset[];
|
|
136
103
|
/**
|
|
@@ -157,13 +124,5 @@ declare class SsrManifest {
|
|
|
157
124
|
* Get asset type
|
|
158
125
|
*/
|
|
159
126
|
protected getAssetType(asset: string): AssetType | null;
|
|
160
|
-
/**
|
|
161
|
-
* Build preload hints without depending on a particular HTTP transport.
|
|
162
|
-
*/
|
|
163
|
-
getEarlyHints(assets: IAsset[]): Headers;
|
|
164
|
-
/**
|
|
165
|
-
* Inject route assets to head html
|
|
166
|
-
*/
|
|
167
|
-
injectAssets({ routerContext, html }: IInjectAssetsContext): Headers;
|
|
168
127
|
}
|
|
169
128
|
export default SsrManifest;
|
package/services/ssr-manifest.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"node:fs";import s from"node:path";import t from"chalk";import i from"./parse-routes.js";import r from"./path-normalize.js";
|
|
1
|
+
import e from"node:fs";import s from"node:path";import t from"chalk";import i from"./parse-routes.js";import r from"./path-normalize.js";import o,{AssetType as a}from"./route-assets.js";class n extends o{static instance=null;config;pathNormalize;root;buildDir;manifestName="manifest.json";viteAliases;basename;renderBuiltUrl;constructor(e,{buildDir:t,viteAliases:i,basename:o,renderBuiltUrl:a}={}){super(s.resolve(e.getParams().root,t||""),e.isModulePreload),this.config=e,this.root=e.getParams().root,this.buildDir=t,this.viteAliases=i??e.getVite()?.config?.resolve.alias,this.pathNormalize=new r(e,i),this.basename=o,this.renderBuiltUrl=a}static get(e,s={}){return null===n.instance&&(n.instance=new n(e,s)),n.instance}get isDev(){return Boolean(this.config.getVite())}getOutDir(){return s.resolve(this.root,this.buildDir||"")}getAssetsManifestFile(){return`${this.getOutDir()}/server/assets-manifest.json`}loadClientManifest(){const t=s.resolve(this.root,`${this.buildDir||""}/client/.vite`),i=`${t}/${this.manifestName}`;if(!e.existsSync(i))return{};const r=JSON.parse(e.readFileSync(i,{encoding:"utf-8"}));return e.rmSync(i),0===e.readdirSync(t).length&&e.rmSync(t,{recursive:!0}),r}getRoutesTreeIds(e,s){const t={};return e.forEach((e,i)=>{const r=[s,String(i)].filter(Boolean).join("-");e.import&&(t[r]=this.pathNormalize.getAppPath(e.import)),e.children.length>0&&Object.assign(t,this.getRoutesTreeIds(e.children,r))}),t}getRouteAssets(e,t,i=!1){const r=[...t?.assets??[],...t?.css??[],t?.file].reduce((e,r)=>{if(r){const o=this.getAssetType(r),a=t.isEntry&&t.file===r;if(o){const t=s.posix.normalize(`${this.basename}/${r}`),n=this.renderBuiltUrl?.(t,{type:"asset",ssr:!0,hostId:"",hostType:t.split(".").at(-1)?.toLowerCase()});e[r]={url:"string"==typeof n?n:t,weight:a?1.9:this.getAssetWeight(r),type:o,isNested:i,isPreload:!a}}}return e},{});return t?.imports?.length&&t.imports.forEach(s=>{const t=e[s];t&&Object.assign(r,this.getRouteAssets(e,t,!0))}),r}buildRoutesManifest(){const s=this.loadClientManifest(),t=new i(this.config,this.viteAliases),r=this.getRoutesTreeIds(t.parse()),o=this.pathNormalize.getImportPostfix(),a={};Object.entries(r).forEach(([e,t])=>{const i=o.find(e=>void 0!==s[`${t}${e}`]),r=s[`${t}${i||""}`];a[e]=this.sortAssets(Object.values(this.getRouteAssets(s,r)))}),e.writeFileSync(this.getAssetsManifestFile(),JSON.stringify(a,null,2),{encoding:"utf-8"})}getAssets(e){return this.isDev?this.getAssetsDev(e):super.getAssets(e)}getDevModules(e){const t=e?.map(({route:e})=>this.pathNormalize.getAppPath(e?.pathId,!0)).filter(Boolean)??[],i=this.pathNormalize.getImportPostfix(),r=this.config.getPluginConfig(),o=[r?.clientFile??"client.ts",r?.serverFile??"server.ts"].map(e=>s.resolve(this.root,e)),a=[];return[...o,...t].forEach(e=>{for(const s of i){const t=this.config.getVite()?.moduleGraph.getModuleById(`${e}${s}`);if(t){a.push(t);break}}}),a}async prepareDevAssets(e){const s=this.config.getVite();if(!s)return;const t=new Set,i=async e=>{t.has(e.url)||(t.add(e.url),e.file&&/\.(?:css|less|s[ac]ss|styl(?:us)?|pcss|postcss)$/.test(e.file)&&await s.transformRequest(e.url),await Promise.all([...e.importedModules].map(i)))};await Promise.all(this.getDevModules(e).map(i))}getAssetsDev(e){const s=Object.assign({},...this.getDevModules(e).map(e=>this.getModuleAssets(e)));return Object.values(s)}getModuleAssets(e,s=new Set){const i=e?.importedModules??e?.clientImportedModules;if(!i?.size||s.has(e.file))return{};let r={};return s.add(e.file),i.forEach(e=>{const{file:i,transformResult:o}=e,n=i?.split(".").at(-1);if(i&&n&&["css","scss","sass","less","styl","stylus","pcss","postcss"].includes(n)){const e=o?.code.match(/__vite__css\s+=\s+"(?<css>.+)"/)?.groups?.css;if(e)try{r[i]={type:a.style,url:i,weight:this.getAssetWeight(i),content:JSON.parse(`{"style": "${e}"}`).style,isNested:Boolean(s.size),isPreload:!1}}catch{console.warn(t.yellowBright("Failed to parse style: ",i))}}else r={...r,...this.getModuleAssets(e,s)}}),r}getAssetWeight(e){switch(this.getAssetType(e)){case a.style:return 1;case a.script:return 2;default:return 3}}getAssetType(e){const s=e.split(".").at(-1)?.toLowerCase();switch(s){case"css":case"scss":return a.style;case"js":return a.script;case"svg":case"jpg":case"jpeg":case"png":case"webp":case"gif":case"ico":return a.image;case"ttf":case"otf":case"woff":case"woff2":return a.font;default:return null}}}export{n 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":[null],"names":["
|
|
1
|
+
{"version":3,"file":"ssr-manifest.js","sources":["../../src/services/ssr-manifest.ts"],"sourcesContent":[null],"names":["SsrManifest","RouteAssets","static","config","pathNormalize","root","buildDir","manifestName","viteAliases","basename","renderBuiltUrl","constructor","super","path","resolve","getParams","isModulePreload","this","getVite","alias","PathNormalize","get","params","instance","isDev","Boolean","getOutDir","getAssetsManifestFile","loadClientManifest","clientManifestDir","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","readdirSync","length","recursive","getRoutesTreeIds","routes","index","forEach","route","routeIndex","routeId","String","filter","join","import","getAppPath","children","Object","assign","getRouteAssets","manifest","module","isNested","assets","css","file","reduce","res","asset","type","getAssetType","isEntry","filename","posix","normalize","modifiedFilename","ssr","hostId","hostType","split","at","toLowerCase","url","weight","getAssetWeight","isPreload","imports","nestedAsset","nestedModule","buildRoutesManifest","routesService","ParseRoutes","routesPaths","postfixes","getImportPostfix","entries","routePath","routePostfix","find","postfix","undefined","routeMeta","sortAssets","values","writeFileSync","stringify","getAssets","getAssetsDev","getDevModules","routeIds","map","pathId","pluginConfig","getPluginConfig","rootIds","clientFile","serverFile","modules","moduleId","ext","moduleGraph","getModuleById","push","prepareDevAssets","vite","visited","Set","visit","async","has","add","test","transformRequest","Promise","all","importedModules","getModuleAssets","skipModules","clientImportedModules","size","subModule","transformResult","includes","code","match","groups","AssetType","style","content","console","warn","chalk","yellowBright","script","image","font"],"mappings":"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"}
|