@gracile/engine 0.9.0-next.7 → 0.9.1-next.0
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/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +25 -16
- package/dist/render/route-template.d.ts.map +1 -1
- package/dist/render/route-template.js +27 -6
- package/dist/routes/load-module.d.ts.map +1 -1
- package/dist/routes/load-module.js +5 -2
- package/dist/routes/render.d.ts.map +1 -1
- package/dist/routes/render.js +9 -8
- package/dist/vite/build-routes.d.ts +1 -2
- package/dist/vite/build-routes.d.ts.map +1 -1
- package/dist/vite/build-routes.js +0 -98
- package/dist/vite/plugin-build-environment.d.ts +21 -0
- package/dist/vite/plugin-build-environment.d.ts.map +1 -0
- package/dist/vite/plugin-build-environment.js +83 -0
- package/dist/vite/plugin-client-build.d.ts +7 -3
- package/dist/vite/plugin-client-build.d.ts.map +1 -1
- package/dist/vite/plugin-client-build.js +10 -14
- package/dist/vite/plugin-html-routes-build.d.ts +22 -0
- package/dist/vite/plugin-html-routes-build.d.ts.map +1 -0
- package/dist/vite/plugin-html-routes-build.js +140 -0
- package/dist/vite/plugin-serve.d.ts.map +1 -1
- package/dist/vite/plugin-serve.js +1 -2
- package/dist/vite/plugin-server-build.d.ts +22 -12
- package/dist/vite/plugin-server-build.d.ts.map +1 -1
- package/dist/vite/plugin-server-build.js +22 -71
- package/dist/vite/plugin-shared-state.d.ts +2 -0
- package/dist/vite/plugin-shared-state.d.ts.map +1 -1
- package/dist/vite/plugin-shared-state.js +1 -0
- package/dist/vite/virtual-routes.d.ts +8 -5
- package/dist/vite/virtual-routes.d.ts.map +1 -1
- package/dist/vite/virtual-routes.js +32 -31
- package/package.json +5 -5
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAsBtD;;;;;;;;;;;;;;;;GAgBG;AAIH,eAAO,MAAM,OAAO,GAAI,SAAS,aAAa,KAAG,GAAG,EA2EnD,CAAC;AAEF,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -2,12 +2,18 @@ import { createLogger } from '@gracile/internal-utils/logger/helpers';
|
|
|
2
2
|
import { getPluginContext, } from '@gracile/internal-utils/plugin-context';
|
|
3
3
|
import { htmlRoutesLoader } from './vite/html-routes.js';
|
|
4
4
|
import { hmrSsrReload } from './vite/hmr.js';
|
|
5
|
-
import { virtualRoutesClient } from './vite/virtual-routes.js';
|
|
5
|
+
import { virtualRoutesClient, virtualRoutes } from './vite/virtual-routes.js';
|
|
6
6
|
import { createPluginSharedState } from './vite/plugin-shared-state.js';
|
|
7
7
|
import { gracileServePlugin } from './vite/plugin-serve.js';
|
|
8
8
|
import { gracileClientBuildPlugin } from './vite/plugin-client-build.js';
|
|
9
|
-
import {
|
|
9
|
+
import { gracileBuildEnvironmentPlugin } from './vite/plugin-build-environment.js';
|
|
10
|
+
import { gracileCollectClientAssetsPlugin, gracileEntrypointPlugin, gracileMoveServerAssetsPlugin, } from './vite/plugin-server-build.js';
|
|
10
11
|
import { gracileCETrackerPlugin } from './vite/plugin-ce-tracker.js';
|
|
12
|
+
import { gracileHtmlRoutesBuildPlugins } from './vite/plugin-html-routes-build.js';
|
|
13
|
+
// When plugin-client-build creates a temporary dev server via createServer(),
|
|
14
|
+
// the user's vite.config is re-evaluated, calling gracile() again.
|
|
15
|
+
// This guard prevents that re-entrant call from initializing the full plugin set.
|
|
16
|
+
// Reset in configureServer so dev-mode config hot-reloads still work.
|
|
11
17
|
let isClientBuilt = false;
|
|
12
18
|
/**
|
|
13
19
|
* The main Vite plugin for loading the Gracile framework.
|
|
@@ -32,8 +38,6 @@ let isClientBuilt = false;
|
|
|
32
38
|
export const gracile = (config) => {
|
|
33
39
|
const logger = createLogger();
|
|
34
40
|
const state = createPluginSharedState(config);
|
|
35
|
-
// HACK: Prevent duplicate client build for the SSR build step in server mode.
|
|
36
|
-
// TODO: Move to the new, clean, environments builders API.
|
|
37
41
|
if (isClientBuilt)
|
|
38
42
|
return [];
|
|
39
43
|
isClientBuilt = true;
|
|
@@ -54,11 +58,11 @@ export const gracile = (config) => {
|
|
|
54
58
|
sharedPluginContext.litSsrRenderInfo;
|
|
55
59
|
},
|
|
56
60
|
},
|
|
57
|
-
// MARK:
|
|
61
|
+
// MARK: 2. CE registry tracker (dev HMR cleanup)
|
|
58
62
|
gracileCETrackerPlugin(),
|
|
59
|
-
// MARK:
|
|
63
|
+
// MARK: 3. HMR SSR reload
|
|
60
64
|
hmrSsrReload(),
|
|
61
|
-
// MARK:
|
|
65
|
+
// MARK: 4. Dev serve middleware
|
|
62
66
|
gracileServePlugin({
|
|
63
67
|
state,
|
|
64
68
|
config,
|
|
@@ -67,21 +71,26 @@ export const gracile = (config) => {
|
|
|
67
71
|
isClientBuilt = false;
|
|
68
72
|
},
|
|
69
73
|
}),
|
|
70
|
-
// MARK:
|
|
74
|
+
// MARK: 5. Client virtual routes
|
|
71
75
|
virtualRoutesForClient,
|
|
72
|
-
// MARK:
|
|
76
|
+
// MARK: 6. HTML routes loader
|
|
73
77
|
htmlRoutesLoader(),
|
|
74
|
-
// MARK:
|
|
78
|
+
// MARK: 7. Client build (route rendering → populates shared state)
|
|
75
79
|
gracileClientBuildPlugin({
|
|
76
80
|
state,
|
|
77
81
|
virtualRoutesForClient,
|
|
78
82
|
}),
|
|
79
|
-
// MARK:
|
|
83
|
+
// MARK: 8. HTML route resolution + asset collection (client build only)
|
|
84
|
+
...gracileHtmlRoutesBuildPlugins({ state }),
|
|
85
|
+
// MARK: 9. Build environment configuration (consumes shared state)
|
|
86
|
+
gracileBuildEnvironmentPlugin({ state }),
|
|
87
|
+
// MARK: 9. Collect client assets for server
|
|
80
88
|
gracileCollectClientAssetsPlugin({ state }),
|
|
81
|
-
// MARK:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
// MARK: 10. Server virtual routes (SSR environment only)
|
|
90
|
+
...virtualRoutes({ state }),
|
|
91
|
+
// MARK: 11. Server entrypoint (SSR environment only)
|
|
92
|
+
gracileEntrypointPlugin({ state }),
|
|
93
|
+
// MARK: 12. Move server assets (SSR environment only)
|
|
94
|
+
gracileMoveServerAssetsPlugin({ state }),
|
|
86
95
|
];
|
|
87
96
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-template.d.ts","sourceRoot":"","sources":["../../src/render/route-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAOxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAO1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,KAAK,CAAC,MAAM,oBAAoB,CAAC;AAa7C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"route-template.d.ts","sourceRoot":"","sources":["../../src/render/route-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAOxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAO1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,KAAK,CAAC,MAAM,oBAAoB,CAAC;AAa7C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AA0BhF,wBAAsB,mBAAmB,CAAC,EACzC,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,WAAW,EACX,UAAU,EACV,OAAO,EACP,UAAU,GACV,EAAE;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,CAAC,YAAY,GAAG,SAAS,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;CAC7C,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAC;IAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;CAAE,CAAC,CAwJhE"}
|
|
@@ -2,11 +2,36 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import * as assert from '@gracile/internal-utils/assertions';
|
|
3
3
|
import { render as renderLitSsr } from '@lit-labs/ssr';
|
|
4
4
|
import { collectResult } from '@lit-labs/ssr/lib/render-result.js';
|
|
5
|
+
// Lit's purpose-built Readable subclass for RenderResult. Handles nested
|
|
6
|
+
// iterables, thunks, and Promises from sub-templates with proper back-pressure,
|
|
7
|
+
// whereas generic `Readable.from()` only sees the top-level iterable.
|
|
8
|
+
// Inherits from the same Node `Readable` we already depend on.
|
|
9
|
+
import { RenderResultReadable } from '@lit-labs/ssr/lib/render-result-readable.js';
|
|
5
10
|
import { GracileError, GracileErrorData, TemplateError, } from '../errors/errors.js';
|
|
6
11
|
import { SSR_OUTLET_MARKER } from './markers.js';
|
|
7
12
|
import { concatStreams, mergeRenderInfo, injectSiblingAssets, ensureDoctype, injectDevelopmentOverlay, injectServerAssets, } from './route-template-pipeline.js';
|
|
8
13
|
// Re-export for consumers that import these regexes from this module.
|
|
9
14
|
export { REGEX_TAG_SCRIPT, REGEX_TAG_LINK } from './route-template-pipeline.js';
|
|
15
|
+
/**
|
|
16
|
+
* Lit SSR's `RenderResultReadable._read()` is `async`, but Node.js
|
|
17
|
+
* calls `_read()` without awaiting its return value. If a thunk inside
|
|
18
|
+
* the render result throws (e.g. template expressions in invalid
|
|
19
|
+
* locations), the rejected Promise escapes and becomes an
|
|
20
|
+
* `unhandledRejection`.
|
|
21
|
+
*
|
|
22
|
+
* This subclass overrides `_read()` to catch that rejection and convert
|
|
23
|
+
* it into a stream `'error'` event via `this.destroy(err)`, which is
|
|
24
|
+
* the standard Node Readable contract.
|
|
25
|
+
*/
|
|
26
|
+
class SafeRenderResultReadable extends RenderResultReadable {
|
|
27
|
+
_read(size) {
|
|
28
|
+
const maybePromise = super._read(size);
|
|
29
|
+
void maybePromise?.catch?.((error) => {
|
|
30
|
+
this.destroy(error);
|
|
31
|
+
});
|
|
32
|
+
return maybePromise;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
10
35
|
export async function renderRouteTemplate({ url, vite, mode, routeInfos, routeAssets, serverMode, docOnly, renderInfo, }) {
|
|
11
36
|
const location = {
|
|
12
37
|
file: routeInfos.foundRoute.filePath,
|
|
@@ -31,10 +56,7 @@ export async function renderRouteTemplate({ url, vite, mode, routeInfos, routeAs
|
|
|
31
56
|
// location,
|
|
32
57
|
});
|
|
33
58
|
const fragmentRender = renderLitSsr(fragmentOutput, mergedRenderInfo);
|
|
34
|
-
const output =
|
|
35
|
-
// TODO: Disabled for now. Causes issue in static renders.
|
|
36
|
-
// Needs investigations.
|
|
37
|
-
// const output = new RenderResultReadable(fragmentRender);
|
|
59
|
+
const output = new SafeRenderResultReadable(fragmentRender);
|
|
38
60
|
return { output, document: null };
|
|
39
61
|
}
|
|
40
62
|
// MARK: Document
|
|
@@ -90,8 +112,7 @@ export async function renderRouteTemplate({ url, vite, mode, routeInfos, routeAs
|
|
|
90
112
|
const routeOutput = await Promise.resolve(routeInfos.routeModule.template(context));
|
|
91
113
|
if (assert.isLitTemplate(routeOutput) === false)
|
|
92
114
|
throw new Error(`Wrong template result for page template ${routeInfos.foundRoute.filePath}.`);
|
|
93
|
-
const renderStream =
|
|
94
|
-
/* TODO: Use `new RenderResultReadable` */ Readable.from(renderLitSsr(routeOutput, mergedRenderInfo));
|
|
115
|
+
const renderStream = new SafeRenderResultReadable(renderLitSsr(routeOutput, mergedRenderInfo));
|
|
95
116
|
const output = Readable.from(concatStreams(baseDocumentRenderStreamPre, renderStream, baseDocumentRenderStreamPost));
|
|
96
117
|
return { output, document: baseDocumentHtml };
|
|
97
118
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-module.d.ts","sourceRoot":"","sources":["../../src/routes/load-module.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"load-module.d.ts","sourceRoot":"","sources":["../../src/routes/load-module.ts"],"names":[],"mappings":"AAKA,OAAO,EAA4B,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAIpE,OAAO,KAAK,CAAC,MAAM,YAAY,CAAC;AAGhC,eAAO,MAAM,OAAO;;;;;;CASnB,CAAC;AAQF,wBAAsB,sBAAsB,CAAC,EAC5C,IAAI,EACJ,KAAK,EACL,YAAY,GACZ,EAAE;IACF,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,CAAC,aAAa,GAAG,SAAS,CAAC;CAC3C,0BAgDA"}
|
|
@@ -2,7 +2,7 @@ import { join } from 'node:path';
|
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
3
|
import { collectErrorMetadata } from '@gracile-labs/better-errors/dev/utils';
|
|
4
4
|
import { enhanceViteSSRError } from '@gracile-labs/better-errors/dev/vite';
|
|
5
|
-
import {} from 'vite';
|
|
5
|
+
import { isRunnableDevEnvironment } from 'vite';
|
|
6
6
|
import { GracileError, GracileErrorData } from '../errors/errors.js';
|
|
7
7
|
import * as R from './route.js';
|
|
8
8
|
// const ROUTE_SPREAD = /^\.{3}.+$/;
|
|
@@ -24,7 +24,10 @@ export async function loadForeignRouteObject({ vite, route, routeImports, }) {
|
|
|
24
24
|
let unknownRouteModule;
|
|
25
25
|
if (vite) {
|
|
26
26
|
try {
|
|
27
|
-
|
|
27
|
+
const ssrEnvironment = vite.environments.ssr;
|
|
28
|
+
if (!isRunnableDevEnvironment(ssrEnvironment))
|
|
29
|
+
throw new Error('Not in a SSR path');
|
|
30
|
+
unknownRouteModule = await ssrEnvironment.runner.import(route.filePath);
|
|
28
31
|
}
|
|
29
32
|
catch (error) {
|
|
30
33
|
const error_ = error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/routes/render.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,MAAM,EAAE;QACP,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;IAEF,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/routes/render.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,MAAM,EAAE;QACP,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;IAEF,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAsBD,wBAAsB,YAAY,CAAC,EAClC,MAAM,EACN,IAAI,EACJ,UAAU,EACV,IAAoB,EACpB,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;CAC7B;;;GAwKA"}
|
package/dist/routes/render.js
CHANGED
|
@@ -8,18 +8,19 @@ import { loadForeignRouteObject } from './load-module.js';
|
|
|
8
8
|
async function streamToString(stream) {
|
|
9
9
|
const chunks = [];
|
|
10
10
|
for await (const chunk of stream) {
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// `RenderResultReadable` always pushes strings (it resolves promises,
|
|
12
|
+
// thunks, and nested iterables internally). `Readable.from(string)`
|
|
13
|
+
// used for the document-only path also yields strings.
|
|
14
|
+
// Accept Buffer too for safety (plain `Readable` streams may emit them).
|
|
14
15
|
if (typeof chunk === 'string') {
|
|
15
16
|
chunks.push(Buffer.from(chunk));
|
|
16
17
|
}
|
|
17
|
-
else
|
|
18
|
-
throw new TypeError('Wrong buffer type from stream. Should be a `string` only.');
|
|
19
|
-
// NOTE: Disabled for now. Causes issues with `RenderResultReadable`.
|
|
20
|
-
/* else {
|
|
18
|
+
else if (Buffer.isBuffer(chunk)) {
|
|
21
19
|
chunks.push(chunk);
|
|
22
|
-
}
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
throw new TypeError(`Unexpected chunk type in stream: ${typeof chunk}`);
|
|
23
|
+
}
|
|
23
24
|
}
|
|
24
25
|
return Buffer.concat(chunks).toString('utf8');
|
|
25
26
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ViteDevServer } from 'vite';
|
|
2
2
|
import { type RenderedRouteDefinition } from '../routes/render.js';
|
|
3
3
|
import type { RoutesManifest } from '../routes/route.js';
|
|
4
4
|
import type { GracileConfig } from '../user-config.js';
|
|
@@ -12,6 +12,5 @@ export declare const buildRoutes: ({ routes, viteServerForBuild, root, gracileCo
|
|
|
12
12
|
routes: RoutesManifest;
|
|
13
13
|
renderedRoutes: RenderedRouteDefinition[];
|
|
14
14
|
inputList: string[];
|
|
15
|
-
plugin: Plugin[];
|
|
16
15
|
}>;
|
|
17
16
|
//# sourceMappingURL=build-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-routes.d.ts","sourceRoot":"","sources":["../../src/vite/build-routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build-routes.d.ts","sourceRoot":"","sources":["../../src/vite/build-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAExD,OAAO,EAEN,KAAK,uBAAuB,EAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AASvD,eAAO,MAAM,WAAW,GAAU,kEAM/B;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,kBAAkB,EAAE,aAAa,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,KAAG,OAAO,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,uBAAuB,EAAE,CAAC;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAC;CACpB,CAkCA,CAAC"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { basename, extname, join } from 'node:path';
|
|
2
1
|
import { createFilter } from 'vite';
|
|
3
2
|
import { renderRoutes, } from '../routes/render.js';
|
|
4
|
-
import { REGEX_TAG_LINK, REGEX_TAG_SCRIPT } from '../render/route-template.js';
|
|
5
3
|
function stripPremises(input) {
|
|
6
4
|
return input
|
|
7
5
|
.replace(/index\.html$/, '__index.doc.html')
|
|
@@ -9,7 +7,6 @@ function stripPremises(input) {
|
|
|
9
7
|
.replace(/500\.html$/, '__500.doc.html');
|
|
10
8
|
}
|
|
11
9
|
export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileConfig, serverMode = false, }) => {
|
|
12
|
-
// TODO: extract upstream, return just the plugins
|
|
13
10
|
const { renderedRoutes } = await renderRoutes({
|
|
14
11
|
vite: viteServerForBuild,
|
|
15
12
|
serverMode,
|
|
@@ -35,100 +32,5 @@ export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileCon
|
|
|
35
32
|
routes,
|
|
36
33
|
renderedRoutes,
|
|
37
34
|
inputList,
|
|
38
|
-
plugin: [
|
|
39
|
-
{
|
|
40
|
-
name: 'gracile-html-routes',
|
|
41
|
-
apply: 'build',
|
|
42
|
-
enforce: 'pre',
|
|
43
|
-
resolveId(id) {
|
|
44
|
-
if (extname(id) === '.html' && inputList.includes(id))
|
|
45
|
-
return join(root, id);
|
|
46
|
-
return null;
|
|
47
|
-
},
|
|
48
|
-
load(id) {
|
|
49
|
-
if (extname(id) === '.html') {
|
|
50
|
-
if (['index.html', '404.html', '500.html'].includes(basename(id))) {
|
|
51
|
-
const content = renderedRoutes.find((index) => index.absoluteId === id)?.html;
|
|
52
|
-
if (content)
|
|
53
|
-
return content;
|
|
54
|
-
}
|
|
55
|
-
if (gracileConfig.pages?.premises?.expose) {
|
|
56
|
-
if (basename(id).endsWith('doc.html')) {
|
|
57
|
-
const content = renderedRoutes.find((index) => stripPremises(index.absoluteId) === id)?.static.document;
|
|
58
|
-
if (content)
|
|
59
|
-
return content;
|
|
60
|
-
}
|
|
61
|
-
const content = renderedRoutes.find((index) => index.name === basename(id))?.html;
|
|
62
|
-
if (content)
|
|
63
|
-
return content;
|
|
64
|
-
// return '';}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'gracile-collect-handler-assets',
|
|
72
|
-
enforce: 'post',
|
|
73
|
-
buildStart() {
|
|
74
|
-
if (!gracileConfig.pages?.premises?.expose || !premisesFilter)
|
|
75
|
-
return;
|
|
76
|
-
for (const route of renderedRoutes) {
|
|
77
|
-
if (premisesFilter(route.name) === false)
|
|
78
|
-
continue;
|
|
79
|
-
if (serverMode && route.savePrerender !== true)
|
|
80
|
-
continue;
|
|
81
|
-
const fileNameParts = route.name.split('/');
|
|
82
|
-
const last = fileNameParts.pop();
|
|
83
|
-
const properties = last?.replace(/(.*)\.html$/, (_, r) => `__${r}.props.json`);
|
|
84
|
-
if (!properties)
|
|
85
|
-
throw new Error('No props.');
|
|
86
|
-
fileNameParts.push(properties);
|
|
87
|
-
const fileName = fileNameParts.join('/');
|
|
88
|
-
this.emitFile({
|
|
89
|
-
fileName,
|
|
90
|
-
type: 'asset',
|
|
91
|
-
source: JSON.stringify(route.static.props ?? {}),
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
generateBundle(_, bundle) {
|
|
96
|
-
if (serverMode === false)
|
|
97
|
-
return;
|
|
98
|
-
for (const fileKey in bundle) {
|
|
99
|
-
const file = bundle[fileKey];
|
|
100
|
-
if (fileKey.endsWith('.html') && file && 'source' in file) {
|
|
101
|
-
const source = file.source.toString();
|
|
102
|
-
const collectedAssets = [
|
|
103
|
-
...[...source.matchAll(REGEX_TAG_SCRIPT)]
|
|
104
|
-
.map((v) => v[0])
|
|
105
|
-
// NOTE: Too brittle
|
|
106
|
-
.filter((v) => v.includes(`type="module"`)),
|
|
107
|
-
...[...source.matchAll(REGEX_TAG_LINK)]
|
|
108
|
-
.map((v) => v[0])
|
|
109
|
-
// NOTE: Too brittle
|
|
110
|
-
.filter((v) => /rel="(stylesheet|modulepreload)"/.test(v)),
|
|
111
|
-
].join('\n');
|
|
112
|
-
// NOTE: Not used (for now?)
|
|
113
|
-
// file.source = alteredContent;
|
|
114
|
-
const route = renderedRoutes.find((r) => {
|
|
115
|
-
if (gracileConfig.pages?.premises?.expose)
|
|
116
|
-
return (`/${r.name}` ===
|
|
117
|
-
`/${fileKey}`.replace(/(.*?)\/__(.*?)\.doc\.html$/, (a, b, c) => `${b}/${c}.html`));
|
|
118
|
-
return r.name === fileKey;
|
|
119
|
-
});
|
|
120
|
-
if (route)
|
|
121
|
-
route.handlerAssets = collectedAssets;
|
|
122
|
-
if (route?.savePrerender !== true) {
|
|
123
|
-
delete bundle[fileKey];
|
|
124
|
-
// NOTE: Not sure if it's useful
|
|
125
|
-
if (route?.html)
|
|
126
|
-
route.html = null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
35
|
};
|
|
134
36
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: build environment configuration.
|
|
3
|
+
*
|
|
4
|
+
* Owns all Environment API concerns for builds:
|
|
5
|
+
* - Top-level config: `builder.sharedConfigBuild`, `ssr.external` (server mode)
|
|
6
|
+
* - `configEnvironment('client')`: rollupOptions.input, outDir
|
|
7
|
+
* - `configEnvironment('ssr')`: outDir, SSR-specific build options, rollupOptions
|
|
8
|
+
* - `buildApp()`: orchestrates build order (client-only or client → SSR)
|
|
9
|
+
*
|
|
10
|
+
* `rollupOptions.input` must be set via `configEnvironment` (not the
|
|
11
|
+
* top-level `config` hook) because `builder.build(env)` uses
|
|
12
|
+
* environment-resolved config, not the top-level config.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
import type { PluginOption } from 'vite';
|
|
17
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
18
|
+
export declare function gracileBuildEnvironmentPlugin({ state, }: {
|
|
19
|
+
state: PluginSharedState;
|
|
20
|
+
}): PluginOption;
|
|
21
|
+
//# sourceMappingURL=plugin-build-environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-build-environment.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-build-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,MAAM,CAAC;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,6BAA6B,CAAC,EAC7C,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,CA4Ef"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugin: build environment configuration.
|
|
3
|
+
*
|
|
4
|
+
* Owns all Environment API concerns for builds:
|
|
5
|
+
* - Top-level config: `builder.sharedConfigBuild`, `ssr.external` (server mode)
|
|
6
|
+
* - `configEnvironment('client')`: rollupOptions.input, outDir
|
|
7
|
+
* - `configEnvironment('ssr')`: outDir, SSR-specific build options, rollupOptions
|
|
8
|
+
* - `buildApp()`: orchestrates build order (client-only or client → SSR)
|
|
9
|
+
*
|
|
10
|
+
* `rollupOptions.input` must be set via `configEnvironment` (not the
|
|
11
|
+
* top-level `config` hook) because `builder.build(env)` uses
|
|
12
|
+
* environment-resolved config, not the top-level config.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
export function gracileBuildEnvironmentPlugin({ state, }) {
|
|
18
|
+
const isServerMode = state.outputMode === 'server';
|
|
19
|
+
return {
|
|
20
|
+
name: 'vite-plugin-gracile-build-env',
|
|
21
|
+
apply: 'build',
|
|
22
|
+
config() {
|
|
23
|
+
return {
|
|
24
|
+
...(isServerMode ? { ssr: { external: ['@gracile/gracile'] } } : {}),
|
|
25
|
+
builder: { sharedConfigBuild: true },
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
configEnvironment(name, config) {
|
|
29
|
+
if (name === 'client') {
|
|
30
|
+
if (!state.clientBuildInputList)
|
|
31
|
+
return null;
|
|
32
|
+
return {
|
|
33
|
+
build: {
|
|
34
|
+
rollupOptions: {
|
|
35
|
+
input: state.clientBuildInputList,
|
|
36
|
+
},
|
|
37
|
+
outDir: join(config.build?.outDir || 'dist', isServerMode ? 'client' : ''),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (name === 'ssr' && isServerMode) {
|
|
42
|
+
return {
|
|
43
|
+
build: {
|
|
44
|
+
outDir: 'dist/server',
|
|
45
|
+
copyPublicDir: false,
|
|
46
|
+
ssrEmitAssets: true,
|
|
47
|
+
cssMinify: true,
|
|
48
|
+
cssCodeSplit: true,
|
|
49
|
+
rollupOptions: {
|
|
50
|
+
input: 'entrypoint.js',
|
|
51
|
+
output: {
|
|
52
|
+
entryFileNames: '[name].js',
|
|
53
|
+
assetFileNames: (chunkInfo) => {
|
|
54
|
+
if (chunkInfo.name) {
|
|
55
|
+
const fileName = state.clientAssets[chunkInfo.name];
|
|
56
|
+
if (fileName)
|
|
57
|
+
return fileName;
|
|
58
|
+
return `assets/${chunkInfo.name.replace(/\.(.*)$/, '')}-[hash].[ext]`;
|
|
59
|
+
}
|
|
60
|
+
return 'assets/[name]-[hash].[ext]';
|
|
61
|
+
},
|
|
62
|
+
chunkFileNames: 'chunk/[name].js',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
},
|
|
70
|
+
async buildApp(builder) {
|
|
71
|
+
const client = builder.environments['client'];
|
|
72
|
+
if (!client)
|
|
73
|
+
throw new Error('Missing client build environment.');
|
|
74
|
+
await builder.build(client);
|
|
75
|
+
if (isServerMode) {
|
|
76
|
+
const ssr = builder.environments['ssr'];
|
|
77
|
+
if (!ssr)
|
|
78
|
+
throw new Error('Missing ssr build environment.');
|
|
79
|
+
await builder.build(ssr);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vite plugin: client-side build
|
|
2
|
+
* Vite plugin: client-side build route rendering.
|
|
3
3
|
*
|
|
4
4
|
* During `vite build`, this spins up a temporary dev server to render
|
|
5
|
-
* all routes into static HTML, then
|
|
6
|
-
*
|
|
5
|
+
* all routes into static HTML, then populates shared state with the
|
|
6
|
+
* rendered routes and input list.
|
|
7
|
+
*
|
|
8
|
+
* The actual HTML route resolution and asset collection are handled by
|
|
9
|
+
* separate Vite plugins (see `plugin-html-routes-build.ts`) that read
|
|
10
|
+
* from shared state and use `applyToEnvironment` to scope to the client.
|
|
7
11
|
*
|
|
8
12
|
* @internal
|
|
9
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-client-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-client-build.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"plugin-client-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-client-build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,wBAAwB,CAAC,EACxC,KAAK,EACL,sBAAsB,GACtB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,sBAAsB,EAAE,YAAY,CAAC;CACrC,GAAG,YAAY,CAoDf"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vite plugin: client-side build
|
|
2
|
+
* Vite plugin: client-side build route rendering.
|
|
3
3
|
*
|
|
4
4
|
* During `vite build`, this spins up a temporary dev server to render
|
|
5
|
-
* all routes into static HTML, then
|
|
6
|
-
*
|
|
5
|
+
* all routes into static HTML, then populates shared state with the
|
|
6
|
+
* rendered routes and input list.
|
|
7
|
+
*
|
|
8
|
+
* The actual HTML route resolution and asset collection are handled by
|
|
9
|
+
* separate Vite plugins (see `plugin-html-routes-build.ts`) that read
|
|
10
|
+
* from shared state and use `applyToEnvironment` to scope to the client.
|
|
7
11
|
*
|
|
8
12
|
* @internal
|
|
9
13
|
*/
|
|
10
|
-
import { join } from 'node:path';
|
|
11
14
|
import { getPluginContext } from '@gracile/internal-utils/plugin-context';
|
|
12
15
|
import { createServer } from 'vite';
|
|
13
16
|
import { buildRoutes } from './build-routes.js';
|
|
@@ -16,8 +19,9 @@ export function gracileClientBuildPlugin({ state, virtualRoutesForClient, }) {
|
|
|
16
19
|
name: 'vite-plugin-gracile-build',
|
|
17
20
|
apply: 'build',
|
|
18
21
|
async config(viteConfig) {
|
|
22
|
+
state.root = viteConfig.root || process.cwd();
|
|
19
23
|
const viteServerForClientHtmlBuild = await createServer({
|
|
20
|
-
root:
|
|
24
|
+
root: state.root,
|
|
21
25
|
server: { middlewareMode: true },
|
|
22
26
|
// NOTE: Stub. KEEP IT!
|
|
23
27
|
optimizeDeps: { include: [] },
|
|
@@ -34,6 +38,7 @@ export function gracileClientBuildPlugin({ state, virtualRoutesForClient, }) {
|
|
|
34
38
|
routes: state.routes,
|
|
35
39
|
});
|
|
36
40
|
state.renderedRoutes = htmlPages.renderedRoutes;
|
|
41
|
+
state.clientBuildInputList = htmlPages.inputList;
|
|
37
42
|
// NOTE: Vite's dev server does not invoke Rollup's `closeWatcher`
|
|
38
43
|
// hook when shutting down. Plugins like @rollup/plugin-typescript
|
|
39
44
|
// use `ts.createWatchProgram()` which sets up hundreds of FS
|
|
@@ -45,15 +50,6 @@ export function gracileClientBuildPlugin({ state, virtualRoutesForClient, }) {
|
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
await viteServerForClientHtmlBuild.close();
|
|
48
|
-
return {
|
|
49
|
-
build: {
|
|
50
|
-
rollupOptions: {
|
|
51
|
-
input: htmlPages.inputList,
|
|
52
|
-
plugins: [htmlPages.plugin],
|
|
53
|
-
},
|
|
54
|
-
outDir: join(viteConfig.build?.outDir || 'dist', state.outputMode === 'server' ? 'client' : ''),
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
53
|
},
|
|
58
54
|
};
|
|
59
55
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugins: HTML route resolution and asset collection for builds.
|
|
3
|
+
*
|
|
4
|
+
* These are registered as Vite plugins (not Rollup plugins via
|
|
5
|
+
* `rollupOptions.plugins`) so they work correctly with the Environment
|
|
6
|
+
* API's `builder.build(env)`, which does not inherit top-level
|
|
7
|
+
* `rollupOptions` into environment builds.
|
|
8
|
+
*
|
|
9
|
+
* They use `applyToEnvironment` to scope to the client build only,
|
|
10
|
+
* preventing the SSR build from trying to resolve HTML entries.
|
|
11
|
+
*
|
|
12
|
+
* Data is read lazily from shared state, which is populated by the
|
|
13
|
+
* client build plugin's `config` hook before these hooks run.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
import { type PluginOption } from 'vite';
|
|
18
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
19
|
+
export declare function gracileHtmlRoutesBuildPlugins({ state, }: {
|
|
20
|
+
state: PluginSharedState;
|
|
21
|
+
}): PluginOption[];
|
|
22
|
+
//# sourceMappingURL=plugin-html-routes-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-html-routes-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-html-routes-build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AAIvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AASlE,wBAAgB,6BAA6B,CAAC,EAC7C,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,EAAE,CAiJjB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugins: HTML route resolution and asset collection for builds.
|
|
3
|
+
*
|
|
4
|
+
* These are registered as Vite plugins (not Rollup plugins via
|
|
5
|
+
* `rollupOptions.plugins`) so they work correctly with the Environment
|
|
6
|
+
* API's `builder.build(env)`, which does not inherit top-level
|
|
7
|
+
* `rollupOptions` into environment builds.
|
|
8
|
+
*
|
|
9
|
+
* They use `applyToEnvironment` to scope to the client build only,
|
|
10
|
+
* preventing the SSR build from trying to resolve HTML entries.
|
|
11
|
+
*
|
|
12
|
+
* Data is read lazily from shared state, which is populated by the
|
|
13
|
+
* client build plugin's `config` hook before these hooks run.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
import { basename, extname, join } from 'node:path';
|
|
18
|
+
import { createFilter } from 'vite';
|
|
19
|
+
import { REGEX_TAG_LINK, REGEX_TAG_SCRIPT } from '../render/route-template.js';
|
|
20
|
+
function stripPremises(input) {
|
|
21
|
+
return input
|
|
22
|
+
.replace(/index\.html$/, '__index.doc.html')
|
|
23
|
+
.replace(/404\.html$/, '__404.doc.html')
|
|
24
|
+
.replace(/500\.html$/, '__500.doc.html');
|
|
25
|
+
}
|
|
26
|
+
export function gracileHtmlRoutesBuildPlugins({ state, }) {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
name: 'gracile-html-routes',
|
|
30
|
+
apply: 'build',
|
|
31
|
+
enforce: 'pre',
|
|
32
|
+
applyToEnvironment(environment) {
|
|
33
|
+
return environment.name !== 'ssr';
|
|
34
|
+
},
|
|
35
|
+
resolveId(id) {
|
|
36
|
+
const inputList = state.clientBuildInputList;
|
|
37
|
+
const root = state.root;
|
|
38
|
+
if (!inputList || !root)
|
|
39
|
+
return null;
|
|
40
|
+
if (extname(id) === '.html' && inputList.includes(id))
|
|
41
|
+
return join(root, id);
|
|
42
|
+
return null;
|
|
43
|
+
},
|
|
44
|
+
load(id) {
|
|
45
|
+
const renderedRoutes = state.renderedRoutes;
|
|
46
|
+
if (!renderedRoutes)
|
|
47
|
+
return null;
|
|
48
|
+
if (extname(id) === '.html') {
|
|
49
|
+
if (['index.html', '404.html', '500.html'].includes(basename(id))) {
|
|
50
|
+
const content = renderedRoutes.find((index) => index.absoluteId === id)?.html;
|
|
51
|
+
if (content)
|
|
52
|
+
return content;
|
|
53
|
+
}
|
|
54
|
+
if (state.gracileConfig.pages?.premises?.expose) {
|
|
55
|
+
if (basename(id).endsWith('doc.html')) {
|
|
56
|
+
const content = renderedRoutes.find((index) => stripPremises(index.absoluteId) === id)?.static.document;
|
|
57
|
+
if (content)
|
|
58
|
+
return content;
|
|
59
|
+
}
|
|
60
|
+
const content = renderedRoutes.find((index) => index.name === basename(id))?.html;
|
|
61
|
+
if (content)
|
|
62
|
+
return content;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'gracile-collect-handler-assets',
|
|
70
|
+
apply: 'build',
|
|
71
|
+
enforce: 'post',
|
|
72
|
+
applyToEnvironment(environment) {
|
|
73
|
+
return environment.name !== 'ssr';
|
|
74
|
+
},
|
|
75
|
+
buildStart() {
|
|
76
|
+
const renderedRoutes = state.renderedRoutes;
|
|
77
|
+
if (!renderedRoutes)
|
|
78
|
+
return;
|
|
79
|
+
if (!state.gracileConfig.pages?.premises?.expose)
|
|
80
|
+
return;
|
|
81
|
+
const premisesFilter = createFilter(state.gracileConfig.pages.premises.include, state.gracileConfig.pages.premises.exclude);
|
|
82
|
+
for (const route of renderedRoutes) {
|
|
83
|
+
if (premisesFilter(route.name) === false)
|
|
84
|
+
continue;
|
|
85
|
+
if (state.outputMode === 'server' && route.savePrerender !== true)
|
|
86
|
+
continue;
|
|
87
|
+
const fileNameParts = route.name.split('/');
|
|
88
|
+
const last = fileNameParts.pop();
|
|
89
|
+
const properties = last?.replace(/(.*)\.html$/, (_, r) => `__${r}.props.json`);
|
|
90
|
+
if (!properties)
|
|
91
|
+
throw new Error('No props.');
|
|
92
|
+
fileNameParts.push(properties);
|
|
93
|
+
const fileName = fileNameParts.join('/');
|
|
94
|
+
this.emitFile({
|
|
95
|
+
fileName,
|
|
96
|
+
type: 'asset',
|
|
97
|
+
source: JSON.stringify(route.static.props ?? {}),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
generateBundle(_, bundle) {
|
|
102
|
+
const renderedRoutes = state.renderedRoutes;
|
|
103
|
+
if (!renderedRoutes)
|
|
104
|
+
return;
|
|
105
|
+
if (state.outputMode !== 'server')
|
|
106
|
+
return;
|
|
107
|
+
for (const fileKey in bundle) {
|
|
108
|
+
const file = bundle[fileKey];
|
|
109
|
+
if (fileKey.endsWith('.html') && file && 'source' in file) {
|
|
110
|
+
const source = file.source.toString();
|
|
111
|
+
const collectedAssets = [
|
|
112
|
+
...[...source.matchAll(REGEX_TAG_SCRIPT)]
|
|
113
|
+
.map((v) => v[0])
|
|
114
|
+
// NOTE: Too brittle
|
|
115
|
+
.filter((v) => v.includes(`type="module"`)),
|
|
116
|
+
...[...source.matchAll(REGEX_TAG_LINK)]
|
|
117
|
+
.map((v) => v[0])
|
|
118
|
+
// NOTE: Too brittle
|
|
119
|
+
.filter((v) => /rel="(stylesheet|modulepreload)"/.test(v)),
|
|
120
|
+
].join('\n');
|
|
121
|
+
const route = renderedRoutes.find((r) => {
|
|
122
|
+
if (state.gracileConfig.pages?.premises?.expose)
|
|
123
|
+
return (`/${r.name}` ===
|
|
124
|
+
`/${fileKey}`.replace(/(.*?)\/__(.*?)\.doc\.html$/, (a, b, c) => `${b}/${c}.html`));
|
|
125
|
+
return r.name === fileKey;
|
|
126
|
+
});
|
|
127
|
+
if (route)
|
|
128
|
+
route.handlerAssets = collectedAssets;
|
|
129
|
+
if (route?.savePrerender !== true) {
|
|
130
|
+
delete bundle[fileKey];
|
|
131
|
+
// NOTE: Not sure if it's useful
|
|
132
|
+
if (route?.html)
|
|
133
|
+
route.html = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-serve.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAIjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,kBAAkB,CAAC,EAClC,KAAK,EACL,MAAM,EACN,MAAM,EACN,oBAAoB,GACpB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,MAAM,IAAI,CAAC;CACjC,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"plugin-serve.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAIjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wBAAgB,kBAAkB,CAAC,EAClC,KAAK,EACL,MAAM,EACN,MAAM,EACN,oBAAoB,GACpB,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,EAAE,MAAM,IAAI,CAAC;CACjC,GAAG,YAAY,CA4Df"}
|
|
@@ -27,8 +27,7 @@ export function gracileServePlugin({ state, config, logger, resetClientBuiltFlag
|
|
|
27
27
|
};
|
|
28
28
|
},
|
|
29
29
|
async configureServer(server) {
|
|
30
|
-
//
|
|
31
|
-
// vite.config hot reloading. Will be removed when adopting env. API.
|
|
30
|
+
// Reset so dev-mode config hot-reloads don't hit the guard.
|
|
32
31
|
resetClientBuiltFlag();
|
|
33
32
|
const version = getVersion();
|
|
34
33
|
logger.info(`${c.cyan(c.italic(c.underline('🧚 Gracile')))}` +
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vite plugins: server-side build pipeline.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Uses the Vite Environment API (`builder.buildApp()`) to coordinate
|
|
5
|
+
* client and SSR builds instead of a nested `build()` call.
|
|
6
6
|
*
|
|
7
7
|
* Includes:
|
|
8
|
-
* - Client asset filename collector (
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - Server-to-client asset mover
|
|
8
|
+
* - Client asset filename collector (client env writeBundle)
|
|
9
|
+
* - Virtual entrypoint codegen (SSR env only)
|
|
10
|
+
* - Server-to-client asset mover (SSR env only)
|
|
12
11
|
*
|
|
13
12
|
* @internal
|
|
14
13
|
*/
|
|
15
|
-
import {
|
|
14
|
+
import type { PluginOption } from 'vite';
|
|
16
15
|
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
17
16
|
/**
|
|
18
17
|
* Tracks client bundle assets so the server build can reference them
|
|
@@ -22,12 +21,23 @@ export declare function gracileCollectClientAssetsPlugin({ state, }: {
|
|
|
22
21
|
state: PluginSharedState;
|
|
23
22
|
}): PluginOption;
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* Generates the virtual `entrypoint.js` module for the server build.
|
|
25
|
+
* This is the server's main entry: it imports routes and creates the
|
|
26
|
+
* Gracile handler.
|
|
27
|
+
*
|
|
28
|
+
* Scoped to the SSR environment via `applyToEnvironment`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function gracileEntrypointPlugin({ state, }: {
|
|
31
|
+
state: PluginSharedState;
|
|
32
|
+
}): PluginOption;
|
|
33
|
+
/**
|
|
34
|
+
* After the server build writes its bundle, move any assets from
|
|
35
|
+
* `dist/server/assets/` into `dist/client/assets/` so the client
|
|
36
|
+
* can serve them.
|
|
37
|
+
*
|
|
38
|
+
* Scoped to the SSR environment via `applyToEnvironment`.
|
|
28
39
|
*/
|
|
29
|
-
export declare function
|
|
40
|
+
export declare function gracileMoveServerAssetsPlugin({ state, }: {
|
|
30
41
|
state: PluginSharedState;
|
|
31
|
-
virtualRoutesForClient: PluginOption;
|
|
32
42
|
}): PluginOption;
|
|
33
43
|
//# sourceMappingURL=plugin-server-build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-server-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-server-build.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"plugin-server-build.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-server-build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAEzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,EAChD,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,CAgBf;AAID;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,EACvC,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,CAsCf;AAID;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,EAC7C,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,YAAY,CA2Bf"}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vite plugins: server-side build pipeline.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Uses the Vite Environment API (`builder.buildApp()`) to coordinate
|
|
5
|
+
* client and SSR builds instead of a nested `build()` call.
|
|
6
6
|
*
|
|
7
7
|
* Includes:
|
|
8
|
-
* - Client asset filename collector (
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - Server-to-client asset mover
|
|
8
|
+
* - Client asset filename collector (client env writeBundle)
|
|
9
|
+
* - Virtual entrypoint codegen (SSR env only)
|
|
10
|
+
* - Server-to-client asset mover (SSR env only)
|
|
12
11
|
*
|
|
13
12
|
* @internal
|
|
14
13
|
*/
|
|
15
14
|
import { join } from 'node:path';
|
|
16
15
|
import { rename, rm } from 'node:fs/promises';
|
|
17
|
-
import { build } from 'vite';
|
|
18
|
-
import { virtualRoutes } from './virtual-routes.js';
|
|
19
16
|
// ── Client asset collector ───────────────────────────────────────────
|
|
20
17
|
/**
|
|
21
18
|
* Tracks client bundle assets so the server build can reference them
|
|
@@ -24,6 +21,9 @@ import { virtualRoutes } from './virtual-routes.js';
|
|
|
24
21
|
export function gracileCollectClientAssetsPlugin({ state, }) {
|
|
25
22
|
return {
|
|
26
23
|
name: 'vite-plugin-gracile-collect-client-assets-for-server',
|
|
24
|
+
applyToEnvironment(environment) {
|
|
25
|
+
return environment.name !== 'ssr';
|
|
26
|
+
},
|
|
27
27
|
writeBundle(_, bundle) {
|
|
28
28
|
if (state.outputMode === 'static')
|
|
29
29
|
return;
|
|
@@ -33,76 +33,21 @@ export function gracileCollectClientAssetsPlugin({ state, }) {
|
|
|
33
33
|
},
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
// ── Server build trigger ─────────────────────────────────────────────
|
|
37
|
-
/**
|
|
38
|
-
* After the client build finishes (`closeBundle`), run a nested SSR
|
|
39
|
-
* build that produces the server entrypoint and moves assets back into
|
|
40
|
-
* the client output directory.
|
|
41
|
-
*/
|
|
42
|
-
export function gracileServerBuildPlugin({ state, virtualRoutesForClient, }) {
|
|
43
|
-
return {
|
|
44
|
-
name: 'vite-plugin-gracile-server-build',
|
|
45
|
-
apply: 'build',
|
|
46
|
-
config(viteConfig) {
|
|
47
|
-
state.root = viteConfig.root || null;
|
|
48
|
-
},
|
|
49
|
-
async closeBundle() {
|
|
50
|
-
if (state.outputMode === 'static' ||
|
|
51
|
-
!state.routes ||
|
|
52
|
-
!state.renderedRoutes)
|
|
53
|
-
return;
|
|
54
|
-
const root = state.root || process.cwd();
|
|
55
|
-
await build({
|
|
56
|
-
root,
|
|
57
|
-
ssr: { external: ['@gracile/gracile'] },
|
|
58
|
-
build: {
|
|
59
|
-
target: 'esnext',
|
|
60
|
-
ssr: true,
|
|
61
|
-
copyPublicDir: false,
|
|
62
|
-
outDir: 'dist/server',
|
|
63
|
-
ssrEmitAssets: true,
|
|
64
|
-
cssMinify: true,
|
|
65
|
-
cssCodeSplit: true,
|
|
66
|
-
rollupOptions: {
|
|
67
|
-
input: 'entrypoint.js',
|
|
68
|
-
output: {
|
|
69
|
-
entryFileNames: '[name].js',
|
|
70
|
-
assetFileNames: (chunkInfo) => {
|
|
71
|
-
if (chunkInfo.name) {
|
|
72
|
-
const fileName = state.clientAssets[chunkInfo.name];
|
|
73
|
-
if (fileName)
|
|
74
|
-
return fileName;
|
|
75
|
-
// NOTE: When not imported at all from client
|
|
76
|
-
return `assets/${chunkInfo.name.replace(/\.(.*)$/, '')}-[hash].[ext]`;
|
|
77
|
-
}
|
|
78
|
-
return 'assets/[name]-[hash].[ext]';
|
|
79
|
-
},
|
|
80
|
-
chunkFileNames: 'chunk/[name].js',
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
plugins: [
|
|
85
|
-
virtualRoutesForClient,
|
|
86
|
-
virtualRoutes({
|
|
87
|
-
routes: state.routes,
|
|
88
|
-
renderedRoutes: state.renderedRoutes,
|
|
89
|
-
}),
|
|
90
|
-
gracileEntrypointPlugin(state),
|
|
91
|
-
gracileMoveServerAssetsPlugin(state),
|
|
92
|
-
],
|
|
93
|
-
});
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
36
|
// ── Virtual entrypoint ───────────────────────────────────────────────
|
|
98
37
|
/**
|
|
99
38
|
* Generates the virtual `entrypoint.js` module for the server build.
|
|
100
39
|
* This is the server's main entry: it imports routes and creates the
|
|
101
40
|
* Gracile handler.
|
|
41
|
+
*
|
|
42
|
+
* Scoped to the SSR environment via `applyToEnvironment`.
|
|
102
43
|
*/
|
|
103
|
-
function gracileEntrypointPlugin(state) {
|
|
44
|
+
export function gracileEntrypointPlugin({ state, }) {
|
|
104
45
|
return {
|
|
105
46
|
name: 'vite-plugin-gracile-entry',
|
|
47
|
+
apply: 'build',
|
|
48
|
+
applyToEnvironment(environment) {
|
|
49
|
+
return environment.name === 'ssr';
|
|
50
|
+
},
|
|
106
51
|
resolveId(id) {
|
|
107
52
|
if (id === 'entrypoint.js') {
|
|
108
53
|
return id;
|
|
@@ -137,10 +82,16 @@ export const handler = createGracileHandler({
|
|
|
137
82
|
* After the server build writes its bundle, move any assets from
|
|
138
83
|
* `dist/server/assets/` into `dist/client/assets/` so the client
|
|
139
84
|
* can serve them.
|
|
85
|
+
*
|
|
86
|
+
* Scoped to the SSR environment via `applyToEnvironment`.
|
|
140
87
|
*/
|
|
141
|
-
function gracileMoveServerAssetsPlugin(state) {
|
|
88
|
+
export function gracileMoveServerAssetsPlugin({ state, }) {
|
|
142
89
|
return {
|
|
143
90
|
name: 'gracile-move-server-assets',
|
|
91
|
+
apply: 'build',
|
|
92
|
+
applyToEnvironment(environment) {
|
|
93
|
+
return environment.name === 'ssr';
|
|
94
|
+
},
|
|
144
95
|
async writeBundle(_, bundle) {
|
|
145
96
|
const cwd = state.root || process.cwd();
|
|
146
97
|
await Promise.all(Object.entries(bundle).map(async ([file]) => {
|
|
@@ -15,6 +15,8 @@ export interface PluginSharedState {
|
|
|
15
15
|
routes: RoutesManifest;
|
|
16
16
|
/** Rendered route definitions from the client build phase. */
|
|
17
17
|
renderedRoutes: RenderedRouteDefinition[] | null;
|
|
18
|
+
/** Rollup input list for the client build (populated by route renderer). */
|
|
19
|
+
clientBuildInputList: string[] | null;
|
|
18
20
|
/** Maps original asset names → hashed filenames from the client bundle. */
|
|
19
21
|
clientAssets: Record<string, string>;
|
|
20
22
|
/** Vite `root` captured during build config. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-shared-state.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-shared-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IACjC,qEAAqE;IACrE,MAAM,EAAE,cAAc,CAAC;IAEvB,8DAA8D;IAC9D,cAAc,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC;IAEjD,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,gDAAgD;IAChD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,0CAA0C;IAC1C,aAAa,EAAE,aAAa,CAAC;IAE7B,6CAA6C;IAC7C,UAAU,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,aAAa,GAAG,SAAS,GAC/B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"plugin-shared-state.d.ts","sourceRoot":"","sources":["../../src/vite/plugin-shared-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IACjC,qEAAqE;IACrE,MAAM,EAAE,cAAc,CAAC;IAEvB,8DAA8D;IAC9D,cAAc,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC;IAEjD,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEtC,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,gDAAgD;IAChD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,0CAA0C;IAC1C,aAAa,EAAE,aAAa,CAAC;IAE7B,6CAA6C;IAC7C,UAAU,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,aAAa,GAAG,SAAS,GAC/B,iBAAiB,CAUnB"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { type Plugin } from 'vite';
|
|
2
|
-
import type { RenderedRouteDefinition } from '../routes/render.js';
|
|
3
2
|
import type { RoutesManifest } from '../routes/route.js';
|
|
4
3
|
import type { GracileConfig } from '../user-config.js';
|
|
4
|
+
import type { PluginSharedState } from './plugin-shared-state.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Server-side routes virtual module (`gracile:routes`).
|
|
7
|
+
*
|
|
8
|
+
* Scoped to the SSR build environment via `applyToEnvironment`.
|
|
9
|
+
* Reads from shared state lazily so `renderedRoutes` is available
|
|
10
|
+
* (populated during the client build).
|
|
7
11
|
*/
|
|
8
|
-
export declare function virtualRoutes({
|
|
9
|
-
|
|
10
|
-
renderedRoutes: RenderedRouteDefinition[];
|
|
12
|
+
export declare function virtualRoutes({ state, }: {
|
|
13
|
+
state: PluginSharedState;
|
|
11
14
|
}): Plugin[];
|
|
12
15
|
export declare function virtualRoutesClient({ routes: routesMap, mode, gracileConfig, }: {
|
|
13
16
|
routes: RoutesManifest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtual-routes.d.ts","sourceRoot":"","sources":["../../src/vite/virtual-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEjD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"virtual-routes.d.ts","sourceRoot":"","sources":["../../src/vite/virtual-routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAC7B,KAAK,GACL,EAAE;IACF,KAAK,EAAE,iBAAiB,CAAC;CACzB,GAAG,MAAM,EAAE,CAwEX;AAKD,wBAAgB,mBAAmB,CAAC,EACnC,MAAM,EAAE,SAAS,EACjB,IAAe,EACf,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;CAC7B,GAAG,MAAM,EAAE,CA4DX"}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import { normalizeToPosix } from '@gracile/internal-utils/paths';
|
|
2
2
|
import { createFilter } from 'vite';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Server-side routes virtual module (`gracile:routes`).
|
|
5
|
+
*
|
|
6
|
+
* Scoped to the SSR build environment via `applyToEnvironment`.
|
|
7
|
+
* Reads from shared state lazily so `renderedRoutes` is available
|
|
8
|
+
* (populated during the client build).
|
|
5
9
|
*/
|
|
6
|
-
export function virtualRoutes({
|
|
7
|
-
// root,
|
|
8
|
-
routes, renderedRoutes, }) {
|
|
10
|
+
export function virtualRoutes({ state, }) {
|
|
9
11
|
const virtualModuleId = 'gracile:routes';
|
|
10
12
|
const resolvedVirtualModuleId = `\0${virtualModuleId}`;
|
|
11
|
-
// TODO: Remove handler when prerendering route
|
|
12
|
-
const routesWithoutPrerender = [...routes];
|
|
13
|
-
const renderedRoutesWithoutPrerender = renderedRoutes;
|
|
14
|
-
// const routesWithoutPrerender = [...routes].filter(
|
|
15
|
-
// ([, r]) => r.prerender !== true,
|
|
16
|
-
// );
|
|
17
|
-
// const renderedRoutesWithoutPrerender = renderedRoutes.filter(
|
|
18
|
-
// (r) => r.savePrerender !== true,
|
|
19
|
-
// );
|
|
20
13
|
return [
|
|
21
14
|
{
|
|
22
15
|
name: 'gracile-server-routes',
|
|
16
|
+
apply: 'build',
|
|
17
|
+
applyToEnvironment(environment) {
|
|
18
|
+
return environment.name === 'ssr';
|
|
19
|
+
},
|
|
23
20
|
resolveId(id) {
|
|
24
21
|
if (id === virtualModuleId) {
|
|
25
22
|
return resolvedVirtualModuleId;
|
|
@@ -27,39 +24,43 @@ routes, renderedRoutes, }) {
|
|
|
27
24
|
return null;
|
|
28
25
|
},
|
|
29
26
|
load(id) {
|
|
30
|
-
if (id
|
|
31
|
-
return
|
|
27
|
+
if (id !== resolvedVirtualModuleId)
|
|
28
|
+
return null;
|
|
29
|
+
const routes = state.routes;
|
|
30
|
+
const renderedRoutes = state.renderedRoutes;
|
|
31
|
+
if (!routes || routes.size === 0 || !renderedRoutes)
|
|
32
|
+
return null;
|
|
33
|
+
const routesArray = [...routes];
|
|
34
|
+
return `
|
|
32
35
|
import { URLPattern } from '@gracile/gracile/url-pattern';
|
|
33
36
|
|
|
34
37
|
const routes = new Map(${
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
//
|
|
39
|
+
JSON.stringify(routesArray, null, 2).replaceAll(
|
|
40
|
+
// NOTE: Not strictly necessary, but just in case.
|
|
41
|
+
'"pattern": {}', '"pattern": null')})
|
|
39
42
|
routes.forEach((route, pattern) => {
|
|
40
43
|
route.pattern = new URLPattern(pattern, 'http://gracile');
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
const routeImports = new Map(
|
|
44
47
|
[
|
|
45
|
-
${
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
${routesArray
|
|
49
|
+
.map(([pattern, route]) => `['${pattern}', () => import('/${normalizeToPosix(route.filePath)}')],`)
|
|
50
|
+
.join('\n ')}
|
|
48
51
|
]
|
|
49
52
|
);
|
|
50
53
|
|
|
51
|
-
const routeAssets = new Map(${JSON.stringify(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
const routeAssets = new Map(${JSON.stringify(renderedRoutes.map((r) => [
|
|
55
|
+
`/${r.name
|
|
56
|
+
//
|
|
57
|
+
.replace(/index\.html$/, '')
|
|
58
|
+
.replace(/* Error pages */ /\.html$/, '/')}`,
|
|
59
|
+
r.handlerAssets,
|
|
60
|
+
]), null, 2)});
|
|
58
61
|
|
|
59
62
|
export { routes, routeImports, routeAssets };
|
|
60
63
|
`;
|
|
61
|
-
}
|
|
62
|
-
return null;
|
|
63
64
|
},
|
|
64
65
|
},
|
|
65
66
|
];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gracile/engine",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.1-next.0",
|
|
4
|
+
"description": "Vite-powered build and dev server engine for the Gracile framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"custom-elements",
|
|
7
7
|
"full-stack",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"!/dist/typedoc-entrypoint.*"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@gracile-labs/better-errors": "^0.
|
|
47
|
-
"@gracile/internal-utils": "^0.6.
|
|
46
|
+
"@gracile-labs/better-errors": "^0.3.1-next.0",
|
|
47
|
+
"@gracile/internal-utils": "^0.6.2-next.0",
|
|
48
48
|
"@whatwg-node/server": "^0.10.18",
|
|
49
49
|
"fdir": "^6.5.0",
|
|
50
50
|
"picocolors": "^1.1.1",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"access": "public",
|
|
61
61
|
"provenance": true
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "d9d9fc5711f843aaa0356d0f5a781aa68f264af2"
|
|
64
64
|
}
|