Skip to content

Commit d38e8b0

Browse files
authored
[fix] more startup robustness (sveltejs#112)
1 parent 99b65c5 commit d38e8b0

File tree

1 file changed

+68
-34
lines changed
  • src/lib/client/adapters/webcontainer

1 file changed

+68
-34
lines changed

src/lib/client/adapters/webcontainer/index.js

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { ready } from '../common/index.js';
44

55
/** @type {import('@webcontainer/api').WebContainer} */
66
let vm;
7+
/** Keep track of startup progress, so we don't repeat previous steps in case of a timeout */
8+
let step = 0;
9+
/** @type {string} */
10+
let base;
711

812
/**
913
* @param {import('$lib/types').Stub[]} stubs
@@ -24,10 +28,22 @@ export async function create(stubs) {
2428
throw new Error('WebContainers are not supported by Safari');
2529
}
2630

27-
const base = await new Promise(async (fulfil, reject) => {
28-
setTimeout(() => {
29-
reject(new Error('Timed out starting WebContainer'));
30-
}, 15000);
31+
base = await new Promise(async (fulfil, reject) => {
32+
if (base) {
33+
// startup was successful in the meantime
34+
fulfil(base);
35+
}
36+
37+
/** @type {any} */
38+
let timeout;
39+
function reset_timeout() {
40+
clearTimeout(timeout);
41+
timeout = setTimeout(() => {
42+
reject(new Error('Timed out starting WebContainer'));
43+
}, 8000);
44+
}
45+
46+
reset_timeout();
3147

3248
// There can only be one instance, else it throws an error - guard against this case
3349
// if there was an error later on or a timeout and the user tries again
@@ -46,44 +62,62 @@ export async function create(stubs) {
4662
reject(new Error(error.message));
4763
});
4864

49-
const ready_unsub = vm.on('server-ready', (port, base) => {
65+
const ready_unsub = vm.on('server-ready', (port, _base) => {
66+
base = _base;
5067
ready_unsub();
51-
console.log(`server ready on port ${port} at ${performance.now()}: ${base}`);
52-
fulfil(base);
68+
console.log(`server ready on port ${port} at ${performance.now()}: ${_base}`);
69+
fulfil(_base);
5370
});
5471

55-
console.log('loading files');
56-
57-
await vm.loadFiles(tree);
58-
59-
console.log('unpacking modules');
60-
61-
const unzip = await vm.run(
62-
{
63-
command: 'node',
64-
args: ['unzip.cjs']
65-
},
66-
{
67-
stderr: (data) => console.error(`[unzip] ${data}`)
68-
}
69-
);
70-
71-
const code = await unzip.onExit;
72+
if (step < 1) {
73+
reset_timeout();
74+
step = 1;
75+
console.log('loading files');
7276

73-
if (code !== 0) {
74-
reject(new Error('Failed to initialize WebContainer'));
77+
await vm.loadFiles(tree);
7578
}
7679

77-
console.log('starting dev server');
80+
if (step < 2) {
81+
reset_timeout();
82+
step = 2;
83+
console.log('unpacking modules');
84+
85+
const unzip = await vm.run(
86+
{
87+
command: 'node',
88+
args: ['unzip.cjs']
89+
},
90+
{
91+
stderr: (data) => console.error(`[unzip] ${data}`)
92+
}
93+
);
7894

79-
await vm.run({ command: 'chmod', args: ['a+x', 'node_modules/vite/bin/vite.js'] });
95+
const code = await unzip.onExit;
8096

81-
await vm.run(
82-
{ command: 'turbo', args: ['run', 'dev'] },
83-
{
84-
stderr: (data) => console.error(`[dev] ${data}`)
97+
if (code !== 0) {
98+
reject(new Error('Failed to initialize WebContainer'));
8599
}
86-
);
100+
}
101+
102+
if (step < 3) {
103+
reset_timeout();
104+
step = 3;
105+
console.log('starting dev server');
106+
107+
await vm.run({ command: 'chmod', args: ['a+x', 'node_modules/vite/bin/vite.js'] });
108+
109+
await vm.run(
110+
{ command: 'turbo', args: ['run', 'dev'] },
111+
{
112+
stdout: () => {
113+
if (!base) {
114+
reset_timeout();
115+
}
116+
},
117+
stderr: (data) => console.error(`[dev] ${data}`)
118+
}
119+
);
120+
}
87121
});
88122

89123
/**
@@ -94,7 +128,7 @@ export async function create(stubs) {
94128
* Keeps track of the latest create/reset to ensure things are not processed in parallel.
95129
* (if this turns out to be insufficient, we can use a queue)
96130
*/
97-
let running = base;
131+
let running = Promise.resolve();
98132

99133
return {
100134
base,

0 commit comments

Comments
 (0)