@@ -5,23 +5,43 @@ import ManacoEditor from "@monaco-editor/react";
55import type * as wc from "@webcontainer/api" ;
66
77export 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
2747export 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() {
6786function 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