Skip to content

Commit baf2a94

Browse files
committed
Revert "use rolldown"
This reverts commit d87cc3b.
1 parent d87cc3b commit baf2a94

File tree

8 files changed

+1042
-1047
lines changed

8 files changed

+1042
-1047
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@
4848
"@orama/orama": "^3.1.10",
4949
"@orama/plugin-data-persistence": "^3.1.10",
5050
"@orama/react-components": "^0.8.1",
51-
"@rollup/plugin-virtual": "^3.0.2",
5251
"acorn": "^8.15.0",
5352
"commander": "^14.0.0",
5453
"dedent": "^1.6.0",
54+
"esbuild": "^0.25.6",
55+
"esbuild-style-plugin": "^1.6.3",
5556
"estree-util-to-js": "^2.0.0",
5657
"estree-util-value-to-estree": "^3.4.0",
5758
"estree-util-visit": "^2.0.0",
5859
"github-slugger": "^2.0.0",
5960
"glob": "^11.0.3",
6061
"hast-util-to-string": "^3.0.1",
6162
"hastscript": "^9.0.1",
62-
"lightningcss": "^1.30.1",
6363
"mdast-util-slice-markdown": "^1.1.0",
6464
"mustache": "^4.2.0",
6565
"preact": "^10.26.9",
@@ -73,7 +73,6 @@
7373
"remark-parse": "^11.0.0",
7474
"remark-rehype": "^11.1.2",
7575
"remark-stringify": "^11.0.0",
76-
"rolldown": "^1.0.0-beta.24",
7776
"semver": "^7.7.1",
7877
"shiki": "^3.7.0",
7978
"unified": "^11.0.5",

src/generators/web/build/bundle.mjs

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,76 @@
1-
import virtual from '@rollup/plugin-virtual';
2-
import { build } from 'rolldown';
1+
import { writeFile } from 'node:fs/promises';
32

4-
import cssLoader from './css.mjs';
3+
import esbuild from 'esbuild';
4+
5+
import { RESOLVE_DIR } from '../constants.mjs';
56
import staticData from './data.mjs';
7+
import plugins from './plugins.mjs';
8+
9+
/** @typedef {{ server: boolean, debug: boolean }} BundleOptions */
610

711
/**
8-
* Bundles JavaScript code and returns JS/CSS content
12+
* Creates the esbuild configuration object
913
* @param {string} code - Source code to bundle
10-
* @param {{ server: boolean }} options - Bundle configuration options
11-
* @returns {Promise<{ js: string, css: string }>} The bundled code
14+
* @param {BundleOptions} options - Options
15+
* @returns {import('esbuild').BuildOptions} ESBuild configuration
1216
*/
13-
export default async function bundle(code, { server = false } = {}) {
14-
const result = await build({
15-
input: 'entrypoint.jsx',
16-
output: {
17-
format: server ? 'cjs' : 'iife',
18-
minify: server ? undefined : true,
19-
},
20-
platform: server ? 'node' : 'browser',
21-
external: server ? ['preact'] : [],
22-
define: {
23-
// Inject static data at build time
24-
__STATIC_DATA__: staticData,
17+
const createConfig = (code, { server, debug }) => ({
18+
stdin: {
19+
contents: code,
20+
resolveDir: RESOLVE_DIR,
21+
loader: 'jsx',
22+
},
23+
bundle: true,
24+
minify: !debug,
25+
format: 'iife',
26+
platform: server ? 'node' : 'browser',
27+
jsx: 'automatic',
28+
write: false,
29+
outfile: 'output.js',
30+
// When updating the `define` object, also update client/types.d.ts to
31+
// include the newly defined globals
32+
define: {
33+
// Inject static data at build time
34+
__STATIC_DATA__: staticData,
35+
// Use `if (CLIENT)` or `if (SERVER)` to conditionally run code for specific environments,
36+
// and omit it otherwise. The `client/package.json` includes `sideEffects: false` to let
37+
// ESBuild safely tree-shake that directory. However, this doesn't affect dependencies,
38+
// so our tree-shaking ability is limited.
39+
//
40+
// TODO(@avivkeller): Consider switching to Rolldown once it's stable, as it offers
41+
// improved tree-shaking support, with the high-speed of ESBuild.
42+
SERVER: String(server),
43+
CLIENT: String(!server),
44+
},
45+
alias: {
46+
react: 'preact/compat',
47+
'react-dom': 'preact/compat',
48+
},
49+
external: server ? ['preact'] : [],
50+
plugins,
51+
metafile: debug,
52+
});
2553

26-
// Environment flags for conditional code
27-
// Use `if (CLIENT)` or `if (SERVER)` to target specific environments
28-
// The unused code will be removed during tree-shaking
29-
SERVER: String(server),
30-
CLIENT: String(!server),
31-
},
32-
jsx: 'react-jsx',
33-
resolve: {
34-
alias: {
35-
react: 'preact/compat',
36-
'react-dom': 'preact/compat',
37-
},
38-
},
39-
plugins: [
40-
virtual({
41-
'entrypoint.jsx': code,
42-
}),
43-
cssLoader(),
44-
],
45-
treeshake: true,
46-
write: false,
47-
});
54+
/**
55+
* Bundles JavaScript code and returns JS/CSS content
56+
* @param {string} code - Source code to bundle
57+
* @param {BundleOptions} options - Options
58+
* @returns {Promise<{js: string, css?: string}>}
59+
*/
60+
export default async (code, { server = false, debug = false } = {}) => {
61+
const config = createConfig(code, { server, debug });
62+
const result = await esbuild.build(config);
63+
const [jsFile, cssFile] = result.outputFiles;
4864

49-
const [js, ...cssFiles] = result.output;
65+
if (debug) {
66+
await writeFile(
67+
`out/meta-${server ? 'server' : 'client'}.json`,
68+
JSON.stringify(result.metafile)
69+
);
70+
}
5071

51-
return { js: js.code, css: cssFiles.map(f => f.source).join('') };
52-
}
72+
return {
73+
js: jsFile.text,
74+
css: cssFile?.text,
75+
};
76+
};

src/generators/web/build/css.mjs

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

src/generators/web/build/generate.mjs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ export default () => {
4040
const buildClientProgram = componentCode => {
4141
return [
4242
...baseImports,
43-
createImportDeclaration(
44-
null,
45-
new URL('../ui/index.css', import.meta.url).pathname
46-
),
43+
createImportDeclaration(null, './index.css'),
4744
createImportDeclaration('hydrate', 'preact', false),
4845
'',
4946
`hydrate(${componentCode}, document.getElementById("root"));`,

src/generators/web/build/plugins.mjs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { existsSync } from 'node:fs';
2+
import { fileURLToPath } from 'node:url';
3+
4+
import stylePlugin from 'esbuild-style-plugin';
5+
6+
/**
7+
* ESBuild plugin that resolves UI component imports
8+
*
9+
* This plugin intercepts imports starting with '@node-core/ui-components' or '#ui/'
10+
* and resolves them to the corresponding TypeScript files. It follows a resolution
11+
* strategy where it first tries to find an index.tsx file, then falls back to a
12+
* .tsx file with the same name.
13+
*/
14+
const uiComponentsResolverPlugin = {
15+
name: 'ui-components-resolver',
16+
17+
/**
18+
* @param {import('esbuild').PluginBuild} build
19+
*/
20+
setup(build) {
21+
build.onResolve({ filter: /^#ui\// }, ({ path }) => {
22+
// Skip paths that already have file extensions
23+
if (/\.[a-zA-Z0-9]+$/.test(path)) return;
24+
25+
// Normalize the import path by converting #ui/ alias to the full package name
26+
const normalizedPath = path.replace(
27+
/^#ui\//,
28+
'@node-core/ui-components/'
29+
);
30+
31+
const resolutionSuffixes = ['/index.js', '.js'];
32+
33+
for (const suffix of resolutionSuffixes) {
34+
try {
35+
const resolvedPath = fileURLToPath(
36+
import.meta.resolve(normalizedPath + suffix)
37+
);
38+
39+
if (existsSync(resolvedPath)) {
40+
return { path: resolvedPath };
41+
}
42+
} catch {
43+
// Silently ignore resolution errors and try the next suffix
44+
continue;
45+
}
46+
}
47+
48+
// If no resolution found, let ESBuild handle it with default behavior
49+
return undefined;
50+
});
51+
},
52+
};
53+
54+
export default [uiComponentsResolverPlugin, stylePlugin()];

src/generators/web/constants.mjs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1+
import { fileURLToPath } from 'node:url';
2+
3+
export const RESOLVE_DIR = fileURLToPath(new URL('./ui', import.meta.url));
4+
5+
// Imports are relative to RESOLVE_DIR, and must be complete paths (w/ file extensions)
16
export const JSX_IMPORTS = {
27
NavBar: {
38
name: 'NavBar',
4-
source: new URL('./ui/components/NavBar', import.meta.url).pathname,
9+
source: './components/NavBar.jsx',
510
},
611
SideBar: {
712
name: 'SideBar',
8-
source: new URL('./ui/components/SideBar', import.meta.url).pathname,
13+
source: './components/SideBar/index.jsx',
914
},
1015
MetaBar: {
1116
name: 'MetaBar',
12-
source: new URL('./ui/components/MetaBar', import.meta.url).pathname,
17+
source: './components/MetaBar/index.jsx',
1318
},
1419
CodeBox: {
1520
name: 'CodeBox',
16-
source: new URL('./ui/components/CodeBox', import.meta.url).pathname,
21+
source: './components/CodeBox.jsx',
1722
},
1823
CodeTabs: {
1924
name: 'CodeTabs',

src/generators/web/index.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Mustache from 'mustache';
88

99
import bundleCode from './build/bundle.mjs';
1010
import createASTBuilder from './build/generate.mjs';
11+
import { RESOLVE_DIR } from './constants.mjs';
1112

1213
/**
1314
* Executes server-side code in a safe, isolated context
@@ -17,11 +18,10 @@ import createASTBuilder from './build/generate.mjs';
1718
*/
1819
export async function executeServerCode(serverCode, require) {
1920
const { js: bundledServer } = await bundleCode(serverCode, { server: true });
20-
const variable = Math.random().toString(36).slice(2);
2121

2222
const executedFunction = new Function(
2323
'require',
24-
`let ${variable};${bundledServer}return ${variable};`
24+
`let code;${bundledServer}return code;`
2525
);
2626

2727
return executedFunction(require);
@@ -105,7 +105,7 @@ export default {
105105
'utf-8'
106106
);
107107
const astBuilders = createASTBuilder();
108-
const require = createRequire(import.meta.url);
108+
const require = createRequire(RESOLVE_DIR);
109109

110110
// Process all entries
111111
const results = [];

0 commit comments

Comments
 (0)