Skip to content

Commit 9b49533

Browse files
jacob-ebeybrookslybrand
authored andcommitted
cleanup loading states a little and give the appearance of a faster boot
1 parent 446ce59 commit 9b49533

File tree

1 file changed

+72
-62
lines changed

1 file changed

+72
-62
lines changed

app/routes/_marketing.playground.tsx

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,43 @@ import ManacoEditor from "@monaco-editor/react";
55
import type * as wc from "@webcontainer/api";
66

77
export default function Playground() {
8-
return (
9-
<div className="flex flex-1 m-auto w-[90rem] max-w-full px-4 sm:px-6 lg:px-8">
10-
<div className="flex flex-1">
11-
<section className="flex flex-1">
12-
<style
13-
dangerouslySetInnerHTML={{
14-
__html: ".playground { height: 100%; }",
15-
}}
16-
/>
17-
<Editor />
18-
</section>
19-
<section className="flex-1">
20-
<Preview />
21-
</section>
22-
</div>
8+
const state = useWebContainer();
9+
const [mounted, setMounted] = React.useState(false);
10+
React.useEffect(() => {
11+
setMounted(true);
12+
}, []);
13+
14+
const loadingState = (
15+
<div className="w-full h-full flex items-center justify-center">
16+
{state?.status ? `${state.status}...` : "booting..."}
2317
</div>
2418
);
19+
20+
if (!mounted || (!state?.containerPromise && !state?.container)) {
21+
return loadingState;
22+
}
23+
24+
return (
25+
<Await resolve={state.containerPromise}>
26+
{() => (
27+
<div className="flex flex-1 m-auto w-[90rem] max-w-full px-4 sm:px-6 lg:px-8">
28+
<div className="flex flex-1">
29+
<section className="flex flex-1">
30+
<style
31+
dangerouslySetInnerHTML={{
32+
__html: ".playground { height: 100%; }",
33+
}}
34+
/>
35+
<Editor />
36+
</section>
37+
<section className="flex-1">
38+
<Preview />
39+
</section>
40+
</div>
41+
</div>
42+
)}
43+
</Await>
44+
);
2545
}
2646

2747
export const headers: HeadersFunction = () => {
@@ -48,7 +68,6 @@ function Preview() {
4868
</div>
4969
);
5070

51-
console.log({ mounted, state });
5271
if (!mounted || !state?.urlPromise) {
5372
return loadingState;
5473
}
@@ -67,29 +86,15 @@ function Preview() {
6786
function Editor() {
6887
const [localContainer, setLocalContainer] =
6988
React.useState<wc.WebContainer | null>(null);
70-
const [mounted, setMounted] = React.useState(false);
71-
React.useEffect(() => {
72-
setMounted(true);
73-
}, []);
7489
const state = useWebContainer();
7590
const containerOrPromise =
7691
state?.container ?? state?.containerPromise ?? null;
7792

78-
const loadingState = (
79-
<div className="w-full h-full flex items-center justify-center">
80-
{state?.status ? `${state.status}...` : "booting..."}
81-
</div>
82-
);
83-
84-
if (!mounted) {
85-
return loadingState;
86-
}
87-
8893
const editor = (
8994
<ManacoEditor
9095
key="playground-editor"
9196
className="playground"
92-
loading={loadingState}
97+
loading={"loading editor..."}
9398
wrapperProps={{
9499
className: "flex-1",
95100
style: { height: "unset" },
@@ -108,7 +113,7 @@ function Editor() {
108113
/>
109114
);
110115
return (
111-
<React.Suspense fallback={loadingState}>
116+
<React.Suspense fallback={editor}>
112117
<Await resolve={containerOrPromise}>
113118
{(container) => {
114119
if (localContainer !== container) {
@@ -130,9 +135,9 @@ interface WebContainerStore {
130135
urlPromise?: Promise<string>;
131136
status:
132137
| "idle"
133-
| "booting"
134-
| "initializing"
135-
| "installing"
138+
| "booting container"
139+
| "initializing template"
140+
| "installing dependencies"
136141
| "ready"
137142
| "error";
138143
};
@@ -192,14 +197,13 @@ function useWebContainer() {
192197
if (!store.container && !store.containerPromise) {
193198
const deferredURL = new Deferred<string>();
194199
webContainerStore.update({
195-
status: "booting",
200+
status: "booting container",
196201
urlPromise: deferredURL.promise,
197202
containerPromise: import("@webcontainer/api")
198203
.then(({ WebContainer }) => WebContainer.boot())
199204
.then(async (container) => {
200-
webContainerStore.update({ status: "initializing" });
205+
webContainerStore.update({ status: "initializing template" });
201206

202-
// npx -y create-remix@latest . -y --no-color --no-motion --no-install --no-git-init
203207
const process = await container.spawn("npx", [
204208
"-y",
205209
"create-remix@latest",
@@ -209,6 +213,8 @@ function useWebContainer() {
209213
"--no-motion",
210214
"--no-install",
211215
"--no-git-init",
216+
"--template",
217+
"https://github.com/remix-run/remix/tree/main/templates/unstable-vite",
212218
]);
213219
if ((await process.exit) !== 0) {
214220
throw new Error("Failed to create remix app");
@@ -222,37 +228,41 @@ function useWebContainer() {
222228

223229
return container;
224230
})
225-
.then(async (container) => {
226-
webContainerStore.update({ status: "installing" });
227-
const process = await container.spawn("npm", ["install"]);
228-
if ((await process.exit) !== 0) {
229-
throw new Error("Failed to install dependencies");
230-
}
231-
232-
return container;
233-
})
234231
.then((container) => {
235-
webContainerStore.update({
236-
status: "ready",
237-
container,
238-
containerPromise: undefined,
239-
});
232+
webContainerStore.update({ status: "installing dependencies" });
233+
container
234+
.spawn("npm", ["install"])
235+
.then((process) => process.exit)
236+
.then((exit) => {
237+
if (exit !== 0) {
238+
throw new Error("Failed to install dependencies");
239+
}
240+
})
241+
.then(() => {
242+
webContainerStore.update({
243+
status: "ready",
244+
container,
245+
containerPromise: undefined,
246+
});
240247

241-
container.on("server-ready", (port, url) => {
242-
if (port === 3000) {
243-
deferredURL.resolve(url);
244-
}
245-
});
248+
container.on("server-ready", (port, url) => {
249+
if (port === 5173) {
250+
deferredURL.resolve(url);
251+
}
252+
});
246253

247-
container
248-
.spawn("npm", ["run", "dev"])
249-
.then(async (process) => {
250-
return process.exit;
254+
return container
255+
.spawn("npm", ["run", "dev"])
256+
.then(async (process) => {
257+
return process.exit;
258+
});
259+
})
260+
.then(() => {
261+
throw new Error("Dev server exited unexpectedly");
251262
})
252263
.catch((reason) => {
253264
deferredURL.reject(reason);
254265
});
255-
256266
return container;
257267
})
258268
.catch((reason) => {

0 commit comments

Comments
 (0)