Skip to content

Commit 8d6420b

Browse files
committed
refactor(repl): move build logic to main thread
The service worker is now only used as a proxy. this way we can use ESM and we don't need to bundle separately.
1 parent f812761 commit 8d6420b

File tree

10 files changed

+976
-45
lines changed

10 files changed

+976
-45
lines changed

packages/docs/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@mui/x-data-grid": "6.20.4",
2020
"@qwik-ui/headless": "0.6.7",
2121
"@qwik.dev/partytown": "0.11.2",
22+
"@rollup/browser": "^4.35.0",
2223
"@shikijs/colorized-brackets": "3.12.2",
2324
"@shikijs/langs": "3.12.2",
2425
"@shikijs/rehype": "3.12.2",
@@ -37,6 +38,7 @@
3738
"gray-matter": "4.0.3",
3839
"leaflet": "1.9.4",
3940
"magic-string": "0.30.17",
41+
"memfs": "^4.17.0",
4042
"openai": "3.3.0",
4143
"prettier": "3.6.2",
4244
"prism-themes": "1.9.0",

packages/docs/src/repl/bundled.tsx

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import { version as qwikVersion } from '@builder.io/qwik';
22
import type { PkgUrls } from './types';
33

4-
import prettierPkgJson from 'prettier/package.json';
5-
import prettierParserHtml from '../../node_modules/prettier/plugins/html.js?raw-source';
6-
import prettierStandaloneJs from '../../node_modules/prettier/standalone.js?raw-source';
7-
8-
import terserPkgJson from 'terser/package.json';
9-
import terserJs from '../../node_modules/terser/dist/bundle.min.js?raw-source';
10-
114
import qBuild from '../../node_modules/@builder.io/qwik/dist/build/index.d.ts?raw-source';
125
import qCoreCjs from '../../node_modules/@builder.io/qwik/dist/core.cjs?raw-source';
136
import qCoreDts from '../../node_modules/@builder.io/qwik/dist/core.d.ts?raw-source';
@@ -63,23 +56,4 @@ export const bundled: PkgUrls = {
6356
'/bindings/qwik.wasm.cjs': qWasmCjs,
6457
'/bindings/qwik_wasm_bg.wasm': qWasmBinUrl,
6558
},
66-
prettier: {
67-
version: prettierPkgJson.version,
68-
'/plugins/html.js': prettierParserHtml,
69-
'/standalone.js': prettierStandaloneJs,
70-
},
71-
// v4 of rollup uses wasm etc, need to figure out how to bundle that
72-
rollup: {
73-
version: ROLLUP_VERSION,
74-
'/dist/rollup.browser.js': getNpmCdnUrl(
75-
{},
76-
'rollup',
77-
ROLLUP_VERSION,
78-
'/dist/rollup.browser.js'
79-
),
80-
},
81-
terser: {
82-
version: terserPkgJson.version,
83-
'/dist/bundle.min.js': terserJs,
84-
},
8559
};

packages/docs/src/repl/repl.tsx

Lines changed: 133 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { getReplVersion } from './repl-version';
1616
import { updateReplOutput } from './repl-output-update';
1717
import { QWIK_PKG_NAME, bundled, getNpmCdnUrl } from './bundled';
1818
import { isServer } from '@builder.io/qwik';
19+
import { loadDependencies } from './worker/repl-dependencies-main';
20+
import { appBundleClient, appBundleSsr, appSsrHtml } from './worker/repl-builder';
1921

2022
export const Repl = component$((props: ReplProps) => {
2123
useStyles$(styles);
@@ -189,15 +191,15 @@ const getDependencies = (input: ReplAppInput) => {
189191
return out;
190192
};
191193

192-
export const sendUserUpdateToReplServer = (input: ReplAppInput, store: ReplStore) => {
194+
export const sendUserUpdateToReplServer = async (input: ReplAppInput, store: ReplStore) => {
193195
if (isServer) {
194196
return;
195197
}
196198
if (input.version && store.serverWindow) {
197-
const msg: ReplUpdateMessage = {
198-
type: 'update',
199-
clientId: store.clientId,
200-
options: {
199+
try {
200+
// Load dependencies in main thread
201+
const deps = getDependencies(input);
202+
await loadDependencies({
201203
buildId: input.buildId,
202204
debug: input.debug,
203205
srcInputs: input.files,
@@ -207,13 +209,133 @@ export const sendUserUpdateToReplServer = (input: ReplAppInput, store: ReplStore
207209
},
208210
version: input.version,
209211
serverUrl: store.serverUrl,
210-
deps: getDependencies(input),
211-
},
212-
};
212+
deps,
213+
});
214+
215+
// Create build result
216+
const result: any = {
217+
type: 'result',
218+
clientId: store.clientId,
219+
buildId: input.buildId,
220+
html: '',
221+
transformedModules: [],
222+
clientBundles: [],
223+
manifest: undefined,
224+
ssrModules: [],
225+
diagnostics: [],
226+
events: [],
227+
};
228+
229+
// Run build process in main thread
230+
await appBundleClient(
231+
{
232+
buildId: input.buildId,
233+
debug: input.debug,
234+
srcInputs: input.files,
235+
buildMode: input.buildMode as any,
236+
entryStrategy: {
237+
type: input.entryStrategy as any,
238+
},
239+
version: input.version,
240+
serverUrl: store.serverUrl,
241+
deps,
242+
},
243+
result
244+
);
245+
246+
await appBundleSsr(
247+
{
248+
buildId: input.buildId,
249+
debug: input.debug,
250+
srcInputs: input.files,
251+
buildMode: input.buildMode as any,
252+
entryStrategy: {
253+
type: input.entryStrategy as any,
254+
},
255+
version: input.version,
256+
serverUrl: store.serverUrl,
257+
deps,
258+
},
259+
result
260+
);
261+
262+
await appSsrHtml(
263+
{
264+
buildId: input.buildId,
265+
debug: input.debug,
266+
srcInputs: input.files,
267+
buildMode: input.buildMode as any,
268+
entryStrategy: {
269+
type: input.entryStrategy as any,
270+
},
271+
version: input.version,
272+
serverUrl: store.serverUrl,
273+
deps,
274+
},
275+
result
276+
);
277+
278+
// Update the store with results
279+
updateReplOutput(store, result);
280+
281+
// Send build results to service worker
282+
if (navigator.serviceWorker.controller) {
283+
navigator.serviceWorker.controller.postMessage({
284+
type: 'update-build',
285+
clientId: store.clientId,
286+
buildId: input.buildId,
287+
html: result.html,
288+
clientBundles: result.clientBundles,
289+
ssrModules: result.ssrModules,
290+
});
291+
}
213292

214-
if (msg.options.srcInputs && msg.options.srcInputs.length > 0) {
215-
// using JSON.stringify() to remove proxies
216-
store.serverWindow.postMessage(JSON.stringify(msg));
293+
// Send result to server window for iframe communication
294+
const msg: ReplUpdateMessage = {
295+
type: 'update',
296+
clientId: store.clientId,
297+
options: {
298+
buildId: input.buildId,
299+
debug: input.debug,
300+
srcInputs: input.files,
301+
buildMode: input.buildMode as any,
302+
entryStrategy: {
303+
type: input.entryStrategy as any,
304+
},
305+
version: input.version,
306+
serverUrl: store.serverUrl,
307+
deps,
308+
},
309+
};
310+
311+
if (msg.options.srcInputs && msg.options.srcInputs.length > 0) {
312+
store.serverWindow.postMessage(JSON.stringify(msg));
313+
}
314+
} catch (e: any) {
315+
console.error('Build error:', e);
316+
const errorResult: any = {
317+
type: 'result',
318+
clientId: store.clientId,
319+
buildId: input.buildId,
320+
html: '',
321+
transformedModules: [],
322+
clientBundles: [],
323+
manifest: undefined,
324+
ssrModules: [],
325+
diagnostics: [
326+
{
327+
scope: 'runtime',
328+
message: String(e.stack || e),
329+
category: 'error',
330+
file: '',
331+
highlights: [],
332+
suggestions: null,
333+
code: 'runtime error',
334+
},
335+
],
336+
events: [],
337+
};
338+
updateReplOutput(store, errorResult);
217339
}
218340
}
219341
};

0 commit comments

Comments
 (0)