Skip to content

Commit 9018a16

Browse files
authored
v1.4.0 (#31)
1 parent 6479bb6 commit 9018a16

File tree

15 files changed

+211
-98
lines changed

15 files changed

+211
-98
lines changed

README.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,101 @@ The `RemixDevTools` component accepts the following props:
100100
- `defaultOpen`: Whether to open the Remix Development Tools by default. Defaults to `false`.
101101
- `position`: The position of the Remix Development Tools trigger. Defaults to `bottom-right`.
102102
- `requireUrlFlag`: Requires rdt=true to be present in the URL search to open the Remix Development Tools. Defaults to `false`.
103-
- `showRouteBoundaries`: Allows you to see each Outlet and route boundaries by coloring the background. Defaults to `false`.
103+
- [**DEPRECATED**] `showRouteBoundaries`:This flag has been deprecated in favor of adding route boundaries. Please see the section below for more information.
104104
- `hideUntilHover`: Allows you to hide the trigger until you hover over it. Defaults to `false`.
105105
- `additionalTabs`: Allows you to provide additional tabs to the Remix Development Tools. Defaults to `[]`.
106106

107+
## Adding route boundaries
108+
109+
The `showErrorBoundaries` flag has been deprecated in favor of this method. Please use it instead.
110+
111+
In order to add Route boundaries to your project you need to do the following two things:
112+
113+
1. Modify your `entry.server.ts` to add the following code:
114+
115+
```diff
116+
function handleBrowserRequest(
117+
request: Request,
118+
responseStatusCode: number,
119+
responseHeaders: Headers,
120+
remixContext: EntryContext
121+
) {
122+
- return new Promise((resolve, reject) => {
123+
+ return new Promise(async (resolve, reject) => {
124+
let shellRendered = false;
125+
+ const context = process.env.NODE_ENV === "development" ? await import("remix-development-tools").then(({ initRouteBoundariesServer }) => initRouteBoundariesServer(remixContext)) : remixContext;
126+
const { pipe, abort } = renderToPipeableStream(
127+
<RemixServer
128+
- context={remixContext}
129+
+ context={context}
130+
url={request.url}
131+
abortDelay={ABORT_DELAY}
132+
/>,
133+
{
134+
onShellReady() {
135+
shellRendered = true;
136+
const body = new PassThrough();
137+
138+
responseHeaders.set("Content-Type", "text/html");
139+
140+
resolve(
141+
new Response(body, {
142+
headers: responseHeaders,
143+
status: responseStatusCode,
144+
})
145+
);
146+
147+
pipe(body);
148+
},
149+
onShellError(error: unknown) {
150+
reject(error);
151+
},
152+
onError(error: unknown) {
153+
responseStatusCode = 500;
154+
// Log streaming rendering errors from inside the shell. Don't log
155+
// errors encountered during initial shell rendering since they'll
156+
// reject and get logged in handleDocumentRequest.
157+
if (shellRendered) {
158+
console.error(error);
159+
}
160+
},
161+
}
162+
);
163+
164+
setTimeout(abort, ABORT_DELAY);
165+
});
166+
}
167+
```
168+
169+
2. Modify your `entry.client.tsx` to add the following code:
170+
171+
```diff
172+
+ if(process.env.NODE_ENV === "development") {
173+
+ import("remix-development-tools").then(({ initRouteBoundariesClient }) => {
174+
+ initRouteBoundariesClient();
175+
+ startTransition(() => {
176+
+ hydrateRoot(
177+
+ document,
178+
+ <StrictMode>
179+
+ <RemixBrowser />
180+
+ </StrictMode>
181+
+ );
182+
+ });
183+
+
184+
+ });
185+
+ } else {
186+
startTransition(() => {
187+
hydrateRoot(
188+
document,
189+
<StrictMode>
190+
<RemixBrowser />
191+
</StrictMode>
192+
);
193+
});
194+
+ }
195+
```
196+
3. You are good to go. Now you can see the route boundaries in your project when you hover each route.
197+
107198
## Plugins
108199

109200
Writing plugins for Remix Development Tools is easy. You can write a plugin that adds a new tab to the Remix Development Tools in the following way:

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "remix-development-tools",
33
"description": "Remix development tools.",
44
"author": "Alem Tuzlak",
5-
"version": "1.3.0",
5+
"version": "1.4.0",
66
"license": "MIT",
77
"keywords": [
88
"remix",

src/RemixDevTools/RemixDevTools.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { useTimelineHandler } from "./hooks/useTimelineHandler";
55
import { useRDTContext } from "./context/useRDTContext";
66
import { isDev } from "./utils/isDev";
77
import { useLocation } from "@remix-run/react";
8-
import { useOutletAugment } from "./hooks/useOutletAugment";
98
import { Trigger } from "./components/Trigger";
109
import { MainPanel } from "./layout/MainPanel";
1110
import { Tabs } from "./layout/Tabs";
@@ -15,17 +14,14 @@ interface Props extends RemixDevToolsProps {
1514
defaultOpen: boolean;
1615
position: Exclude<RemixDevToolsProps["position"], undefined>;
1716
hideUntilHover: boolean;
18-
showRouteBoundaries: boolean;
1917
}
2018

2119
const RemixDevTools = ({
2220
defaultOpen,
2321
position,
2422
additionalTabs,
2523
hideUntilHover,
26-
showRouteBoundaries,
2724
}: Props) => {
28-
useOutletAugment(showRouteBoundaries);
2925
useTimelineHandler();
3026
const { persistOpen } = useRDTContext();
3127
const [isOpen, setIsOpen] = useState(defaultOpen || persistOpen);
@@ -49,7 +45,6 @@ const RemixDevTools = ({
4945
</div>
5046
);
5147
};
52-
5348
let hydrating = true;
5449

5550
function useHydrated() {
@@ -78,8 +73,6 @@ export interface RemixDevToolsProps {
7873
| "top-left"
7974
| "middle-right"
8075
| "middle-left";
81-
// Show route boundaries when you hover over a route in active page tab
82-
showRouteBoundaries?: boolean;
8376
// Additional tabs to add to the dev tools
8477
additionalTabs?: Tab[];
8578
// Whether the dev tools trigger should hide until hovered
@@ -90,7 +83,6 @@ const RDTWithContext = ({
9083
port = 3003,
9184
defaultOpen = false,
9285
requireUrlFlag,
93-
showRouteBoundaries = false,
9486
position = "bottom-right",
9587
hideUntilHover = false,
9688
additionalTabs,
@@ -101,14 +93,14 @@ const RDTWithContext = ({
10193

10294
if (!hydrated || !isDevelopment) return null;
10395
if (requireUrlFlag && !url.includes("rdt=true")) return null;
96+
10497
return (
105-
<RDTContextProvider showRouteBoundaries={showRouteBoundaries} port={port}>
98+
<RDTContextProvider port={port}>
10699
<RemixDevTools
107100
defaultOpen={defaultOpen}
108101
position={position}
109102
additionalTabs={additionalTabs}
110103
hideUntilHover={hideUntilHover}
111-
showRouteBoundaries={showRouteBoundaries}
112104
/>
113105
</RDTContextProvider>
114106
);

src/RemixDevTools/context/RDTContext.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,13 @@ interface ContextProps {
2222

2323
export const REMIX_DEV_TOOLS = "remixDevTools";
2424

25-
export const RDTContextProvider = ({
26-
children,
27-
port,
28-
showRouteBoundaries,
29-
}: ContextProps) => {
25+
export const RDTContextProvider = ({ children, port }: ContextProps) => {
3026
const existingState = sessionStorage.getItem(REMIX_DEV_TOOLS);
3127
const settings = localStorage.getItem(REMIX_DEV_TOOLS);
3228

3329
const [state, dispatch] = useReducer(rdtReducer, {
3430
...initialState,
3531
...(existingState ? JSON.parse(existingState) : {}),
36-
showRouteBoundaries,
3732
settings: settings
3833
? { ...initialState.settings, ...JSON.parse(settings), port }
3934
: { ...initialState.settings, port },

src/RemixDevTools/context/rdtReducer.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export type RouteWildcards = Record<string, Record<string, string> | undefined>;
66

77
export type RemixDevToolsState = {
88
timeline: TimelineEvent[];
9-
showRouteBoundaries?: boolean;
109
terminals: Terminal[];
1110
settings: {
1211
routeWildcards: RouteWildcards;
@@ -20,7 +19,6 @@ export type RemixDevToolsState = {
2019

2120
export const initialState: RemixDevToolsState = {
2221
timeline: [],
23-
showRouteBoundaries: false,
2422
terminals: [{ id: 0, locked: false, output: [], history: [] }],
2523
settings: {
2624
routeWildcards: {},

src/RemixDevTools/context/useRDTContext.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ const useRDTContext = () => {
1111
throw new Error("useRDTContext must be used within a RDTContextProvider");
1212
}
1313
const { state, dispatch } = context;
14-
const { timeline, settings, showRouteBoundaries, terminals, persistOpen } =
15-
state;
14+
const { timeline, settings, terminals, persistOpen } = state;
1615
const { activeTab, shouldConnectWithForge, routeWildcards, port, height } =
1716
settings;
1817

@@ -140,7 +139,6 @@ const useRDTContext = () => {
140139
routeWildcards,
141140
port,
142141
height,
143-
showRouteBoundaries,
144142
setHeight,
145143
setRouteWildcards,
146144
terminals,

src/RemixDevTools/hooks/useOutletAugment.tsx

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/RemixDevTools/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
export { RemixDevTools } from "./RemixDevTools";
22
export { useRemixForgeSocketExternal as useRemixForgeSocket } from "./hooks/useRemixForgeSocket";
3+
export {
4+
initRouteBoundariesClient,
5+
initRouteBoundariesServer,
6+
} from "./methods/boundaries";
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { EntryContext } from "@remix-run/server-runtime";
2+
import clsx from "clsx";
3+
4+
export const initRouteBoundariesServer = (context: EntryContext) => {
5+
return {
6+
...context,
7+
routeModules: Object.entries(context.routeModules).reduce(
8+
(acc, [key, value]) => {
9+
if (key === "root") {
10+
return { ...acc, [key]: value };
11+
}
12+
return {
13+
...acc,
14+
[key]: {
15+
...value,
16+
default: () => {
17+
return (
18+
<>
19+
<div
20+
className={clsx(
21+
"rdt-invisible rdt-absolute rdt-hidden rdt-h-0 rdt-w-0",
22+
key
23+
)}
24+
/>
25+
<value.default />
26+
</>
27+
);
28+
},
29+
},
30+
};
31+
},
32+
{}
33+
),
34+
};
35+
};
36+
37+
export const initRouteBoundariesClient = () => {
38+
window.__remixRouteModules = new Proxy(window.__remixRouteModules, {
39+
get: function (target, property) {
40+
if (property === "root") return target[property];
41+
const value = target[property as any];
42+
if (value?.default && value.default.name !== "hooked") {
43+
return {
44+
...value,
45+
default: function hooked() {
46+
return (
47+
<>
48+
<div
49+
className={clsx(
50+
"rdt-invisible rdt-absolute rdt-hidden rdt-h-0 rdt-w-0",
51+
property as string
52+
)}
53+
/>
54+
<value.default />
55+
</>
56+
);
57+
},
58+
};
59+
}
60+
61+
return value;
62+
},
63+
});
64+
};

0 commit comments

Comments
 (0)