diff --git a/docs/app/components/ui/Sparkles.tsx b/docs/app/components/ui/Sparkles.tsx index faf6ccc6..73060dac 100644 --- a/docs/app/components/ui/Sparkles.tsx +++ b/docs/app/components/ui/Sparkles.tsx @@ -39,7 +39,6 @@ export const SparklesCore = (props: ParticlesProps) => { const particlesLoaded = async (container?: Container) => { if (container) { - console.log(container) controls.start({ opacity: 1, transition: { diff --git a/package-lock.json b/package-lock.json index 9663b765..46afb9dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-router-devtools", - "version": "1.1.8", + "version": "5.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-router-devtools", - "version": "1.1.8", + "version": "5.0.0", "license": "MIT", "workspaces": [ ".", @@ -29,7 +29,8 @@ "react-d3-tree": "^3.6.4", "react-diff-viewer-continued": "^4.0.5", "react-hotkeys-hook": "^4.6.1", - "react-tooltip": "^5.28.0" + "react-tooltip": "^5.28.0", + "tailwind-merge": "^3.0.1" }, "devDependencies": { "@biomejs/biome": "1.9.4", @@ -41,8 +42,6 @@ "@types/babel__core": "^7.20.5", "@types/beautify": "^0.0.3", "@types/node": "^22.12.0", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", "@vitest/coverage-v8": "^3.0.4", "@vitest/ui": "^3.0.4", "autoprefixer": "^10.4.20", @@ -55,13 +54,13 @@ "npm-run-all": "^4.1.5", "postcss": "^8.5.1", "prompt": "^1.3.0", - "tailwind-merge": "^3.0.1", "tailwindcss": "^3.4.0", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.6", "tsx": "^4.19.2", "typescript": "^5.7.3", "vite": "^6.0.11", + "vite-node": "^3.1.2", "vitest": "^3.0.4" }, "optionalDependencies": { @@ -70,6 +69,8 @@ "@rollup/rollup-linux-x64-gnu": "^4.32.1" }, "peerDependencies": { + "@types/react": ">=17", + "@types/react-dom": ">=17", "react": ">=17", "react-dom": ">=17", "react-router": ">=7.0.0", @@ -2354,6 +2355,28 @@ "node": ">=10" } }, + "node_modules/@react-router/dev/node_modules/vite-node": { + "version": "3.0.0-beta.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.0-beta.2.tgz", + "integrity": "sha512-ofTf6cfRdL30Wbl9n/BX81EyIR5s4PReLmSurrxQ+koLaWUNOEo8E0lCM53OJkb8vpa2URM2nSrxZsIFyvY1rg==", + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@react-router/express": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.1.4.tgz", @@ -3135,7 +3158,6 @@ "version": "19.0.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz", "integrity": "sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==", - "devOptional": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -10966,7 +10988,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.1.tgz", "integrity": "sha512-AvzE8FmSoXC7nC+oU5GlQJbip2UO7tmOhOfQyOmPhrStOGXHU08j8mZEHZ4BmCqY5dWTCo4ClWkNyRNx1wpT0g==", - "dev": true, "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -12438,14 +12459,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.0-beta.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.0-beta.2.tgz", - "integrity": "sha512-ofTf6cfRdL30Wbl9n/BX81EyIR5s4PReLmSurrxQ+koLaWUNOEo8E0lCM53OJkb8vpa2URM2nSrxZsIFyvY1rg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", + "dev": true, + "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -12458,6 +12481,13 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-node/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/vite-plugin-inspect": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-10.1.0.tgz", diff --git a/package.json b/package.json index 9a9ea8c5..a7cd46de 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "react-router-devtools", "description": "Devtools for React Router - debug, trace, find hydration errors, catch bugs and inspect server/client data with react-router-devtools", "author": "Alem Tuzlak", - "version": "1.1.10", + "version": "5.0.0", "license": "MIT", "keywords": [ "react-router", @@ -19,7 +19,6 @@ ], "private": false, "type": "module", - "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { @@ -105,6 +104,8 @@ "peerDependencies": { "react": ">=17", "react-dom": ">=17", + "@types/react": ">=17", + "@types/react-dom": ">=17", "react-router": ">=7.0.0", "vite": ">=5.0.0 || >=6.0.0" }, @@ -118,8 +119,6 @@ "@types/babel__core": "^7.20.5", "@types/beautify": "^0.0.3", "@types/node": "^22.12.0", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", "@vitest/coverage-v8": "^3.0.4", "@vitest/ui": "^3.0.4", "autoprefixer": "^10.4.20", @@ -132,13 +131,13 @@ "npm-run-all": "^4.1.5", "postcss": "^8.5.1", "prompt": "^1.3.0", - "tailwind-merge": "^3.0.1", "tailwindcss": "^3.4.0", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.6", "tsx": "^4.19.2", "typescript": "^5.7.3", "vite": "^6.0.11", + "vite-node": "^3.1.2", "vitest": "^3.0.4" }, "dependencies": { @@ -158,7 +157,8 @@ "react-d3-tree": "^3.6.4", "react-diff-viewer-continued": "^4.0.5", "react-hotkeys-hook": "^4.6.1", - "react-tooltip": "^5.28.0" + "react-tooltip": "^5.28.0", + "tailwind-merge": "^3.0.1" }, "optionalDependencies": { "@biomejs/cli-darwin-arm64": "^1.9.4", diff --git a/src/client/components/RouteInfo.tsx b/src/client/components/RouteInfo.tsx index cb42eb6d..d5847d93 100644 --- a/src/client/components/RouteInfo.tsx +++ b/src/client/components/RouteInfo.tsx @@ -3,6 +3,7 @@ import type { MouseEvent } from "react" import { Link } from "react-router" import { useSettingsContext } from "../context/useRDTContext.js" import { type ExtendedRoute, constructRoutePath } from "../utils/routing.js" +import { findParentErrorBoundary } from "../utils/sanitize.js" import { Input } from "./Input.js" import { Tag } from "./Tag.js" import { Icon } from "./icon/Icon.js" @@ -14,39 +15,49 @@ interface RouteInfoProps { onClose?: () => void } -export const RouteInfo = ({ route, className, openNewRoute, onClose }: RouteInfoProps) => { +export const RouteInfo = ({ route: routeToUse, className, openNewRoute, onClose }: RouteInfoProps) => { + const route = window.__reactRouterManifest?.routes[routeToUse.id] || routeToUse const { settings, setSettings } = useSettingsContext() const { routeWildcards, routeViewMode } = settings - const { hasWildcard, path, pathToOpen } = constructRoutePath(route, routeWildcards) + const { hasWildcard, path, pathToOpen } = constructRoutePath(routeToUse, routeWildcards) const isTreeView = routeViewMode === "tree" - const hasParentErrorBoundary = route.errorBoundary.errorBoundaryId && route.errorBoundary.errorBoundaryId !== route.id - const hasErrorBoundary = route.errorBoundary.hasErrorBoundary + const { hasErrorBoundary, errorBoundaryId } = findParentErrorBoundary(route) + const hasParentErrorBoundary = errorBoundaryId && errorBoundaryId !== route.id + return (
{isTreeView && ( <> -

{route.url}

+

{routeToUse.url}


- Path: {path} + Path: + {path}

- Url: {pathToOpen} + Url: {pathToOpen}

)}
Route file: - {route.id} + {route.module ?? routeToUse.file}
+
Components contained in the route: -
+
Loader + + Client Loader + + + Client Action + Action @@ -60,9 +71,7 @@ export const RouteInfo = ({ route, className, openNewRoute, onClose }: RouteInfo
{hasErrorBoundary ? (
- {hasParentErrorBoundary - ? `Covered by parent ErrorBoundary located in: ${route.errorBoundary.errorBoundaryId}` - : ""} + {hasParentErrorBoundary ? `Covered by parent ErrorBoundary located in: ${errorBoundaryId}` : ""}
) : null}
@@ -70,7 +79,7 @@ export const RouteInfo = ({ route, className, openNewRoute, onClose }: RouteInfo <>

Wildcard parameters:

- {route.url + {routeToUse.url .split("/") .filter((p) => p.startsWith(":")) .map((param) => ( diff --git a/src/client/tabs/RoutesTab.tsx b/src/client/tabs/RoutesTab.tsx index 5b96daaf..b5831495 100644 --- a/src/client/tabs/RoutesTab.tsx +++ b/src/client/tabs/RoutesTab.tsx @@ -1,4 +1,4 @@ -import { type MouseEvent, useState } from "react" +import { type MouseEvent, useEffect, useState } from "react" import { useMatches, useNavigate } from "react-router" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../components/Accordion.js" import { NewRouteForm } from "../components/NewRouteForm.js" @@ -22,7 +22,7 @@ const RoutesTab = () => { const { detachedWindow } = useDetachedWindowControls() const [activeRoute, setActiveRoute] = useState(null) const [routes] = useState(createExtendedRoutes() as ExtendedRoute[]) - const [treeRoutes] = useState(createRouteTree(window.__reactRouterManifest?.routes)) + const [treeRoutes, setTreeRoutes] = useState(createRouteTree(window.__reactRouterManifest?.routes)) const isTreeView = routeViewMode === "tree" const openNewRoute = (path: string) => (e?: MouseEvent) => { e?.preventDefault() @@ -32,6 +32,26 @@ const RoutesTab = () => { } } + useEffect(function fetchAllRoutesOnMount() { + import.meta.hot?.send("routes-info") + const cb = (event: any) => { + const parsed = JSON.parse(event) + const data = parsed.data as Record[] + + const routeObject: Record = {} + for (const route of data) { + routeObject[route.id] = route + } + + routeObject.root = window.__reactRouterManifest?.routes?.root + + setTreeRoutes(createRouteTree(routeObject)) + } + import.meta.hot?.on("routes-info", cb) + return () => { + import.meta.hot?.off("routes-info", cb) + } + }, []) return (
@@ -40,7 +60,11 @@ const RoutesTab = () => { - activeRoutes.includes((link.target.data.attributes as any).id) ? "stroke-yellow-500" : "stroke-gray-400" + activeRoutes.includes((link.target.data.attributes as any).id) + ? "stroke-yellow-500" + : window.__reactRouterManifest?.routes?.[link.target.data.attributes.id] + ? "stroke-gray-400" + : "stroke-gray-400/20" } renderCustomNodeElement={(props) => RouteNode({ diff --git a/src/client/utils/routing.ts b/src/client/utils/routing.ts index 573d149d..5792280f 100644 --- a/src/client/utils/routing.ts +++ b/src/client/utils/routing.ts @@ -48,18 +48,29 @@ const ROUTE_FILLS = { PURPLE: "fill-purple-500 text-white", } as const +const UNDISCOVERED_ROUTE_FILLS = { + GREEN: "fill-green-500/20 text-white", + BLUE: "fill-blue-500/20 text-white", + PURPLE: "fill-purple-500/20 text-white", +} + export function getRouteColor(route: Route) { + const isDiscovered = !!window.__reactRouterManifest?.routes[route.id] + const FILL = isDiscovered ? ROUTE_FILLS : UNDISCOVERED_ROUTE_FILLS switch (getRouteType(route)) { case "ROOT": - return ROUTE_FILLS.PURPLE - case "LAYOUT": - return ROUTE_FILLS.BLUE + return FILL.PURPLE + case "ROUTE": - return ROUTE_FILLS.GREEN + return FILL.GREEN + + case "LAYOUT": + return FILL.BLUE } } export type ExtendedRoute = EntryRoute & { url: string + file?: string errorBoundary: { hasErrorBoundary: boolean; errorBoundaryId: string | null } } @@ -89,8 +100,7 @@ export const createExtendedRoutes = () => { ...route, // biome-ignore lint/style/noNonNullAssertion: url: convertReactRouterPathToUrl(window.__reactRouterManifest!.routes, route), - // biome-ignore lint/style/noNonNullAssertion: - errorBoundary: findParentErrorBoundary(window.__reactRouterManifest!.routes, route), + errorBoundary: findParentErrorBoundary(route), } }) .filter((route) => isLeafRoute(route as any)) diff --git a/src/client/utils/sanitize.ts b/src/client/utils/sanitize.ts index 6a9309b1..3b67eab7 100644 --- a/src/client/utils/sanitize.ts +++ b/src/client/utils/sanitize.ts @@ -21,7 +21,9 @@ export const convertReactRouterPathToUrl = (routes: any, route: Route) => { return output === "" ? "/" : output } -export const findParentErrorBoundary = (routes: RouteManifest, route: Route) => { +export const findParentErrorBoundary = (route: Route) => { + // biome-ignore lint/style/noNonNullAssertion: + const routes = window.__reactRouterManifest?.routes! let currentRoute: Route | null = route while (currentRoute) { @@ -56,6 +58,7 @@ const constructTree = (routes: any, parentId?: string): RawNodeDatum[] => { const routeKeys = Object.keys(routes) for (const key of routeKeys) { const route = routes[key] + if (route.parentId === parentId) { const url = convertReactRouterPathToUrl(routes, route) const node: RawNodeDatum = { @@ -64,9 +67,10 @@ const constructTree = (routes: any, parentId?: string): RawNodeDatum[] => { ...route, url, }, - errorBoundary: findParentErrorBoundary(routes, route), + errorBoundary: findParentErrorBoundary(route), children: constructTree(routes, route.id), } + nodes.push(node) } } diff --git a/src/vite/node-server.ts b/src/vite/node-server.ts new file mode 100644 index 00000000..7d995574 --- /dev/null +++ b/src/vite/node-server.ts @@ -0,0 +1,51 @@ +import { createServer, version as viteVersion } from "vite" +import { ViteNodeRunner } from "vite-node/client" +import { ViteNodeServer } from "vite-node/server" +import { installSourcemapsSupport } from "vite-node/source-map" + +// create vite server +const server = await createServer({ + mode: "development", + root: process.cwd(), + server: { + preTransformRequests: false, + hmr: false, + watch: null, + }, + + optimizeDeps: { + noDiscovery: true, + }, + configFile: false, + envFile: false, + plugins: [], +}) +// For old Vite, this is need to initialize the plugins. +if (Number(viteVersion.split(".")[0]) < 6) { + await server.pluginContainer.buildStart({}) +} + +// create vite-node server +const node = new ViteNodeServer(server) + +// fixes stacktraces in Errors +installSourcemapsSupport({ + getSourceMap: (source) => node.getSourceMap(source), +}) + +// create vite-node runner +const runner = new ViteNodeRunner({ + root: server.config.root, + base: server.config.base, + // when having the server and runner in a different context, + // you will need to handle the communication between them + // and pass to this function + fetchModule(id) { + return node.fetchModule(id) + }, + resolveId(id, importer) { + return node.resolveId(id, importer) + }, +}) + +export { runner } diff --git a/src/vite/plugin.tsx b/src/vite/plugin.tsx index 666e0e67..f5509189 100644 --- a/src/vite/plugin.tsx +++ b/src/vite/plugin.tsx @@ -7,6 +7,7 @@ import type { ActionEvent, LoaderEvent } from "../server/event-queue.js" import type { RequestEvent } from "../shared/request-event.js" import { DEFAULT_EDITOR_CONFIG, type EditorConfig, type OpenSourceData, handleOpenSource } from "./editor.js" import { type WriteFileData, handleWriteFile } from "./file.js" +import { runner } from "./node-server.js" import { handleDevToolsViteRequest, processPlugins } from "./utils.js" import { augmentDataFetchingFunctions } from "./utils/data-functions-augment.js" import { injectRdtClient } from "./utils/inject-client.js" @@ -41,6 +42,15 @@ type ReactRouterViteConfig = { editor?: EditorConfig } +type Route = { + id: string + file: string + path?: string + index?: boolean + caseSensitive?: boolean + children?: Route[] +} + export const defineRdtConfig = (config: ReactRouterViteConfig) => config export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = (args) => { @@ -53,6 +63,8 @@ export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = ( const includeServer = args?.includeInProd?.server ?? false const includeDevtools = args?.includeInProd?.devTools ?? false + let routes: Route[] = [] + let flatRoutes: Route[] = [] const appDir = args?.appDir || "./app" const appDirName = appDir.replace("./", "") const shouldInject = (mode: string | undefined, include: boolean) => mode === "development" || include @@ -61,12 +73,23 @@ export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = ( if (!extensions.some((ext) => id.endsWith(ext))) { return } - const isRoute = id.includes(`${appDirName}/root`) || id.includes(`${appDirName}/routes`) - if (id.includes("node_modules") || id.includes("dist") || id.includes("build") || id.includes("?") || !isRoute) { + if (id.includes("node_modules") || id.includes("dist") || id.includes("build") || id.includes("?")) { return } - const routeId = id.replace(normalizePath(process.cwd()), "").replace(`/${appDirName}/`, "").replace(".tsx", "") + const isRoute = + id.includes(`${appDirName}/root`) || + flatRoutes.some((route) => id.endsWith(route.file.replace(/^\.\//, "").replace(/^\.\.\//, ""))) + + if (!isRoute) { + return + } + + const routeId = id + .replace(normalizePath(process.cwd()), "") + .replace(`/${appDirName}/`, "") + .replace(".tsx", "") + .replace(".ts", "") return routeId } // Set the server config on the process object so that it can be accessed by the plugin @@ -80,6 +103,64 @@ export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = ( return shouldInject(config.mode, includeClient) }, async configResolved(resolvedViteConfig) { + try { + const path = await import("node:path") + // Set the route config + const routeConfigExport = (await runner.executeFile(path.join(process.cwd(), "./app/routes.ts"))).default + const routeConfig = await routeConfigExport + routes = routeConfig + + const recursiveFlatten = (routeOrRoutes: Route | Route[]): Route[] => { + if (Array.isArray(routeOrRoutes)) { + return routeOrRoutes.flatMap((route) => recursiveFlatten(route)) + } + if (routeOrRoutes.children) { + return [ + routeOrRoutes, + ...recursiveFlatten( + routeOrRoutes.children.map((child) => { + // ./path.tsx => path + // ../path.tsx => path + const withoutExtension = child.file + .split(".") + .slice(0, -1) + .join(".") + .replace(/^\.\//, "") + .replace(/^\.\.\//, "") + // ./path.tsx => path + // ../path.tsx => path + const withoutExtensionParent = routeOrRoutes.file + .split(".") + .slice(0, -1) + .join(".") + .replace(/^\.\//, "") + .replace(/^\.\.\//, "") + + return { + ...child, + id: child.id ?? withoutExtension, + parentId: withoutExtensionParent, + } + }) + ), + ] + } + return [routeOrRoutes] + } + flatRoutes = routes + .map((route) => { + // ./path.tsx => path + // ../path.tsx => path + const withoutExtension = route.file + .split(".") + .slice(0, -1) + .join(".") + .replace(/^\.\//, "") + .replace(/^\.\.\//, "") + return { ...route, parentId: "root", id: route.id ?? withoutExtension } + }) + .flatMap(recursiveFlatten) + } catch (e) {} const reactRouterIndex = resolvedViteConfig.plugins.findIndex((p) => p.name === "react-router") const devToolsIndex = resolvedViteConfig.plugins.findIndex((p) => p.name === "react-router-devtools") if (reactRouterIndex >= 0 && devToolsIndex > reactRouterIndex) { @@ -203,6 +284,15 @@ export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = ( }) ) }) + server.hot.on("routes-info", (data, client) => { + client.send( + "routes-info", + JSON.stringify({ + type: "routes-info", + data: flatRoutes, + }) + ) + }) if (!server.config.isProduction) { channel?.on("remove-event", (data, client) => { diff --git a/test-apps/react-router-vite/app/root.tsx b/test-apps/react-router-vite/app/root.tsx index 956163c4..2f650825 100644 --- a/test-apps/react-router-vite/app/root.tsx +++ b/test-apps/react-router-vite/app/root.tsx @@ -28,7 +28,7 @@ export const loader = ({context, devTools }: LoaderFunctionArgs) => { }); const start =devTools?.tracing.start("test")!; devTools?.tracing.end("test", start); - return data({ message: "Hello World", mainPromise, bigInt: BigInt(10) }, { headers: { "Cache-Control": "max-age=3600, private" } }); + return data({ message: "Hello World", mainPromise, bigInt: BigInt(10) }, ); } export const action =async ({devTools}: ActionFunctionArgs) => { diff --git a/test-apps/react-router-vite/app/routes.ts b/test-apps/react-router-vite/app/routes.ts index b8a61f25..7efea74a 100644 --- a/test-apps/react-router-vite/app/routes.ts +++ b/test-apps/react-router-vite/app/routes.ts @@ -1,3 +1,8 @@ import { flatRoutes } from "@react-router/fs-routes"; -export default flatRoutes() \ No newline at end of file +import { type RouteConfig, index, layout, prefix, route } from "@react-router/dev/routes" +import subroutes from "./subroutes.js" + + + +export default [...await flatRoutes(), ...subroutes ] \ No newline at end of file diff --git a/test-apps/react-router-vite/app/subroutes.ts b/test-apps/react-router-vite/app/subroutes.ts new file mode 100644 index 00000000..8f2b3be7 --- /dev/null +++ b/test-apps/react-router-vite/app/subroutes.ts @@ -0,0 +1,7 @@ +import { type RouteConfig, index, layout, prefix, route } from "@react-router/dev/routes" + + +export default [ + route("outside", "./routes/_index.tsx", { id: "something" }), + +] satisfies RouteConfig diff --git a/test-apps/react-router-vite/vite.config.ts b/test-apps/react-router-vite/vite.config.ts index e0905b6c..03409038 100644 --- a/test-apps/react-router-vite/vite.config.ts +++ b/test-apps/react-router-vite/vite.config.ts @@ -37,10 +37,10 @@ export default defineConfig({ tsconfigPaths() ], optimizeDeps: { - exclude: ["react-router-devtools"] + noDiscovery: true }, server: { open: true, - port: 3005, + port: 3000, }, }); diff --git a/tsup.config.ts b/tsup.config.ts index 93f53d0f..87abce49 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -7,4 +7,5 @@ export default defineConfig({ clean: false, dts: true, format: ["esm"], + external: ["vite-node"], })