rari 0.2.18 → 0.2.19
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/client-dev.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/{runtime-client-P4vvSVPV.d.ts → runtime-client-CwQkaktd.d.ts} +14 -1
- package/dist/{server-CpxpL2un.d.ts → server-Bna18v8X.d.ts} +4 -2
- package/dist/{server-BrkE-3ny.js → server-DYwz6RKf.js} +85 -7
- package/dist/{server-build-DaBgiV55.js → server-build-BM8_GFF5.js} +23 -2
- package/dist/server-build-DcbOtG3e.js +3 -0
- package/dist/server.d.ts +3 -3
- package/dist/server.js +3 -3
- package/package.json +6 -6
- package/src/router/cache.ts +54 -0
- package/src/router/types.ts +2 -0
- package/src/server.ts +3 -1
- package/src/vite/index.ts +125 -1
- package/src/vite/server-build.ts +36 -2
- package/dist/server-build-Cp6_RdeA.js +0 -3
package/dist/client-dev.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-
|
|
1
|
+
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CwQkaktd.js";
|
|
2
2
|
export { type ErrorBoundaryProps, type FileRouteInfo, HttpRuntimeClient, type LayoutProps, Link, type LinkProps, type LoadingProps, Navigate, type NavigationOptions, type NavigationState, Outlet, type PageComponent, type PageProps, RouteComponent as Route, type RouteGenerationOptions, type RouteMatch, type RouteMeta, type RouteParams, type Route as RouteType, type RouterConfig, type RouterContext, RouterProvider, type RouterProviderProps, Routes, type RuntimeClient, type SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-
|
|
1
|
+
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CwQkaktd.js";
|
|
2
2
|
export { type ErrorBoundaryProps, type FileRouteInfo, HttpRuntimeClient, type LayoutProps, Link, type LinkProps, type LoadingProps, Navigate, type NavigationOptions, type NavigationState, Outlet, type PageComponent, type PageProps, RouteComponent as Route, type RouteGenerationOptions, type RouteMatch, type RouteMeta, type RouteParams, type Route as RouteType, type RouterConfig, type RouterContext, RouterProvider, type RouterProviderProps, Routes, type RuntimeClient, type SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
export { ErrorBoundaryProps, FileRouteGenerator, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, RouteComponent as Route, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, Route as RouteType, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
1
|
+
import { CacheConfig, ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageCacheConfig, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CwQkaktd.js";
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-Bna18v8X.js";
|
|
3
|
+
export { CacheConfig, ErrorBoundaryProps, FileRouteGenerator, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageCacheConfig, PageComponent, PageProps, RouteComponent as Route, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, Route as RouteType, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, router_default, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CcEhh-F7.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
import "./server-build-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-DYwz6RKf.js";
|
|
3
|
+
import "./server-build-BM8_GFF5.js";
|
|
4
4
|
|
|
5
|
-
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
5
|
+
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import React$1, { ComponentType, ReactNode } from "react";
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
|
+
//#region src/router/cache.d.ts
|
|
5
|
+
interface CacheConfig {
|
|
6
|
+
routes?: Record<string, string>;
|
|
7
|
+
static?: string;
|
|
8
|
+
serverComponents?: string;
|
|
9
|
+
}
|
|
10
|
+
interface PageCacheConfig {
|
|
11
|
+
'cache-control'?: string;
|
|
12
|
+
'vary'?: string;
|
|
13
|
+
[key: string]: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
4
16
|
//#region src/router/types.d.ts
|
|
5
17
|
interface Route {
|
|
6
18
|
path: string;
|
|
@@ -18,6 +30,7 @@ interface RouteMeta {
|
|
|
18
30
|
title?: string;
|
|
19
31
|
description?: string;
|
|
20
32
|
requiresAuth?: boolean;
|
|
33
|
+
cacheConfig?: PageCacheConfig;
|
|
21
34
|
[key: string]: any;
|
|
22
35
|
}
|
|
23
36
|
interface RouteParams {
|
|
@@ -281,4 +294,4 @@ declare function createHttpRuntimeClient(options?: {
|
|
|
281
294
|
ssl?: boolean;
|
|
282
295
|
}): RuntimeClient;
|
|
283
296
|
//#endregion
|
|
284
|
-
export { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext$1 as RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter };
|
|
297
|
+
export { CacheConfig, ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageCacheConfig, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext$1 as RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Route, RouteGenerationOptions } from "./runtime-client-
|
|
1
|
+
import { CacheConfig, Route, RouteGenerationOptions } from "./runtime-client-CwQkaktd.js";
|
|
2
2
|
import { Plugin, UserConfig } from "rolldown-vite";
|
|
3
3
|
|
|
4
4
|
//#region src/router/file-routes.d.ts
|
|
@@ -60,10 +60,12 @@ interface RariOptions {
|
|
|
60
60
|
projectRoot?: string;
|
|
61
61
|
serverBuild?: ServerBuildOptions;
|
|
62
62
|
serverHandler?: boolean;
|
|
63
|
+
caching?: CacheConfig;
|
|
63
64
|
}
|
|
65
|
+
declare function defineRariOptions(config: RariOptions): RariOptions;
|
|
64
66
|
declare function rari(options?: RariOptions): Plugin[];
|
|
65
67
|
declare function defineRariConfig(config: UserConfig & {
|
|
66
68
|
plugins?: Plugin[];
|
|
67
69
|
}): UserConfig;
|
|
68
70
|
//#endregion
|
|
69
|
-
export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
|
|
71
|
+
export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __commonJS, __require, __toESM } from "./chunk-BLXvPPr8.js";
|
|
2
2
|
import { analyzeFilePath } from "./runtime-client-CcEhh-F7.js";
|
|
3
|
-
import { createServerBuildPlugin } from "./server-build-
|
|
3
|
+
import { createServerBuildPlugin } from "./server-build-BM8_GFF5.js";
|
|
4
4
|
import fs, { promises } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process$1 from "node:process";
|
|
@@ -5637,6 +5637,40 @@ function scanForClientComponents(srcDir) {
|
|
|
5637
5637
|
scanDirectory(srcDir);
|
|
5638
5638
|
return clientComponents;
|
|
5639
5639
|
}
|
|
5640
|
+
function extractCacheConfigFromContent(content) {
|
|
5641
|
+
const ast = acorn.parse(content, {
|
|
5642
|
+
ecmaVersion: 2022,
|
|
5643
|
+
sourceType: "module",
|
|
5644
|
+
allowImportExportEverywhere: true
|
|
5645
|
+
});
|
|
5646
|
+
for (const node of ast.body) if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
|
|
5647
|
+
for (const declarator of node.declaration.declarations) if (declarator.id && declarator.id.name === "cacheConfig" && declarator.init && declarator.init.type === "ObjectExpression") {
|
|
5648
|
+
const config = {};
|
|
5649
|
+
for (const prop of declarator.init.properties) if (prop.type === "Property" && prop.key && prop.value && prop.value.type === "Literal") {
|
|
5650
|
+
const keyName = prop.key.type === "Literal" ? prop.key.value : prop.key.name;
|
|
5651
|
+
if (keyName === "cache-control" || keyName === "vary") config[keyName] = prop.value.value;
|
|
5652
|
+
}
|
|
5653
|
+
return Object.keys(config).length > 0 ? config : void 0;
|
|
5654
|
+
}
|
|
5655
|
+
}
|
|
5656
|
+
return void 0;
|
|
5657
|
+
}
|
|
5658
|
+
function matchesPattern(pattern, path$5) {
|
|
5659
|
+
if (pattern === path$5) return true;
|
|
5660
|
+
if (pattern.endsWith("/*")) {
|
|
5661
|
+
const prefix = pattern.slice(0, -2);
|
|
5662
|
+
return path$5.startsWith(prefix);
|
|
5663
|
+
}
|
|
5664
|
+
if (pattern.includes("*")) {
|
|
5665
|
+
const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
|
|
5666
|
+
const regex = /* @__PURE__ */ new RegExp(`^${regexPattern}$`);
|
|
5667
|
+
return regex.test(path$5);
|
|
5668
|
+
}
|
|
5669
|
+
return false;
|
|
5670
|
+
}
|
|
5671
|
+
function defineRariOptions(config) {
|
|
5672
|
+
return config;
|
|
5673
|
+
}
|
|
5640
5674
|
function rari(options = {}) {
|
|
5641
5675
|
const componentTypeCache = /* @__PURE__ */ new Map();
|
|
5642
5676
|
const serverComponents = /* @__PURE__ */ new Set();
|
|
@@ -6028,7 +6062,7 @@ const ${componentName$1} = registerClientReference(
|
|
|
6028
6062
|
const srcDir = path.join(projectRoot, "src");
|
|
6029
6063
|
const discoverAndRegisterComponents = async () => {
|
|
6030
6064
|
try {
|
|
6031
|
-
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-
|
|
6065
|
+
const { ServerComponentBuilder, scanDirectory } = await import("./server-build-DcbOtG3e.js");
|
|
6032
6066
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6033
6067
|
outDir: "temp",
|
|
6034
6068
|
serverDir: "server",
|
|
@@ -6045,7 +6079,8 @@ const ${componentName$1} = registerClientReference(
|
|
|
6045
6079
|
headers: { "Content-Type": "application/json" },
|
|
6046
6080
|
body: JSON.stringify({
|
|
6047
6081
|
component_id: component.id,
|
|
6048
|
-
component_code: component.code
|
|
6082
|
+
component_code: component.code,
|
|
6083
|
+
cache_config: component.cacheConfig
|
|
6049
6084
|
})
|
|
6050
6085
|
});
|
|
6051
6086
|
if (!registerResponse.ok) {
|
|
@@ -6162,7 +6197,7 @@ const ${componentName$1} = registerClientReference(
|
|
|
6162
6197
|
};
|
|
6163
6198
|
const handleServerComponentHMR = async (filePath) => {
|
|
6164
6199
|
try {
|
|
6165
|
-
const { ServerComponentBuilder } = await import("./server-build-
|
|
6200
|
+
const { ServerComponentBuilder } = await import("./server-build-DcbOtG3e.js");
|
|
6166
6201
|
const builder = new ServerComponentBuilder(projectRoot, {
|
|
6167
6202
|
outDir: "temp",
|
|
6168
6203
|
serverDir: "server",
|
|
@@ -6179,7 +6214,8 @@ const ${componentName$1} = registerClientReference(
|
|
|
6179
6214
|
headers: { "Content-Type": "application/json" },
|
|
6180
6215
|
body: JSON.stringify({
|
|
6181
6216
|
component_id: component.id,
|
|
6182
|
-
component_code: component.code
|
|
6217
|
+
component_code: component.code,
|
|
6218
|
+
cache_config: component.cacheConfig
|
|
6183
6219
|
})
|
|
6184
6220
|
});
|
|
6185
6221
|
if (!registerResponse.ok) {
|
|
@@ -7507,7 +7543,49 @@ ${registrations.join("\n")}
|
|
|
7507
7543
|
}
|
|
7508
7544
|
};
|
|
7509
7545
|
const serverBuildPlugin = createServerBuildPlugin(options.serverBuild);
|
|
7510
|
-
|
|
7546
|
+
const cacheMiddlewarePlugin = {
|
|
7547
|
+
name: "rari:cache-middleware",
|
|
7548
|
+
configureServer(server) {
|
|
7549
|
+
server.middlewares.use((req, res, next) => {
|
|
7550
|
+
if (req.url?.startsWith("/@fs/")) {
|
|
7551
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
7552
|
+
next();
|
|
7553
|
+
return;
|
|
7554
|
+
}
|
|
7555
|
+
const url = req.url || "";
|
|
7556
|
+
const pathname = url.split("?")[0];
|
|
7557
|
+
if (pathname && !pathname.includes(".") && !pathname.startsWith("/api") && !pathname.startsWith("/rsc")) {
|
|
7558
|
+
if (options.caching?.routes) {
|
|
7559
|
+
for (const [pattern, cacheControl] of Object.entries(options.caching.routes)) if (matchesPattern(pattern, pathname)) {
|
|
7560
|
+
res.setHeader("cache-control", cacheControl);
|
|
7561
|
+
break;
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
const pagePath = pathname === "/" ? "/index" : pathname;
|
|
7565
|
+
const pageFilePath = path.join(process$1.cwd(), "src/pages", `${pagePath.slice(1) || "index"}.tsx`);
|
|
7566
|
+
if (fs.existsSync(pageFilePath)) {
|
|
7567
|
+
const pageContent = fs.readFileSync(pageFilePath, "utf-8");
|
|
7568
|
+
const cacheConfig = extractCacheConfigFromContent(pageContent);
|
|
7569
|
+
if (cacheConfig) Object.entries(cacheConfig).forEach(([key, value]) => {
|
|
7570
|
+
if (value) res.setHeader(key, value);
|
|
7571
|
+
});
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
next();
|
|
7575
|
+
});
|
|
7576
|
+
},
|
|
7577
|
+
writeBundle() {
|
|
7578
|
+
if (options.caching) {
|
|
7579
|
+
const cacheConfigPath = path.join(process$1.cwd(), "dist", "cache-config.json");
|
|
7580
|
+
fs.writeFileSync(cacheConfigPath, JSON.stringify(options.caching, null, 2));
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
};
|
|
7584
|
+
return [
|
|
7585
|
+
mainPlugin,
|
|
7586
|
+
serverBuildPlugin,
|
|
7587
|
+
cacheMiddlewarePlugin
|
|
7588
|
+
];
|
|
7511
7589
|
}
|
|
7512
7590
|
function defineRariConfig(config) {
|
|
7513
7591
|
return {
|
|
@@ -7517,4 +7595,4 @@ function defineRariConfig(config) {
|
|
|
7517
7595
|
}
|
|
7518
7596
|
|
|
7519
7597
|
//#endregion
|
|
7520
|
-
export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
|
|
7598
|
+
export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
|
|
@@ -64,13 +64,33 @@ var ServerComponentBuilder = class {
|
|
|
64
64
|
const code = fs.readFileSync(filePath, "utf-8");
|
|
65
65
|
const dependencies = this.extractDependencies(code);
|
|
66
66
|
const hasNodeImports = this.hasNodeImports(code);
|
|
67
|
+
const cacheConfig = this.extractCacheConfig(code);
|
|
67
68
|
this.serverComponents.set(filePath, {
|
|
68
69
|
filePath,
|
|
69
70
|
originalCode: code,
|
|
70
71
|
dependencies,
|
|
71
|
-
hasNodeImports
|
|
72
|
+
hasNodeImports,
|
|
73
|
+
cacheConfig
|
|
72
74
|
});
|
|
73
75
|
}
|
|
76
|
+
extractCacheConfig(code) {
|
|
77
|
+
try {
|
|
78
|
+
const cacheConfigRegex = /export\s+const\s+cacheConfig\s*[:=]\s*(\{[^}]*\})/;
|
|
79
|
+
const match = code.match(cacheConfigRegex);
|
|
80
|
+
if (match) {
|
|
81
|
+
const configStr = match[1];
|
|
82
|
+
const cacheControlMatch = configStr.match(/'cache-control'\s*:\s*['"]([^'"]+)['"]/);
|
|
83
|
+
const varyMatch = configStr.match(/'vary'\s*:\s*['"]([^'"]+)['"]/);
|
|
84
|
+
const config = {};
|
|
85
|
+
if (cacheControlMatch) config["cache-control"] = cacheControlMatch[1];
|
|
86
|
+
if (varyMatch) config.vary = varyMatch[1];
|
|
87
|
+
return Object.keys(config).length > 0 ? config : void 0;
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.warn(`Failed to extract cache config from component: ${error}`);
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
74
94
|
extractDependencies(code) {
|
|
75
95
|
const dependencies = [];
|
|
76
96
|
const importRegex = /import(?:\s+(?:\w+|\{[^}]*\}|\*\s+as\s+\w+)(?:\s*,\s*(?:\w+|\{[^}]*\}|\*\s+as\s+\w+))*\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
@@ -118,7 +138,8 @@ var ServerComponentBuilder = class {
|
|
|
118
138
|
const transformedCode = await this.buildComponentCodeOnly(filePath, componentId, component);
|
|
119
139
|
components.push({
|
|
120
140
|
id: componentId,
|
|
121
|
-
code: transformedCode
|
|
141
|
+
code: transformedCode,
|
|
142
|
+
cacheConfig: component.cacheConfig
|
|
122
143
|
});
|
|
123
144
|
}
|
|
124
145
|
return components;
|
package/dist/server.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
export { ErrorBoundaryProps, FileRouteGenerator, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageComponent, PageProps, RouteComponent as Route, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, Route as RouteType, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
1
|
+
import { CacheConfig, ErrorBoundaryProps, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageCacheConfig, PageComponent, PageProps, Route, RouteComponent, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CwQkaktd.js";
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-Bna18v8X.js";
|
|
3
|
+
export { CacheConfig, ErrorBoundaryProps, FileRouteGenerator, FileRouteInfo, HttpRuntimeClient, LayoutProps, Link, LinkProps, LoadingProps, Navigate, NavigationOptions, NavigationState, Outlet, PageCacheConfig, PageComponent, PageProps, RouteComponent as Route, RouteGenerationOptions, RouteMatch, RouteMeta, RouteParams, Route as RouteType, RouterConfig, RouterContext, RouterProvider, RouterProviderProps, Routes, RuntimeClient, SearchParams, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent, Routes, buildSearchString, buildUrl, createHttpRuntimeClient, extractParamNames, findMatchingRoute, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, normalizePathname, parseSearchParams, parseUrl, router_default, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, withRouter } from "./runtime-client-CcEhh-F7.js";
|
|
2
|
-
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-
|
|
3
|
-
import "./server-build-
|
|
2
|
+
import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, defineRariOptions, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-DYwz6RKf.js";
|
|
3
|
+
import "./server-build-BM8_GFF5.js";
|
|
4
4
|
|
|
5
|
-
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
|
5
|
+
export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createRouteManifest, defineRariConfig, defineRariOptions, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rari",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.19",
|
|
5
5
|
"description": "Runtime Accelerated Rendering Infrastructure (Rari)",
|
|
6
6
|
"author": "Ryan Skinner",
|
|
7
7
|
"license": "MIT",
|
|
@@ -82,11 +82,11 @@
|
|
|
82
82
|
"rollup-plugin-esbuild": "^6.2.1"
|
|
83
83
|
},
|
|
84
84
|
"optionalDependencies": {
|
|
85
|
-
"rari-darwin-arm64": "0.2.
|
|
86
|
-
"rari-darwin-x64": "0.2.
|
|
87
|
-
"rari-linux-arm64": "0.2.
|
|
88
|
-
"rari-linux-x64": "0.2.
|
|
89
|
-
"rari-win32-x64": "0.2.
|
|
85
|
+
"rari-darwin-arm64": "0.2.14",
|
|
86
|
+
"rari-darwin-x64": "0.2.14",
|
|
87
|
+
"rari-linux-arm64": "0.2.14",
|
|
88
|
+
"rari-linux-x64": "0.2.14",
|
|
89
|
+
"rari-win32-x64": "0.2.14"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@types/node": "^24.3.0",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface CacheConfig {
|
|
2
|
+
routes?: Record<string, string>
|
|
3
|
+
static?: string
|
|
4
|
+
serverComponents?: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface PageCacheConfig {
|
|
8
|
+
'cache-control'?: string
|
|
9
|
+
'vary'?: string
|
|
10
|
+
[key: string]: string | undefined
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const cacheConfigs = new Map<string, PageCacheConfig>()
|
|
14
|
+
|
|
15
|
+
export function registerPageCacheConfig(pagePath: string, config: PageCacheConfig): void {
|
|
16
|
+
cacheConfigs.set(pagePath, config)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getPageCacheConfig(pagePath: string): PageCacheConfig | undefined {
|
|
20
|
+
return cacheConfigs.get(pagePath)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function clearPageCacheConfigs(): void {
|
|
24
|
+
cacheConfigs.clear()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getAllPageCacheConfigs(): Map<string, PageCacheConfig> {
|
|
28
|
+
return new Map(cacheConfigs)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function extractPageCacheConfig(pageModule: any): PageCacheConfig | undefined {
|
|
32
|
+
if (pageModule && typeof pageModule === 'object') {
|
|
33
|
+
return pageModule.cacheConfig
|
|
34
|
+
}
|
|
35
|
+
return undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function registerPageCacheConfigFromModule(pagePath: string, pageModule: any): void {
|
|
39
|
+
const cacheConfig = extractPageCacheConfig(pageModule)
|
|
40
|
+
if (cacheConfig) {
|
|
41
|
+
registerPageCacheConfig(pagePath, cacheConfig)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function applyCacheHeaders(
|
|
46
|
+
headers: Record<string, string>,
|
|
47
|
+
cacheConfig: PageCacheConfig,
|
|
48
|
+
): void {
|
|
49
|
+
for (const [key, value] of Object.entries(cacheConfig)) {
|
|
50
|
+
if (value !== undefined) {
|
|
51
|
+
headers[key.toLowerCase()] = value
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/router/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from 'react'
|
|
2
|
+
import type { PageCacheConfig } from './cache'
|
|
2
3
|
|
|
3
4
|
export interface Route {
|
|
4
5
|
path: string
|
|
@@ -17,6 +18,7 @@ export interface RouteMeta {
|
|
|
17
18
|
title?: string
|
|
18
19
|
description?: string
|
|
19
20
|
requiresAuth?: boolean
|
|
21
|
+
cacheConfig?: PageCacheConfig
|
|
20
22
|
[key: string]: any
|
|
21
23
|
}
|
|
22
24
|
|
package/src/server.ts
CHANGED
|
@@ -49,6 +49,8 @@ export type {
|
|
|
49
49
|
SearchParams,
|
|
50
50
|
} from './router'
|
|
51
51
|
|
|
52
|
+
export type { CacheConfig, PageCacheConfig } from './router/cache'
|
|
53
|
+
|
|
52
54
|
export {
|
|
53
55
|
convertFilePatternToRoutePattern,
|
|
54
56
|
createRouteManifest,
|
|
@@ -67,4 +69,4 @@ export { createHttpRuntimeClient, HttpRuntimeClient } from './runtime-client'
|
|
|
67
69
|
|
|
68
70
|
export type { RuntimeClient } from './runtime-client'
|
|
69
71
|
|
|
70
|
-
export { defineRariConfig, rari } from './vite'
|
|
72
|
+
export { defineRariConfig, defineRariOptions, rari } from './vite'
|
package/src/vite/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Buffer } from 'node:buffer'
|
|
2
2
|
import type { Plugin, UserConfig } from 'rolldown-vite'
|
|
3
|
+
import type { CacheConfig, PageCacheConfig } from '../router/cache'
|
|
3
4
|
import type { ServerBuildOptions } from './server-build'
|
|
4
5
|
import { spawn } from 'node:child_process'
|
|
5
6
|
import fs from 'node:fs'
|
|
@@ -12,6 +13,7 @@ interface RariOptions {
|
|
|
12
13
|
projectRoot?: string
|
|
13
14
|
serverBuild?: ServerBuildOptions
|
|
14
15
|
serverHandler?: boolean
|
|
16
|
+
caching?: CacheConfig
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
function scanForClientComponents(srcDir: string): Set<string> {
|
|
@@ -50,6 +52,75 @@ function scanForClientComponents(srcDir: string): Set<string> {
|
|
|
50
52
|
return clientComponents
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
export type { CacheConfig, PageCacheConfig } from '../router/cache'
|
|
56
|
+
|
|
57
|
+
function extractCacheConfigFromContent(content: string): PageCacheConfig | undefined {
|
|
58
|
+
const ast = acorn.parse(content, {
|
|
59
|
+
ecmaVersion: 2022,
|
|
60
|
+
sourceType: 'module',
|
|
61
|
+
allowImportExportEverywhere: true,
|
|
62
|
+
}) as any
|
|
63
|
+
|
|
64
|
+
for (const node of ast.body) {
|
|
65
|
+
if (
|
|
66
|
+
node.type === 'ExportNamedDeclaration'
|
|
67
|
+
&& node.declaration
|
|
68
|
+
&& node.declaration.type === 'VariableDeclaration'
|
|
69
|
+
) {
|
|
70
|
+
for (const declarator of node.declaration.declarations) {
|
|
71
|
+
if (
|
|
72
|
+
declarator.id
|
|
73
|
+
&& declarator.id.name === 'cacheConfig'
|
|
74
|
+
&& declarator.init
|
|
75
|
+
&& declarator.init.type === 'ObjectExpression'
|
|
76
|
+
) {
|
|
77
|
+
const config: PageCacheConfig = {}
|
|
78
|
+
|
|
79
|
+
for (const prop of declarator.init.properties) {
|
|
80
|
+
if (
|
|
81
|
+
prop.type === 'Property'
|
|
82
|
+
&& prop.key
|
|
83
|
+
&& prop.value
|
|
84
|
+
&& prop.value.type === 'Literal'
|
|
85
|
+
) {
|
|
86
|
+
const keyName = prop.key.type === 'Literal' ? prop.key.value : prop.key.name
|
|
87
|
+
if (keyName === 'cache-control' || keyName === 'vary') {
|
|
88
|
+
config[keyName as keyof PageCacheConfig] = prop.value.value as string
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return Object.keys(config).length > 0 ? config : undefined
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return undefined
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function matchesPattern(pattern: string, path: string): boolean {
|
|
103
|
+
if (pattern === path)
|
|
104
|
+
return true
|
|
105
|
+
|
|
106
|
+
if (pattern.endsWith('/*')) {
|
|
107
|
+
const prefix = pattern.slice(0, -2)
|
|
108
|
+
return path.startsWith(prefix)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (pattern.includes('*')) {
|
|
112
|
+
const regexPattern = pattern.replace(/\*/g, '.*').replace(/\//g, '\\/')
|
|
113
|
+
const regex = new RegExp(`^${regexPattern}$`)
|
|
114
|
+
return regex.test(path)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return false
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function defineRariOptions(config: RariOptions): RariOptions {
|
|
121
|
+
return config
|
|
122
|
+
}
|
|
123
|
+
|
|
53
124
|
export function rari(options: RariOptions = {}): Plugin[] {
|
|
54
125
|
const componentTypeCache = new Map<string, 'client' | 'server' | 'unknown'>()
|
|
55
126
|
const serverComponents = new Set<string>()
|
|
@@ -789,6 +860,7 @@ const ${componentName} = registerClientReference(
|
|
|
789
860
|
body: JSON.stringify({
|
|
790
861
|
component_id: component.id,
|
|
791
862
|
component_code: component.code,
|
|
863
|
+
cache_config: component.cacheConfig,
|
|
792
864
|
}),
|
|
793
865
|
},
|
|
794
866
|
)
|
|
@@ -1008,6 +1080,7 @@ const ${componentName} = registerClientReference(
|
|
|
1008
1080
|
body: JSON.stringify({
|
|
1009
1081
|
component_id: component.id,
|
|
1010
1082
|
component_code: component.code,
|
|
1083
|
+
cache_config: component.cacheConfig,
|
|
1011
1084
|
}),
|
|
1012
1085
|
},
|
|
1013
1086
|
)
|
|
@@ -2405,7 +2478,58 @@ ${registrations.join('\n')}
|
|
|
2405
2478
|
|
|
2406
2479
|
const serverBuildPlugin = createServerBuildPlugin(options.serverBuild)
|
|
2407
2480
|
|
|
2408
|
-
|
|
2481
|
+
const cacheMiddlewarePlugin: Plugin = {
|
|
2482
|
+
name: 'rari:cache-middleware',
|
|
2483
|
+
configureServer(server) {
|
|
2484
|
+
server.middlewares.use((req, res, next) => {
|
|
2485
|
+
if (req.url?.startsWith('/@fs/')) {
|
|
2486
|
+
res.setHeader('Cache-Control', 'no-cache')
|
|
2487
|
+
next()
|
|
2488
|
+
return
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
const url = req.url || ''
|
|
2492
|
+
const pathname = url.split('?')[0]
|
|
2493
|
+
|
|
2494
|
+
if (pathname && !pathname.includes('.') && !pathname.startsWith('/api') && !pathname.startsWith('/rsc')) {
|
|
2495
|
+
if (options.caching?.routes) {
|
|
2496
|
+
for (const [pattern, cacheControl] of Object.entries(options.caching.routes)) {
|
|
2497
|
+
if (matchesPattern(pattern, pathname)) {
|
|
2498
|
+
res.setHeader('cache-control', cacheControl)
|
|
2499
|
+
break
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
const pagePath = pathname === '/' ? '/index' : pathname
|
|
2505
|
+
const pageFilePath = path.join(process.cwd(), 'src/pages', `${pagePath.slice(1) || 'index'}.tsx`)
|
|
2506
|
+
|
|
2507
|
+
if (fs.existsSync(pageFilePath)) {
|
|
2508
|
+
const pageContent = fs.readFileSync(pageFilePath, 'utf-8')
|
|
2509
|
+
const cacheConfig = extractCacheConfigFromContent(pageContent)
|
|
2510
|
+
|
|
2511
|
+
if (cacheConfig) {
|
|
2512
|
+
Object.entries(cacheConfig).forEach(([key, value]) => {
|
|
2513
|
+
if (value) {
|
|
2514
|
+
res.setHeader(key, value)
|
|
2515
|
+
}
|
|
2516
|
+
})
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
next()
|
|
2522
|
+
})
|
|
2523
|
+
},
|
|
2524
|
+
writeBundle() {
|
|
2525
|
+
if (options.caching) {
|
|
2526
|
+
const cacheConfigPath = path.join(process.cwd(), 'dist', 'cache-config.json')
|
|
2527
|
+
fs.writeFileSync(cacheConfigPath, JSON.stringify(options.caching, null, 2))
|
|
2528
|
+
}
|
|
2529
|
+
},
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
return [mainPlugin, serverBuildPlugin, cacheMiddlewarePlugin]
|
|
2409
2533
|
}
|
|
2410
2534
|
|
|
2411
2535
|
export function defineRariConfig(
|
package/src/vite/server-build.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from 'rolldown-vite'
|
|
2
|
+
import type { PageCacheConfig } from '../router/cache'
|
|
2
3
|
import fs from 'node:fs'
|
|
3
4
|
import path from 'node:path'
|
|
4
5
|
import process from 'node:process'
|
|
@@ -14,6 +15,7 @@ export interface ServerComponentManifest {
|
|
|
14
15
|
bundlePath: string
|
|
15
16
|
dependencies: string[]
|
|
16
17
|
hasNodeImports: boolean
|
|
18
|
+
cacheConfig?: PageCacheConfig
|
|
17
19
|
}
|
|
18
20
|
>
|
|
19
21
|
version: string
|
|
@@ -35,6 +37,7 @@ export class ServerComponentBuilder {
|
|
|
35
37
|
originalCode: string
|
|
36
38
|
dependencies: string[]
|
|
37
39
|
hasNodeImports: boolean
|
|
40
|
+
cacheConfig?: PageCacheConfig
|
|
38
41
|
}
|
|
39
42
|
>()
|
|
40
43
|
|
|
@@ -143,15 +146,45 @@ export class ServerComponentBuilder {
|
|
|
143
146
|
const code = fs.readFileSync(filePath, 'utf-8')
|
|
144
147
|
const dependencies = this.extractDependencies(code)
|
|
145
148
|
const hasNodeImports = this.hasNodeImports(code)
|
|
149
|
+
const cacheConfig = this.extractCacheConfig(code)
|
|
146
150
|
|
|
147
151
|
this.serverComponents.set(filePath, {
|
|
148
152
|
filePath,
|
|
149
153
|
originalCode: code,
|
|
150
154
|
dependencies,
|
|
151
155
|
hasNodeImports,
|
|
156
|
+
cacheConfig,
|
|
152
157
|
})
|
|
153
158
|
}
|
|
154
159
|
|
|
160
|
+
private extractCacheConfig(code: string): PageCacheConfig | undefined {
|
|
161
|
+
try {
|
|
162
|
+
const cacheConfigRegex = /export\s+const\s+cacheConfig\s*[:=]\s*(\{[^}]*\})/
|
|
163
|
+
const match = code.match(cacheConfigRegex)
|
|
164
|
+
|
|
165
|
+
if (match) {
|
|
166
|
+
const configStr = match[1]
|
|
167
|
+
const cacheControlMatch = configStr.match(/'cache-control'\s*:\s*['"]([^'"]+)['"]/)
|
|
168
|
+
const varyMatch = configStr.match(/'vary'\s*:\s*['"]([^'"]+)['"]/)
|
|
169
|
+
|
|
170
|
+
const config: PageCacheConfig = {}
|
|
171
|
+
if (cacheControlMatch) {
|
|
172
|
+
config['cache-control'] = cacheControlMatch[1]
|
|
173
|
+
}
|
|
174
|
+
if (varyMatch) {
|
|
175
|
+
config.vary = varyMatch[1]
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return Object.keys(config).length > 0 ? config : undefined
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
console.warn(`Failed to extract cache config from component: ${error}`)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return undefined
|
|
186
|
+
}
|
|
187
|
+
|
|
155
188
|
private extractDependencies(code: string): string[] {
|
|
156
189
|
const dependencies: string[] = []
|
|
157
190
|
const importRegex
|
|
@@ -223,8 +256,8 @@ export class ServerComponentBuilder {
|
|
|
223
256
|
)
|
|
224
257
|
}
|
|
225
258
|
|
|
226
|
-
async getTransformedComponentsForDevelopment(): Promise<Array<{ id: string, code: string }>> {
|
|
227
|
-
const components: Array<{ id: string, code: string }> = []
|
|
259
|
+
async getTransformedComponentsForDevelopment(): Promise<Array<{ id: string, code: string, cacheConfig?: PageCacheConfig }>> {
|
|
260
|
+
const components: Array<{ id: string, code: string, cacheConfig?: PageCacheConfig }> = []
|
|
228
261
|
|
|
229
262
|
for (const [filePath, component] of this.serverComponents) {
|
|
230
263
|
const relativePath = path.relative(this.projectRoot, filePath)
|
|
@@ -235,6 +268,7 @@ export class ServerComponentBuilder {
|
|
|
235
268
|
components.push({
|
|
236
269
|
id: componentId,
|
|
237
270
|
code: transformedCode,
|
|
271
|
+
cacheConfig: component.cacheConfig,
|
|
238
272
|
})
|
|
239
273
|
}
|
|
240
274
|
|