rari 0.2.13 → 0.2.14

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/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
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-P4vvSVPV.js";
2
- import { FileRouteGenerator, convertFilePatternToRoutePattern, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-Ph4oyo0B.js";
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, createReactDOMOptimization, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
2
+ import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-CpxpL2un.js";
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 };
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, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-MkYb94pQ.js";
2
+ import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-BrkE-3ny.js";
3
3
  import "./server-build-DaBgiV55.js";
4
4
 
5
- export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createReactDOMOptimization, 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, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
@@ -6,7 +6,6 @@ import path from "node:path";
6
6
  import process$1 from "node:process";
7
7
  import { spawn } from "node:child_process";
8
8
  import * as acorn from "acorn";
9
- import { minify } from "rollup-plugin-esbuild";
10
9
 
11
10
  //#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/constants.js
12
11
  var require_constants$2 = __commonJS({ "../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/constants.js"(exports, module) {
@@ -5743,6 +5742,7 @@ function rari(options = {}) {
5743
5742
  }
5744
5743
  newCode += `
5745
5744
 
5745
+ // HMR acceptance for server components
5746
5746
  if (import.meta.hot) {
5747
5747
  import.meta.hot.accept(() => {
5748
5748
  // Server component updated, no need to reload
@@ -5832,14 +5832,6 @@ if (import.meta.hot) {
5832
5832
  const existingDedupe = Array.isArray(config.resolve.dedupe) ? config.resolve.dedupe : [];
5833
5833
  const toAdd = ["react", "react-dom"];
5834
5834
  config.resolve.dedupe = Array.from(new Set([...existingDedupe || [], ...toAdd]));
5835
- const existingResolveAlias = config.resolve.alias || {};
5836
- config.resolve.alias = {
5837
- ...existingResolveAlias,
5838
- "react-dom/server": "react-dom/server.browser",
5839
- "react-dom$": "react-dom/client",
5840
- "react-dom/cjs/react-dom.production.min.js": "react-dom/client",
5841
- "react-dom/cjs/react-dom.development.js": "react-dom/client"
5842
- };
5843
5835
  const existingAlias = Array.isArray(config.resolve.alias) ? config.resolve.alias : [];
5844
5836
  const aliasFinds = new Set(existingAlias.map((a) => String(a.find)));
5845
5837
  try {
@@ -5888,17 +5880,13 @@ if (import.meta.hot) {
5888
5880
  config.optimizeDeps = config.optimizeDeps || {};
5889
5881
  config.optimizeDeps.include = config.optimizeDeps.include || [];
5890
5882
  if (!config.optimizeDeps.include.includes("react-dom/server")) config.optimizeDeps.include.push("react-dom/server");
5891
- if (!config.optimizeDeps.include.includes("react")) config.optimizeDeps.include.push("react");
5892
- if (!config.optimizeDeps.include.includes("react-dom/client")) config.optimizeDeps.include.push("react-dom/client");
5893
- config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
5894
- if (!config.optimizeDeps.exclude.includes("virtual:rsc-integration")) config.optimizeDeps.exclude.push("virtual:rsc-integration");
5895
5883
  if (command === "build") for (const envName of [
5896
5884
  "rsc",
5897
5885
  "ssr",
5898
5886
  "client"
5899
5887
  ]) {
5900
5888
  const env = config.environments[envName];
5901
- if (env && env.build) env.build.rolldownOptions = env.build.rolldownOptions || {};
5889
+ if (env && env.build) env.build.rollupOptions = env.build.rollupOptions || {};
5902
5890
  }
5903
5891
  config.server = config.server || {};
5904
5892
  config.server.proxy = config.server.proxy || {};
@@ -5924,183 +5912,19 @@ if (import.meta.hot) {
5924
5912
  };
5925
5913
  if (command === "build") {
5926
5914
  config.build = config.build || {};
5927
- config.build.rolldownOptions = config.build.rolldownOptions || {};
5928
- config.build.rolldownOptions.plugins = config.build.rolldownOptions.plugins || [];
5929
- if (Array.isArray(config.build.rolldownOptions.plugins)) {
5930
- config.build.rolldownOptions.plugins.push(minify());
5931
- config.build.rolldownOptions.plugins.push({
5932
- name: "html-css-optimizer",
5933
- generateBundle(options$1, bundle) {
5934
- Object.keys(bundle).forEach((fileName) => {
5935
- const file = bundle[fileName];
5936
- if (file.type === "asset" && fileName.endsWith(".html")) {
5937
- let html = file.source;
5938
- html = html.replace(/<link\s+rel="stylesheet"\s+crossorigin\s+href="([^"]+\.css)"\s*>/g, (match, href) => {
5939
- return `<link rel="preload" as="style" crossorigin href="${href}" fetchpriority="high" onload="this.onload=null;this.rel='stylesheet'">
5940
- <noscript><link rel="stylesheet" crossorigin href="${href}"></noscript>`;
5941
- });
5942
- const scriptMatch = html.match(/<script\s+type="module"\s+crossorigin\s+src="([^"]+)"\s*><\/script>/);
5943
- if (scriptMatch) {
5944
- const mainJsHref = scriptMatch[1];
5945
- html = html.replace(scriptMatch[0], `<link rel="preload" as="script" crossorigin href="${mainJsHref}" fetchpriority="high">
5946
- <script type="module" crossorigin src="${mainJsHref}" fetchpriority="high"><\/script>`);
5947
- }
5948
- file.source = html;
5949
- }
5950
- });
5951
- }
5952
- });
5953
- }
5954
- if (!config.build.rolldownOptions.input) config.build.rolldownOptions.input = { main: "./index.html" };
5955
- config.build.rolldownOptions.output = config.build.rolldownOptions.output || {};
5956
- const outputConfig = Array.isArray(config.build.rolldownOptions.output) ? config.build.rolldownOptions.output[0] || {} : config.build.rolldownOptions.output;
5957
- outputConfig.manualChunks = (id) => {
5958
- if (id.includes("node_modules/react-dom") || id.includes("react-dom/client") || id.includes("react-dom/server") || id.includes("react-dom/")) return "react-dom";
5959
- if ((id.includes("node_modules/react") || id.includes("react/")) && !id.includes("react-dom")) return "react";
5960
- if (id.includes("scheduler") && id.includes("node_modules")) return "scheduler";
5961
- if (id.includes("markdown-it") || id.includes("shiki")) return "vendor";
5962
- if (id.includes("node_modules")) return "vendor";
5963
- };
5964
- config.build.rolldownOptions.treeshake = config.build.rolldownOptions.treeshake || {
5965
- moduleSideEffects: (id) => {
5966
- if (id.includes(".css") || id.includes("polyfill")) return true;
5967
- if (id.includes("react-dom") || id.includes("react") || id.includes("scheduler") || id.includes("react-dom/client") || id.includes("react-dom/server")) return true;
5968
- if (id.includes("node_modules") && !id.includes("react")) return false;
5969
- return true;
5970
- },
5971
- unknownGlobalSideEffects: false
5972
- };
5973
- const existingExternal = config.build.rolldownOptions?.external || [];
5974
- const reactDomExternals = [
5975
- "react-dom/profiling",
5976
- "react-dom/test-utils",
5977
- "react-dom/server",
5978
- "react-dom/server.browser",
5979
- "react-dom/server.node",
5980
- "react/jsx-dev-runtime",
5981
- "scheduler/tracing",
5982
- "scheduler/unstable_mock",
5983
- "react/cjs/react.development.js",
5984
- "react/cjs/react.production.min.js",
5985
- "react-dom/cjs/react-dom.development.js",
5986
- "react-dom/cjs/react-dom.production.min.js",
5987
- "react-dom/src/client/ReactDOMRoot.js",
5988
- "react-dom/src/events/plugins",
5989
- "react-dom/src/shared/HTMLDOMPropertyConfig.js",
5990
- "react-dom/src/shared/DOMPropertyOperations.js"
5991
- ];
5992
- if (Array.isArray(existingExternal)) {
5993
- const external = [...existingExternal];
5994
- external.push(...reactDomExternals.filter((dep) => !external.includes(dep)));
5995
- config.build.rolldownOptions.external = external;
5996
- } else if (typeof existingExternal === "function") {
5997
- const originalExternal = existingExternal;
5998
- config.build.rolldownOptions.external = (id, parentId, isResolved) => {
5999
- if (reactDomExternals.includes(id)) return true;
6000
- return originalExternal(id, parentId, isResolved);
6001
- };
6002
- } else config.build.rolldownOptions.external = [...Array.isArray(existingExternal) ? existingExternal : [existingExternal], ...reactDomExternals].filter(Boolean);
6003
- config.build.minify = true;
6004
- config.build.target = config.build.target || [
6005
- "es2020",
6006
- "edge88",
6007
- "firefox78",
6008
- "chrome87",
6009
- "safari14"
6010
- ];
6011
- config.build.cssMinify = config.build.cssMinify !== false ? "esbuild" : false;
6012
- config.build.cssCodeSplit = true;
6013
- config.build.assetsInlineLimit = 4096;
6014
- config.build.chunkSizeWarningLimit = 1e3;
6015
- config.build.sourcemap = config.build.sourcemap !== void 0 ? config.build.sourcemap : true;
6016
- config.build.terserOptions = config.build.terserOptions || {
6017
- compress: {
6018
- drop_console: true,
6019
- drop_debugger: true,
6020
- pure_funcs: [
6021
- "console.log",
6022
- "console.info",
6023
- "console.debug",
6024
- "console.warn",
6025
- "invariant",
6026
- "warning",
6027
- "__DEV__",
6028
- "ReactDOM.render",
6029
- "ReactDOM.unmountComponentAtNode",
6030
- "ReactDOM.findDOMNode",
6031
- "ReactDOM.createPortal"
6032
- ],
6033
- passes: 3,
6034
- unsafe: true,
6035
- unsafe_comps: true,
6036
- unsafe_Function: true,
6037
- unsafe_math: true,
6038
- unsafe_symbols: true,
6039
- unsafe_methods: true,
6040
- unsafe_proto: true,
6041
- unsafe_regexp: true,
6042
- unsafe_undefined: true,
6043
- dead_code: true,
6044
- side_effects: false
6045
- },
6046
- mangle: {
6047
- safari10: true,
6048
- properties: { regex: /^_/ }
6049
- },
6050
- format: { comments: false }
6051
- };
6052
- outputConfig.format = outputConfig.format || "es";
6053
- outputConfig.minify = true;
6054
- if (Array.isArray(config.build.rolldownOptions.output)) config.build.rolldownOptions.output[0] = outputConfig;
6055
- else config.build.rolldownOptions.output = outputConfig;
5915
+ config.build.rollupOptions = config.build.rollupOptions || {};
5916
+ if (!config.build.rollupOptions.input) config.build.rollupOptions.input = { main: "./index.html" };
6056
5917
  }
6057
5918
  if (config.environments && config.environments.client) {
6058
5919
  if (!config.environments.client.build) config.environments.client.build = {};
6059
- if (!config.environments.client.build.rolldownOptions) config.environments.client.build.rolldownOptions = {};
6060
- if (!config.environments.client.build.rolldownOptions.input) config.environments.client.build.rolldownOptions.input = {};
6061
- if (typeof config.environments.client.build.rolldownOptions.input === "object" && !Array.isArray(config.environments.client.build.rolldownOptions.input)) config.environments.client.build.rolldownOptions.input["client-components"] = "virtual:rsc-client-components";
6062
- config.environments.client.build.rolldownOptions.plugins = config.environments.client.build.rolldownOptions.plugins || [];
6063
- if (Array.isArray(config.environments.client.build.rolldownOptions.plugins)) config.environments.client.build.rolldownOptions.plugins.push(minify());
6064
- config.environments.client.build.minify = true;
6065
- config.environments.client.build.target = config.environments.client.build.target || [
6066
- "es2020",
6067
- "edge88",
6068
- "firefox78",
6069
- "chrome87",
6070
- "safari14"
6071
- ];
6072
- config.environments.client.build.cssMinify = "esbuild";
6073
- config.environments.client.build.cssCodeSplit = true;
6074
- config.environments.client.build.assetsInlineLimit = 4096;
6075
- config.environments.client.build.rolldownOptions.treeshake = {
6076
- moduleSideEffects: false,
6077
- unknownGlobalSideEffects: false
6078
- };
6079
- config.environments.client.build.rolldownOptions.output = config.environments.client.build.rolldownOptions.output || {};
6080
- const clientOutputConfig = Array.isArray(config.environments.client.build.rolldownOptions.output) ? config.environments.client.build.rolldownOptions.output[0] || {} : config.environments.client.build.rolldownOptions.output;
6081
- clientOutputConfig.manualChunks = (id) => {
6082
- if (id.includes("node_modules/react-dom") || id.includes("react-dom/client") || id.includes("react-dom/server") || id.includes("react-dom/")) return "react-dom";
6083
- if ((id.includes("node_modules/react") || id.includes("react/")) && !id.includes("react-dom")) return "react";
6084
- if (id.includes("scheduler") && id.includes("node_modules")) return "scheduler";
6085
- if (id.includes("rari") && (id.includes("router") || id.includes("navigation"))) return "router";
6086
- if (id.includes("markdown-it") || id.includes("shiki")) return "vendor";
6087
- if (id.includes("node_modules")) return "vendor";
6088
- };
6089
- clientOutputConfig.format = clientOutputConfig.format || "es";
6090
- clientOutputConfig.minify = true;
6091
- if (Array.isArray(config.environments.client.build.rolldownOptions.output)) config.environments.client.build.rolldownOptions.output[0] = clientOutputConfig;
6092
- else config.environments.client.build.rolldownOptions.output = clientOutputConfig;
5920
+ if (!config.environments.client.build.rollupOptions) config.environments.client.build.rollupOptions = {};
5921
+ if (!config.environments.client.build.rollupOptions.input) config.environments.client.build.rollupOptions.input = {};
5922
+ if (typeof config.environments.client.build.rollupOptions.input === "object" && !Array.isArray(config.environments.client.build.rollupOptions.input)) config.environments.client.build.rollupOptions.input["client-components"] = "virtual:rsc-client-components";
6093
5923
  }
6094
5924
  return config;
6095
5925
  },
6096
5926
  transform(code, id) {
6097
5927
  if (!/\.(?:tsx?|jsx?)$/.test(id)) return null;
6098
- if (code.includes("react-dom")) {
6099
- code = code.replace(/import\s+ReactDOM\s+from\s+['"]react-dom\/client['"];?/g, "import { createRoot, hydrateRoot } from 'react-dom/client';");
6100
- code = code.replace(/import\s+ReactDOM\s+from\s+['"]react-dom['"];?/g, "import { createRoot, hydrateRoot } from 'react-dom/client';");
6101
- code = code.replace(/ReactDOM\.createRoot/g, "createRoot");
6102
- code = code.replace(/ReactDOM\.hydrateRoot/g, "hydrateRoot");
6103
- }
6104
5928
  const environment = this.environment;
6105
5929
  if (hasTopLevelDirective(code, "use client")) {
6106
5930
  componentTypeCache.set(id, "client");
@@ -6550,6 +6374,7 @@ export const __CLIENT_REFERENCE_REGISTRY__ = clientReferenceRegistry;
6550
6374
  export const __SERVER_REFERENCE_REGISTRY__ = serverReferenceRegistry;
6551
6375
  export const __CLIENT_COMPONENT_REGISTRY__ = clientComponentRegistry;
6552
6376
 
6377
+ // Module map for React Server Components
6553
6378
  export function createClientModuleMap() {
6554
6379
  const moduleMap = {};
6555
6380
 
@@ -6572,6 +6397,7 @@ export function createClientModuleMap() {
6572
6397
  if (id === "virtual:rsc-integration") return `
6573
6398
  import React, { useState, useEffect, Suspense } from 'react';
6574
6399
 
6400
+ // Client component registration for RSC system compatibility
6575
6401
  if (typeof globalThis.__clientComponents === 'undefined') {
6576
6402
  globalThis.__clientComponents = {};
6577
6403
  }
@@ -6589,6 +6415,7 @@ export function registerClientComponent(componentFunction, id, exportName) {
6589
6415
 
6590
6416
  const componentId = componentName;
6591
6417
 
6418
+ // Register in global registry for RSC traversal
6592
6419
  globalThis.__clientComponents[componentId] = {
6593
6420
  id: componentId,
6594
6421
  path: id,
@@ -7349,7 +7176,7 @@ class RscClient {
7349
7176
  const processedChildren = value.map((child, index) => {
7350
7177
  const result = this.reconstructElementFromRscData(child, modules);
7351
7178
  return result;
7352
- }).filter(child => child !== null && child !== undefined);
7179
+ }).filter(child => child !== null && child !== undefined); // Remove null/undefined children
7353
7180
 
7354
7181
  if (processedChildren.length === 0) {
7355
7182
  processed[key] = null;
@@ -7494,6 +7321,7 @@ function ServerComponentWrapper({
7494
7321
  }
7495
7322
 
7496
7323
  function createServerComponentWrapper(componentName, importPath) {
7324
+ // Use a global refresh counter to force re-mounting when components change
7497
7325
  let globalRefreshCounter = 0;
7498
7326
 
7499
7327
  if (typeof window !== 'undefined') {
@@ -7507,6 +7335,7 @@ function createServerComponentWrapper(componentName, importPath) {
7507
7335
  const ServerComponent = (props) => {
7508
7336
  const [mountKey, setMountKey] = useState(globalRefreshCounter);
7509
7337
 
7338
+ // Force re-mount when component is invalidated
7510
7339
  useEffect(() => {
7511
7340
  const handleRscInvalidate = (event) => {
7512
7341
  const detail = event.detail;
@@ -7527,7 +7356,7 @@ function createServerComponentWrapper(componentName, importPath) {
7527
7356
  return React.createElement(Suspense, {
7528
7357
  fallback: null
7529
7358
  }, React.createElement(ServerComponentWrapper, {
7530
- key: componentName + '-' + mountKey,
7359
+ key: componentName + '-' + mountKey, // Force re-mount with key change
7531
7360
  componentId: componentName,
7532
7361
  props: props,
7533
7362
  fallback: null
@@ -7544,7 +7373,9 @@ function createServerComponentWrapper(componentName, importPath) {
7544
7373
  export const fetchServerComponent = (componentId, props) =>
7545
7374
  rscClient.fetchServerComponent(componentId, props);
7546
7375
 
7376
+ // Helper function to check if a file is a server component (client-side)
7547
7377
  function isServerComponent(filePath) {
7378
+ // Simple client-side check based on file path patterns
7548
7379
  return filePath && (
7549
7380
  filePath.includes('ServerWithClient') ||
7550
7381
  filePath.includes('server') ||
@@ -7552,26 +7383,32 @@ function isServerComponent(filePath) {
7552
7383
  );
7553
7384
  }
7554
7385
 
7386
+ // HMR support for RSC cache invalidation
7555
7387
  if (import.meta.hot) {
7388
+ // Listen for Vite's beforeFullReload event for server components
7556
7389
  import.meta.hot.on('vite:beforeFullReload', async (data) => {
7557
7390
  if (data?.path && isServerComponent(data.path)) {
7391
+ // Immediately invalidate cache and trigger re-registration before reload
7558
7392
  await invalidateRscCache({ filePath: data.path, forceReload: true });
7559
7393
  }
7560
7394
  });
7561
7395
 
7562
7396
 
7563
7397
 
7398
+ // Helper function to invalidate RSC cache and trigger component re-registration
7564
7399
  async function invalidateRscCache(data) {
7565
7400
  const filePath = data?.filePath || data;
7566
7401
 
7402
+ // Wait for server to be ready
7567
7403
  const waitForServerReady = async () => {
7568
- for (let i = 0; i < 20; i++) {
7404
+ for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
7569
7405
  try {
7570
7406
  const response = await fetch('/_rsc_status');
7571
7407
  if (response.ok) {
7572
7408
  return true;
7573
7409
  }
7574
7410
  } catch (e) {
7411
+ // Server not ready yet
7575
7412
  }
7576
7413
  await new Promise(resolve => setTimeout(resolve, 100));
7577
7414
  }
@@ -7580,8 +7417,10 @@ if (import.meta.hot) {
7580
7417
 
7581
7418
  const serverReady = await waitForServerReady();
7582
7419
  if (serverReady) {
7420
+ // Clear client-side RSC cache immediately
7583
7421
  rscClient.clearCache();
7584
7422
 
7423
+ // Trigger immediate server component re-registration
7585
7424
  try {
7586
7425
  await fetch('/api/rsc/hmr-register', {
7587
7426
  method: 'POST',
@@ -7593,10 +7432,14 @@ if (import.meta.hot) {
7593
7432
  })
7594
7433
  });
7595
7434
 
7435
+ // Wait a bit for the server to re-register the component
7436
+ // The server now immediately reads and re-registers the component
7596
7437
  await new Promise(resolve => setTimeout(resolve, 300));
7597
7438
  } catch (error) {
7439
+ // Fallback to existing timeout-based approach
7598
7440
  }
7599
7441
 
7442
+ // Trigger re-render of active server components
7600
7443
  if (typeof window !== 'undefined') {
7601
7444
  const event = new CustomEvent('rari:rsc-invalidate', {
7602
7445
  detail: { filePath }
@@ -7666,73 +7509,6 @@ ${registrations.join("\n")}
7666
7509
  const serverBuildPlugin = createServerBuildPlugin(options.serverBuild);
7667
7510
  return [mainPlugin, serverBuildPlugin];
7668
7511
  }
7669
- function createReactDOMOptimization() {
7670
- return { build: {
7671
- rollupOptions: {
7672
- output: { manualChunks: (id) => {
7673
- if (id.includes("node_modules/react-dom") || id.includes("react-dom/client") || id.includes("react-dom/server") || id.includes("react-dom/")) return "react-dom";
7674
- if ((id.includes("node_modules/react") || id.includes("react/")) && !id.includes("react-dom")) return "react";
7675
- if (id.includes("scheduler") && id.includes("node_modules")) return "scheduler";
7676
- if (id.includes("markdown-it") || id.includes("shiki")) return "vendor";
7677
- if (id.includes("node_modules")) return "vendor";
7678
- } },
7679
- treeshake: {
7680
- moduleSideEffects: (id) => {
7681
- if (id.includes(".css") || id.includes("polyfill")) return true;
7682
- if (id.includes("react-dom") || id.includes("react") || id.includes("scheduler") || id.includes("react-dom/client") || id.includes("react-dom/server")) return false;
7683
- return false;
7684
- },
7685
- unknownGlobalSideEffects: false
7686
- }
7687
- },
7688
- minify: "terser",
7689
- target: [
7690
- "es2020",
7691
- "edge88",
7692
- "firefox78",
7693
- "chrome87",
7694
- "safari14"
7695
- ],
7696
- cssMinify: "esbuild",
7697
- sourcemap: false,
7698
- terserOptions: {
7699
- compress: {
7700
- drop_console: true,
7701
- drop_debugger: true,
7702
- pure_funcs: [
7703
- "console.log",
7704
- "console.info",
7705
- "console.debug",
7706
- "console.warn",
7707
- "invariant",
7708
- "warning",
7709
- "__DEV__",
7710
- "ReactDOM.render",
7711
- "ReactDOM.unmountComponentAtNode",
7712
- "ReactDOM.findDOMNode",
7713
- "ReactDOM.createPortal"
7714
- ],
7715
- passes: 3,
7716
- unsafe: true,
7717
- unsafe_comps: true,
7718
- unsafe_Function: true,
7719
- unsafe_math: true,
7720
- unsafe_symbols: true,
7721
- unsafe_methods: true,
7722
- unsafe_proto: true,
7723
- unsafe_regexp: true,
7724
- unsafe_undefined: true,
7725
- dead_code: true,
7726
- side_effects: false
7727
- },
7728
- mangle: {
7729
- safari10: true,
7730
- properties: { regex: /^_/ }
7731
- },
7732
- format: { comments: false }
7733
- }
7734
- } };
7735
- }
7736
7512
  function defineRariConfig(config) {
7737
7513
  return {
7738
7514
  plugins: [rari(), ...config.plugins || []],
@@ -7741,4 +7517,4 @@ function defineRariConfig(config) {
7741
7517
  }
7742
7518
 
7743
7519
  //#endregion
7744
- export { FileRouteGenerator, convertFilePatternToRoutePattern, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
7520
+ export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
@@ -62,53 +62,8 @@ interface RariOptions {
62
62
  serverHandler?: boolean;
63
63
  }
64
64
  declare function rari(options?: RariOptions): Plugin[];
65
- declare function createReactDOMOptimization(): {
66
- build: {
67
- rollupOptions: {
68
- output: {
69
- manualChunks: (id: string) => "react-dom" | "react" | "scheduler" | "vendor" | undefined;
70
- };
71
- treeshake: {
72
- moduleSideEffects: (id: string) => boolean;
73
- unknownGlobalSideEffects: boolean;
74
- };
75
- };
76
- minify: string;
77
- target: string[];
78
- cssMinify: string;
79
- sourcemap: boolean;
80
- terserOptions: {
81
- compress: {
82
- drop_console: boolean;
83
- drop_debugger: boolean;
84
- pure_funcs: string[];
85
- passes: number;
86
- unsafe: boolean;
87
- unsafe_comps: boolean;
88
- unsafe_Function: boolean;
89
- unsafe_math: boolean;
90
- unsafe_symbols: boolean;
91
- unsafe_methods: boolean;
92
- unsafe_proto: boolean;
93
- unsafe_regexp: boolean;
94
- unsafe_undefined: boolean;
95
- dead_code: boolean;
96
- side_effects: boolean;
97
- };
98
- mangle: {
99
- safari10: boolean;
100
- properties: {
101
- regex: RegExp;
102
- };
103
- };
104
- format: {
105
- comments: boolean;
106
- };
107
- };
108
- };
109
- };
110
65
  declare function defineRariConfig(config: UserConfig & {
111
66
  plugins?: Plugin[];
112
67
  }): UserConfig;
113
68
  //#endregion
114
- export { FileRouteGenerator, convertFilePatternToRoutePattern, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
69
+ export { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes };
package/dist/server.d.ts CHANGED
@@ -1,3 +1,3 @@
1
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-P4vvSVPV.js";
2
- import { FileRouteGenerator, convertFilePatternToRoutePattern, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-Ph4oyo0B.js";
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, createReactDOMOptimization, createRouteManifest, defineRariConfig, extractParamNames, findMatchingRoute, generateFileRoutes, getRoutePriority, isDynamicRoute, isPathActive, joinPaths, loadRouteManifest, normalizePathname, parseSearchParams, parseUrl, rari, rariRouter, useNavigation, useParams, usePathname, useRoute, useRouter, useSearchParams, validateRoutes, watchFileRoutes, withRouter };
2
+ import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-CpxpL2un.js";
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 };
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, createReactDOMOptimization, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-MkYb94pQ.js";
2
+ import { FileRouteGenerator, convertFilePatternToRoutePattern, createRouteManifest, defineRariConfig, generateFileRoutes, loadRouteManifest, rari, rariRouter, validateRoutes, watchFileRoutes } from "./server-BrkE-3ny.js";
3
3
  import "./server-build-DaBgiV55.js";
4
4
 
5
- export { FileRouteGenerator, HttpRuntimeClient, Link, Navigate, Outlet, RouteComponent as Route, router_default as RouterProvider, Routes, buildSearchString, buildUrl, convertFilePatternToRoutePattern, createHttpRuntimeClient, createReactDOMOptimization, 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, 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.13",
4
+ "version": "0.2.14",
5
5
  "description": "Runtime Accelerated Rendering Infrastructure (Rari)",
6
6
  "author": "Ryan Skinner",
7
7
  "license": "MIT",
package/src/server.ts CHANGED
@@ -67,4 +67,4 @@ export { createHttpRuntimeClient, HttpRuntimeClient } from './runtime-client'
67
67
 
68
68
  export type { RuntimeClient } from './runtime-client'
69
69
 
70
- export { createReactDOMOptimization, defineRariConfig, rari } from './vite'
70
+ export { defineRariConfig, rari } from './vite'
package/src/vite/index.ts CHANGED
@@ -6,7 +6,6 @@ import fs from 'node:fs'
6
6
  import path from 'node:path'
7
7
  import process from 'node:process'
8
8
  import * as acorn from 'acorn'
9
- import { minify } from 'rollup-plugin-esbuild'
10
9
  import { createServerBuildPlugin } from './server-build'
11
10
 
12
11
  interface RariOptions {
@@ -228,6 +227,7 @@ export function rari(options: RariOptions = {}): Plugin[] {
228
227
 
229
228
  newCode += `
230
229
 
230
+ // HMR acceptance for server components
231
231
  if (import.meta.hot) {
232
232
  import.meta.hot.accept(() => {
233
233
  // Server component updated, no need to reload
@@ -380,15 +380,6 @@ if (import.meta.hot) {
380
380
  new Set([...(existingDedupe || []), ...toAdd]),
381
381
  )
382
382
 
383
- const existingResolveAlias = (config.resolve as any).alias || {};
384
- (config.resolve as any).alias = {
385
- ...existingResolveAlias,
386
- 'react-dom/server': 'react-dom/server.browser',
387
- 'react-dom$': 'react-dom/client',
388
- 'react-dom/cjs/react-dom.production.min.js': 'react-dom/client',
389
- 'react-dom/cjs/react-dom.development.js': 'react-dom/client',
390
- }
391
-
392
383
  const existingAlias: Array<{
393
384
  find: string | RegExp
394
385
  replacement: string
@@ -419,7 +410,7 @@ if (import.meta.hot) {
419
410
  })
420
411
  }
421
412
  }
422
- catch { }
413
+ catch {}
423
414
  if (!aliasFinds.has('react')) {
424
415
  aliasesToAppend.push({ find: 'react', replacement: reactPath })
425
416
  }
@@ -436,7 +427,7 @@ if (import.meta.hot) {
436
427
  ]
437
428
  }
438
429
  }
439
- catch { }
430
+ catch {}
440
431
 
441
432
  config.environments = config.environments || {}
442
433
 
@@ -466,22 +457,12 @@ if (import.meta.hot) {
466
457
  if (!config.optimizeDeps.include.includes('react-dom/server')) {
467
458
  config.optimizeDeps.include.push('react-dom/server')
468
459
  }
469
- if (!config.optimizeDeps.include.includes('react')) {
470
- config.optimizeDeps.include.push('react')
471
- }
472
- if (!config.optimizeDeps.include.includes('react-dom/client')) {
473
- config.optimizeDeps.include.push('react-dom/client')
474
- }
475
- config.optimizeDeps.exclude = config.optimizeDeps.exclude || []
476
- if (!config.optimizeDeps.exclude.includes('virtual:rsc-integration')) {
477
- config.optimizeDeps.exclude.push('virtual:rsc-integration')
478
- }
479
460
 
480
461
  if (command === 'build') {
481
462
  for (const envName of ['rsc', 'ssr', 'client']) {
482
463
  const env = config.environments[envName]
483
464
  if (env && env.build) {
484
- env.build.rolldownOptions = env.build.rolldownOptions || {}
465
+ env.build.rollupOptions = env.build.rollupOptions || {}
485
466
  }
486
467
  }
487
468
  }
@@ -517,334 +498,38 @@ if (import.meta.hot) {
517
498
 
518
499
  if (command === 'build') {
519
500
  config.build = config.build || {}
520
- config.build.rolldownOptions = config.build.rolldownOptions || {}
521
-
522
- config.build.rolldownOptions.plugins
523
- = config.build.rolldownOptions.plugins || []
524
- if (Array.isArray(config.build.rolldownOptions.plugins)) {
525
- config.build.rolldownOptions.plugins.push(minify())
526
-
527
- config.build.rolldownOptions.plugins.push({
528
- name: 'html-css-optimizer',
529
- generateBundle(options, bundle) {
530
- Object.keys(bundle).forEach((fileName) => {
531
- const file = bundle[fileName]
532
- if (file.type === 'asset' && fileName.endsWith('.html')) {
533
- let html = file.source as string
534
-
535
- html = html.replace(
536
- /<link\s+rel="stylesheet"\s+crossorigin\s+href="([^"]+\.css)"\s*>/g,
537
- (match, href) => {
538
- return `<link rel="preload" as="style" crossorigin href="${href}" fetchpriority="high" onload="this.onload=null;this.rel='stylesheet'">
539
- <noscript><link rel="stylesheet" crossorigin href="${href}"></noscript>`
540
- },
541
- )
542
-
543
- const scriptMatch = html.match(
544
- /<script\s+type="module"\s+crossorigin\s+src="([^"]+)"\s*><\/script>/,
545
- )
546
- if (scriptMatch) {
547
- const mainJsHref = scriptMatch[1]
548
- html = html.replace(
549
- scriptMatch[0],
550
- `<link rel="preload" as="script" crossorigin href="${mainJsHref}" fetchpriority="high">
551
- <script type="module" crossorigin src="${mainJsHref}" fetchpriority="high"></script>`,
552
- )
553
- }
501
+ config.build.rollupOptions = config.build.rollupOptions || {}
554
502
 
555
- file.source = html
556
- }
557
- })
558
- },
559
- })
560
- }
561
-
562
- if (!config.build.rolldownOptions.input) {
563
- config.build.rolldownOptions.input = {
503
+ if (!config.build.rollupOptions.input) {
504
+ config.build.rollupOptions.input = {
564
505
  main: './index.html',
565
506
  }
566
507
  }
567
-
568
- config.build.rolldownOptions.output
569
- = config.build.rolldownOptions.output || {}
570
- const outputConfig = Array.isArray(config.build.rolldownOptions.output)
571
- ? config.build.rolldownOptions.output[0] || {}
572
- : config.build.rolldownOptions.output
573
-
574
- outputConfig.manualChunks = (id) => {
575
- if (
576
- id.includes('node_modules/react-dom')
577
- || id.includes('react-dom/client')
578
- || id.includes('react-dom/server')
579
- || id.includes('react-dom/')
580
- ) {
581
- return 'react-dom'
582
- }
583
- if (
584
- (id.includes('node_modules/react') || id.includes('react/'))
585
- && !id.includes('react-dom')
586
- ) {
587
- return 'react'
588
- }
589
- if (id.includes('scheduler') && id.includes('node_modules')) {
590
- return 'scheduler'
591
- }
592
- if (id.includes('markdown-it') || id.includes('shiki')) {
593
- return 'vendor'
594
- }
595
- if (id.includes('node_modules')) {
596
- return 'vendor'
597
- }
598
- }
599
-
600
- config.build.rolldownOptions.treeshake = config.build.rolldownOptions
601
- .treeshake || {
602
- moduleSideEffects: (id) => {
603
- if (id.includes('.css') || id.includes('polyfill')) {
604
- return true
605
- }
606
- // Preserve side effects for React modules to prevent import issues
607
- if (
608
- id.includes('react-dom')
609
- || id.includes('react')
610
- || id.includes('scheduler')
611
- || id.includes('react-dom/client')
612
- || id.includes('react-dom/server')
613
- ) {
614
- return true
615
- }
616
- // Only disable side effects for specific safe modules
617
- if (id.includes('node_modules') && !id.includes('react')) {
618
- return false
619
- }
620
- return true
621
- },
622
- unknownGlobalSideEffects: false,
623
- }
624
-
625
- const existingExternal = config.build.rolldownOptions?.external || []
626
- const reactDomExternals = [
627
- 'react-dom/profiling',
628
- 'react-dom/test-utils',
629
- 'react-dom/server',
630
- 'react-dom/server.browser',
631
- 'react-dom/server.node',
632
- 'react/jsx-dev-runtime',
633
- 'scheduler/tracing',
634
- 'scheduler/unstable_mock',
635
- 'react/cjs/react.development.js',
636
- 'react/cjs/react.production.min.js',
637
- 'react-dom/cjs/react-dom.development.js',
638
- 'react-dom/cjs/react-dom.production.min.js',
639
- 'react-dom/src/client/ReactDOMRoot.js',
640
- 'react-dom/src/events/plugins',
641
- 'react-dom/src/shared/HTMLDOMPropertyConfig.js',
642
- 'react-dom/src/shared/DOMPropertyOperations.js',
643
- ]
644
-
645
- if (Array.isArray(existingExternal)) {
646
- const external = [...existingExternal]
647
- external.push(
648
- ...reactDomExternals.filter(dep => !external.includes(dep)),
649
- )
650
- config.build.rolldownOptions.external = external
651
- }
652
- else if (typeof existingExternal === 'function') {
653
- const originalExternal = existingExternal
654
- config.build.rolldownOptions.external = (
655
- id,
656
- parentId,
657
- isResolved,
658
- ) => {
659
- if (reactDomExternals.includes(id))
660
- return true
661
- return originalExternal(id, parentId, isResolved)
662
- }
663
- }
664
- else {
665
- config.build.rolldownOptions.external = [
666
- ...(Array.isArray(existingExternal)
667
- ? existingExternal
668
- : [existingExternal]),
669
- ...reactDomExternals,
670
- ].filter(Boolean)
671
- }
672
-
673
- config.build.minify = true
674
- config.build.target = config.build.target || [
675
- 'es2020',
676
- 'edge88',
677
- 'firefox78',
678
- 'chrome87',
679
- 'safari14',
680
- ]
681
- config.build.cssMinify
682
- = config.build.cssMinify !== false ? 'esbuild' : false
683
- config.build.cssCodeSplit = true
684
- config.build.assetsInlineLimit = 4096
685
- config.build.chunkSizeWarningLimit = 1000
686
- config.build.sourcemap
687
- = config.build.sourcemap !== undefined ? config.build.sourcemap : true
688
-
689
- config.build.terserOptions = config.build.terserOptions || {
690
- compress: {
691
- drop_console: true,
692
- drop_debugger: true,
693
- pure_funcs: [
694
- 'console.log',
695
- 'console.info',
696
- 'console.debug',
697
- 'console.warn',
698
- 'invariant',
699
- 'warning',
700
- '__DEV__',
701
- 'ReactDOM.render',
702
- 'ReactDOM.unmountComponentAtNode',
703
- 'ReactDOM.findDOMNode',
704
- 'ReactDOM.createPortal',
705
- ],
706
- passes: 3,
707
- unsafe: true,
708
- unsafe_comps: true,
709
- unsafe_Function: true,
710
- unsafe_math: true,
711
- unsafe_symbols: true,
712
- unsafe_methods: true,
713
- unsafe_proto: true,
714
- unsafe_regexp: true,
715
- unsafe_undefined: true,
716
- dead_code: true,
717
- side_effects: false,
718
- },
719
- mangle: {
720
- safari10: true,
721
- properties: {
722
- regex: /^_/,
723
- },
724
- },
725
- format: {
726
- comments: false,
727
- },
728
- }
729
-
730
- outputConfig.format = outputConfig.format || 'es'
731
- outputConfig.minify = true
732
-
733
- if (Array.isArray(config.build.rolldownOptions.output)) {
734
- config.build.rolldownOptions.output[0] = outputConfig
735
- }
736
- else {
737
- config.build.rolldownOptions.output = outputConfig
738
- }
739
508
  }
740
509
 
741
510
  if (config.environments && config.environments.client) {
742
511
  if (!config.environments.client.build) {
743
512
  config.environments.client.build = {}
744
513
  }
745
- if (!config.environments.client.build.rolldownOptions) {
746
- config.environments.client.build.rolldownOptions = {}
514
+ if (!config.environments.client.build.rollupOptions) {
515
+ config.environments.client.build.rollupOptions = {}
747
516
  }
748
- if (!config.environments.client.build.rolldownOptions.input) {
749
- config.environments.client.build.rolldownOptions.input = {}
517
+ if (!config.environments.client.build.rollupOptions.input) {
518
+ config.environments.client.build.rollupOptions.input = {}
750
519
  }
751
520
 
752
521
  if (
753
- typeof config.environments.client.build.rolldownOptions.input
522
+ typeof config.environments.client.build.rollupOptions.input
754
523
  === 'object'
755
- && !Array.isArray(config.environments.client.build.rolldownOptions.input)
524
+ && !Array.isArray(config.environments.client.build.rollupOptions.input)
756
525
  ) {
757
526
  (
758
- config.environments.client.build.rolldownOptions.input as Record<
527
+ config.environments.client.build.rollupOptions.input as Record<
759
528
  string,
760
529
  string
761
530
  >
762
531
  )['client-components'] = 'virtual:rsc-client-components'
763
532
  }
764
-
765
- config.environments.client.build.rolldownOptions.plugins
766
- = config.environments.client.build.rolldownOptions.plugins || []
767
- if (
768
- Array.isArray(
769
- config.environments.client.build.rolldownOptions.plugins,
770
- )
771
- ) {
772
- config.environments.client.build.rolldownOptions.plugins.push(
773
- minify(),
774
- )
775
- }
776
-
777
- config.environments.client.build.minify = true
778
- config.environments.client.build.target = config.environments.client
779
- .build
780
- .target || [
781
- 'es2020',
782
- 'edge88',
783
- 'firefox78',
784
- 'chrome87',
785
- 'safari14',
786
- ]
787
- config.environments.client.build.cssMinify = 'esbuild'
788
- config.environments.client.build.cssCodeSplit = true
789
- config.environments.client.build.assetsInlineLimit = 4096
790
- config.environments.client.build.rolldownOptions.treeshake = {
791
- moduleSideEffects: false,
792
- unknownGlobalSideEffects: false,
793
- }
794
-
795
- config.environments.client.build.rolldownOptions.output
796
- = config.environments.client.build.rolldownOptions.output || {}
797
- const clientOutputConfig = Array.isArray(
798
- config.environments.client.build.rolldownOptions.output,
799
- )
800
- ? config.environments.client.build.rolldownOptions.output[0] || {}
801
- : config.environments.client.build.rolldownOptions.output
802
-
803
- clientOutputConfig.manualChunks = (id) => {
804
- if (
805
- id.includes('node_modules/react-dom')
806
- || id.includes('react-dom/client')
807
- || id.includes('react-dom/server')
808
- || id.includes('react-dom/')
809
- ) {
810
- return 'react-dom'
811
- }
812
- if (
813
- (id.includes('node_modules/react') || id.includes('react/'))
814
- && !id.includes('react-dom')
815
- ) {
816
- return 'react'
817
- }
818
- if (id.includes('scheduler') && id.includes('node_modules')) {
819
- return 'scheduler'
820
- }
821
- if (
822
- id.includes('rari')
823
- && (id.includes('router') || id.includes('navigation'))
824
- ) {
825
- return 'router'
826
- }
827
- if (id.includes('markdown-it') || id.includes('shiki')) {
828
- return 'vendor'
829
- }
830
- if (id.includes('node_modules')) {
831
- return 'vendor'
832
- }
833
- }
834
-
835
- clientOutputConfig.format = clientOutputConfig.format || 'es'
836
- clientOutputConfig.minify = true
837
-
838
- if (
839
- Array.isArray(config.environments.client.build.rolldownOptions.output)
840
- ) {
841
- config.environments.client.build.rolldownOptions.output[0]
842
- = clientOutputConfig
843
- }
844
- else {
845
- config.environments.client.build.rolldownOptions.output
846
- = clientOutputConfig
847
- }
848
533
  }
849
534
 
850
535
  return config
@@ -855,20 +540,6 @@ if (import.meta.hot) {
855
540
  return null
856
541
  }
857
542
 
858
- if (code.includes('react-dom')) {
859
- code = code.replace(
860
- /import\s+ReactDOM\s+from\s+['"]react-dom\/client['"];?/g,
861
- 'import { createRoot, hydrateRoot } from \'react-dom/client\';',
862
- )
863
- code = code.replace(
864
- /import\s+ReactDOM\s+from\s+['"]react-dom['"];?/g,
865
- 'import { createRoot, hydrateRoot } from \'react-dom/client\';',
866
- )
867
-
868
- code = code.replace(/ReactDOM\.createRoot/g, 'createRoot')
869
- code = code.replace(/ReactDOM\.hydrateRoot/g, 'hydrateRoot')
870
- }
871
-
872
543
  const environment = (this as any).environment
873
544
 
874
545
  if (hasTopLevelDirective(code, 'use client')) {
@@ -1459,7 +1130,7 @@ const ${componentName} = registerClientReference(
1459
1130
  return { id, external: true }
1460
1131
  }
1461
1132
  }
1462
- catch { }
1133
+ catch {}
1463
1134
  }
1464
1135
 
1465
1136
  return null
@@ -1584,6 +1255,7 @@ export const __CLIENT_REFERENCE_REGISTRY__ = clientReferenceRegistry;
1584
1255
  export const __SERVER_REFERENCE_REGISTRY__ = serverReferenceRegistry;
1585
1256
  export const __CLIENT_COMPONENT_REGISTRY__ = clientComponentRegistry;
1586
1257
 
1258
+ // Module map for React Server Components
1587
1259
  export function createClientModuleMap() {
1588
1260
  const moduleMap = {};
1589
1261
 
@@ -1609,6 +1281,7 @@ export function createClientModuleMap() {
1609
1281
  return `
1610
1282
  import React, { useState, useEffect, Suspense } from 'react';
1611
1283
 
1284
+ // Client component registration for RSC system compatibility
1612
1285
  if (typeof globalThis.__clientComponents === 'undefined') {
1613
1286
  globalThis.__clientComponents = {};
1614
1287
  }
@@ -1626,6 +1299,7 @@ export function registerClientComponent(componentFunction, id, exportName) {
1626
1299
 
1627
1300
  const componentId = componentName;
1628
1301
 
1302
+ // Register in global registry for RSC traversal
1629
1303
  globalThis.__clientComponents[componentId] = {
1630
1304
  id: componentId,
1631
1305
  path: id,
@@ -2386,7 +2060,7 @@ class RscClient {
2386
2060
  const processedChildren = value.map((child, index) => {
2387
2061
  const result = this.reconstructElementFromRscData(child, modules);
2388
2062
  return result;
2389
- }).filter(child => child !== null && child !== undefined);
2063
+ }).filter(child => child !== null && child !== undefined); // Remove null/undefined children
2390
2064
 
2391
2065
  if (processedChildren.length === 0) {
2392
2066
  processed[key] = null;
@@ -2531,6 +2205,7 @@ function ServerComponentWrapper({
2531
2205
  }
2532
2206
 
2533
2207
  function createServerComponentWrapper(componentName, importPath) {
2208
+ // Use a global refresh counter to force re-mounting when components change
2534
2209
  let globalRefreshCounter = 0;
2535
2210
 
2536
2211
  if (typeof window !== 'undefined') {
@@ -2544,6 +2219,7 @@ function createServerComponentWrapper(componentName, importPath) {
2544
2219
  const ServerComponent = (props) => {
2545
2220
  const [mountKey, setMountKey] = useState(globalRefreshCounter);
2546
2221
 
2222
+ // Force re-mount when component is invalidated
2547
2223
  useEffect(() => {
2548
2224
  const handleRscInvalidate = (event) => {
2549
2225
  const detail = event.detail;
@@ -2564,7 +2240,7 @@ function createServerComponentWrapper(componentName, importPath) {
2564
2240
  return React.createElement(Suspense, {
2565
2241
  fallback: null
2566
2242
  }, React.createElement(ServerComponentWrapper, {
2567
- key: componentName + '-' + mountKey,
2243
+ key: componentName + '-' + mountKey, // Force re-mount with key change
2568
2244
  componentId: componentName,
2569
2245
  props: props,
2570
2246
  fallback: null
@@ -2581,7 +2257,9 @@ function createServerComponentWrapper(componentName, importPath) {
2581
2257
  export const fetchServerComponent = (componentId, props) =>
2582
2258
  rscClient.fetchServerComponent(componentId, props);
2583
2259
 
2260
+ // Helper function to check if a file is a server component (client-side)
2584
2261
  function isServerComponent(filePath) {
2262
+ // Simple client-side check based on file path patterns
2585
2263
  return filePath && (
2586
2264
  filePath.includes('ServerWithClient') ||
2587
2265
  filePath.includes('server') ||
@@ -2589,26 +2267,32 @@ function isServerComponent(filePath) {
2589
2267
  );
2590
2268
  }
2591
2269
 
2270
+ // HMR support for RSC cache invalidation
2592
2271
  if (import.meta.hot) {
2272
+ // Listen for Vite's beforeFullReload event for server components
2593
2273
  import.meta.hot.on('vite:beforeFullReload', async (data) => {
2594
2274
  if (data?.path && isServerComponent(data.path)) {
2275
+ // Immediately invalidate cache and trigger re-registration before reload
2595
2276
  await invalidateRscCache({ filePath: data.path, forceReload: true });
2596
2277
  }
2597
2278
  });
2598
2279
 
2599
2280
 
2600
2281
 
2282
+ // Helper function to invalidate RSC cache and trigger component re-registration
2601
2283
  async function invalidateRscCache(data) {
2602
2284
  const filePath = data?.filePath || data;
2603
2285
 
2286
+ // Wait for server to be ready
2604
2287
  const waitForServerReady = async () => {
2605
- for (let i = 0; i < 20; i++) {
2288
+ for (let i = 0; i < 20; i++) { // Try for up to 2 seconds
2606
2289
  try {
2607
2290
  const response = await fetch('/_rsc_status');
2608
2291
  if (response.ok) {
2609
2292
  return true;
2610
2293
  }
2611
2294
  } catch (e) {
2295
+ // Server not ready yet
2612
2296
  }
2613
2297
  await new Promise(resolve => setTimeout(resolve, 100));
2614
2298
  }
@@ -2617,8 +2301,10 @@ if (import.meta.hot) {
2617
2301
 
2618
2302
  const serverReady = await waitForServerReady();
2619
2303
  if (serverReady) {
2304
+ // Clear client-side RSC cache immediately
2620
2305
  rscClient.clearCache();
2621
2306
 
2307
+ // Trigger immediate server component re-registration
2622
2308
  try {
2623
2309
  await fetch('/api/rsc/hmr-register', {
2624
2310
  method: 'POST',
@@ -2630,10 +2316,14 @@ if (import.meta.hot) {
2630
2316
  })
2631
2317
  });
2632
2318
 
2319
+ // Wait a bit for the server to re-register the component
2320
+ // The server now immediately reads and re-registers the component
2633
2321
  await new Promise(resolve => setTimeout(resolve, 300));
2634
2322
  } catch (error) {
2323
+ // Fallback to existing timeout-based approach
2635
2324
  }
2636
2325
 
2326
+ // Trigger re-render of active server components
2637
2327
  if (typeof window !== 'undefined') {
2638
2328
  const event = new CustomEvent('rari:rsc-invalidate', {
2639
2329
  detail: { filePath }
@@ -2718,108 +2408,6 @@ ${registrations.join('\n')}
2718
2408
  return [mainPlugin, serverBuildPlugin]
2719
2409
  }
2720
2410
 
2721
- export function createReactDOMOptimization() {
2722
- return {
2723
- build: {
2724
- rollupOptions: {
2725
- output: {
2726
- manualChunks: (id: string) => {
2727
- if (
2728
- id.includes('node_modules/react-dom')
2729
- || id.includes('react-dom/client')
2730
- || id.includes('react-dom/server')
2731
- || id.includes('react-dom/')
2732
- ) {
2733
- return 'react-dom'
2734
- }
2735
-
2736
- if (
2737
- (id.includes('node_modules/react') || id.includes('react/'))
2738
- && !id.includes('react-dom')
2739
- ) {
2740
- return 'react'
2741
- }
2742
-
2743
- if (id.includes('scheduler') && id.includes('node_modules')) {
2744
- return 'scheduler'
2745
- }
2746
-
2747
- if (id.includes('markdown-it') || id.includes('shiki')) {
2748
- return 'vendor'
2749
- }
2750
-
2751
- if (id.includes('node_modules')) {
2752
- return 'vendor'
2753
- }
2754
- },
2755
- },
2756
- treeshake: {
2757
- moduleSideEffects: (id: string) => {
2758
- if (id.includes('.css') || id.includes('polyfill')) {
2759
- return true
2760
- }
2761
- if (
2762
- id.includes('react-dom')
2763
- || id.includes('react')
2764
- || id.includes('scheduler')
2765
- || id.includes('react-dom/client')
2766
- || id.includes('react-dom/server')
2767
- ) {
2768
- return false
2769
- }
2770
- return false
2771
- },
2772
- unknownGlobalSideEffects: false,
2773
- },
2774
- },
2775
- minify: 'terser',
2776
- target: ['es2020', 'edge88', 'firefox78', 'chrome87', 'safari14'],
2777
- cssMinify: 'esbuild',
2778
- sourcemap: false,
2779
- terserOptions: {
2780
- compress: {
2781
- drop_console: true,
2782
- drop_debugger: true,
2783
- pure_funcs: [
2784
- 'console.log',
2785
- 'console.info',
2786
- 'console.debug',
2787
- 'console.warn',
2788
- 'invariant',
2789
- 'warning',
2790
- '__DEV__',
2791
- 'ReactDOM.render',
2792
- 'ReactDOM.unmountComponentAtNode',
2793
- 'ReactDOM.findDOMNode',
2794
- 'ReactDOM.createPortal',
2795
- ],
2796
- passes: 3,
2797
- unsafe: true,
2798
- unsafe_comps: true,
2799
- unsafe_Function: true,
2800
- unsafe_math: true,
2801
- unsafe_symbols: true,
2802
- unsafe_methods: true,
2803
- unsafe_proto: true,
2804
- unsafe_regexp: true,
2805
- unsafe_undefined: true,
2806
- dead_code: true,
2807
- side_effects: false,
2808
- },
2809
- mangle: {
2810
- safari10: true,
2811
- properties: {
2812
- regex: /^_/,
2813
- },
2814
- },
2815
- format: {
2816
- comments: false,
2817
- },
2818
- },
2819
- },
2820
- }
2821
- }
2822
-
2823
2411
  export function defineRariConfig(
2824
2412
  config: UserConfig & { plugins?: Plugin[] },
2825
2413
  ): UserConfig {