Skip to content

Commit 6b1b38f

Browse files
authored
chore: add rolldown customization (#829)
* chore: add rolldown customization * fixup!
1 parent e2063d4 commit 6b1b38f

7 files changed

Lines changed: 115 additions & 27 deletions

File tree

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@node-core/doc-kit",
33
"type": "module",
4-
"version": "1.3.8",
4+
"version": "1.3.9",
55
"repository": {
66
"type": "git",
77
"url": "git+https://github.com/nodejs/doc-kit.git"

src/generators/web/README.md

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@ The `web` generator transforms JSX AST entries into complete web bundles, produc
66

77
The `web` generator accepts the following configuration options:
88

9-
| Name | Type | Default | Description |
10-
| ----------------- | --------- | --------------------------------------------- | --------------------------------------------------------------------- |
11-
| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
12-
| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
13-
| `project` | `string` | `'Node.js'` | Project name used in page titles and the version selector |
14-
| `title` | `string` | `'{project} v{version} Documentation'` | Title template for HTML pages (supports `{project}`, `{version}`) |
15-
| `useAbsoluteURLs` | `boolean` | `false` | When `true`, all internal links use absolute URLs based on `baseURL` |
16-
| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links |
17-
| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links |
18-
| `head` | `object` | See below | Configurable `<meta>`, `<link>`, and raw markup for the document head |
19-
| `lightningcss` | `object` | `{}` | Options spread into LightningCSS while bundling CSS (see below) |
20-
| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization |
21-
| `virtualImports` | `object` | `{}` | Additional virtual module mappings merged into the build |
9+
| Name | Type | Default | Description |
10+
| ----------------- | --------- | --------------------------------------------- | ------------------------------------------------------------------------ |
11+
| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
12+
| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
13+
| `project` | `string` | `'Node.js'` | Project name used in page titles and the version selector |
14+
| `title` | `string` | `'{project} v{version} Documentation'` | Title template for HTML pages (supports `{project}`, `{version}`) |
15+
| `useAbsoluteURLs` | `boolean` | `false` | When `true`, all internal links use absolute URLs based on `baseURL` |
16+
| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links |
17+
| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links |
18+
| `head` | `object` | See below | Configurable `<meta>`, `<link>`, and raw markup for the document head |
19+
| `lightningcss` | `object` | `{}` | Options spread into LightningCSS while bundling CSS (see below) |
20+
| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization |
21+
| `virtualImports` | `object` | `{}` | Additional virtual module mappings merged into the build |
22+
| `rolldown` | `object` | `{}` | Options merged into the Rolldown build — extra plugins, etc. (see below) |
2223

2324
#### `head`
2425

@@ -95,6 +96,63 @@ To apply more than one visitor, compose them with LightningCSS's
9596

9697
[lightningcss]: https://lightningcss.dev/transforms.html
9798

99+
#### Custom Rolldown options
100+
101+
The `rolldown` object is merged into the [Rolldown][rolldown] `build` call used
102+
for **both** the client and server bundles, so you can register extra plugins,
103+
inject compile-time constants, add module aliases, or set any other Rolldown
104+
option. The same config is applied to both builds — branch inside a plugin (or
105+
read the `SERVER`/`CLIENT` defines) if you need per-target behavior.
106+
107+
The merge follows these rules:
108+
109+
- **`plugins`** are registered after the built-in virtual-module plugin (so
110+
they see the in-memory entry modules) and before the CSS loader.
111+
- **`transform.define`** and **`resolve.alias`** are merged key-by-key, so you
112+
can add entries without dropping the generator's. The built-in `SERVER`/
113+
`CLIENT` defines and the `react`/`react-dom``preact/compat` aliases
114+
(plus anything from `imports`) always win.
115+
- **All other options** (e.g. `output.minify`, `treeshake`, `external`,
116+
`platform`, `logLevel`) override the generator's defaults.
117+
- **`input`** and the built-in plugins are managed by the generator and cannot
118+
be overridden.
119+
120+
> Functions (plugins, hooks, alias resolvers, etc.) are allowed here because the
121+
> `web` generator runs entirely on the main thread. Unlike the chunked
122+
> generators, its config is never serialized to a worker, so values that can't
123+
> be structured-cloned are safe. Keep this in mind if `web` ever gains parallel
124+
> processing: function-valued options would then need a serializable form.
125+
126+
```js
127+
// doc-kit.config.mjs
128+
import myRolldownPlugin from './my-rolldown-plugin.mjs';
129+
130+
export default {
131+
web: {
132+
rolldown: {
133+
// Register additional plugins (run after the built-in ones).
134+
plugins: [myRolldownPlugin()],
135+
136+
// Inject extra compile-time constants (merged with SERVER/CLIENT).
137+
transform: {
138+
define: {
139+
'process.env.ANALYTICS_ID': JSON.stringify('UA-XXXXX'),
140+
},
141+
},
142+
143+
// Extend module resolution with custom aliases.
144+
resolve: {
145+
alias: {
146+
'@components': './src/components',
147+
},
148+
},
149+
},
150+
},
151+
};
152+
```
153+
154+
[rolldown]: https://rolldown.rs/
155+
98156
#### Default `imports`
99157

100158
| Alias | Default | Description |

src/generators/web/index.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,9 @@ export default createLazyGenerator({
8686
'#theme/Layout': join(import.meta.dirname, './ui/components/Layout'),
8787
},
8888
virtualImports: {},
89+
90+
// Options merged into the Rolldown build (client and server), e.g. extra
91+
// `plugins`. See the README for the merge semantics.
92+
rolldown: {},
8993
},
9094
});

src/generators/web/types.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { BundleAsyncOptions, CustomAtRules } from 'lightningcss-wasm';
2+
import type { BuildOptions } from 'rolldown';
23

34
import type { JSXContent } from '../jsx-ast/utils/buildContent.mjs';
45

@@ -33,6 +34,9 @@ export type Configuration = {
3334
>;
3435
imports: Record<string, string>;
3536
virtualImports: Record<string, string>;
37+
// Options merged into the Rolldown build for the client and server bundles.
38+
// See the web generator README for the merge semantics.
39+
rolldown: Partial<BuildOptions>;
3640
};
3741

3842
export type Generator = GeneratorMetadata<

src/generators/web/utils/bundle.mjs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,24 @@ export default async function bundleCode(
3939
) {
4040
const config = getConfig('web');
4141

42+
const { rolldown = {} } = config;
43+
4244
const result = await build({
45+
...rolldown,
46+
4347
// Entry points: array of virtual module names that the virtual plugin provides
4448
input: Array.from(codeMap.keys()),
4549

4650
// Experimental features: import maps for client, none for server
4751
experimental: {
4852
chunkImportMap: !server,
53+
...rolldown.experimental,
4954
},
5055

5156
checks: {
5257
// Disable plugin timing logs for cleaner output. This can be re-enabled for debugging performance issues.
5358
pluginTimings: false,
59+
...rolldown.checks,
5460
},
5561

5662
// Output configuration
@@ -63,25 +69,33 @@ export default async function bundleCode(
6369
// Minify output only for browser builds to optimize file size.
6470
// Server builds are usually not minified to preserve stack traces and debuggability.
6571
minify: !server,
72+
73+
...rolldown.output,
6674
},
6775

6876
// Platform informs Rolldown of the environment-specific code behavior:
6977
// - 'node' enables things like `require`, and skips polyfills.
7078
// - 'browser' enables inlining of polyfills and uses native browser features.
71-
platform: server ? 'node' : 'browser',
79+
platform: rolldown.platform ?? (server ? 'node' : 'browser'),
7280

7381
// External dependencies to exclude from bundling.
7482
// These are expected to be available at runtime in the server environment.
7583
// This reduces bundle size and avoids bundling shared server libs.
76-
external: server
77-
? ['preact', 'preact-render-to-string', '@node-core/ui-components']
78-
: [],
84+
external:
85+
rolldown.external ??
86+
(server
87+
? ['preact', 'preact-render-to-string', '@node-core/ui-components']
88+
: []),
7989

8090
transform: {
91+
...rolldown.transform,
92+
8193
// Inject global compile-time constants that will be replaced in code.
8294
// These are useful for tree-shaking and conditional branching.
8395
// Be sure to update type declarations (`types.d.ts`) if these change.
8496
define: {
97+
...rolldown.transform?.define,
98+
8599
// Boolean flags used for conditional logic in source code:
86100
// Example: `if (SERVER) {...}` or `if (CLIENT) {...}`
87101
// These flags help split logic for server/client environments.
@@ -93,25 +107,28 @@ export default async function bundleCode(
93107
// JSX transformation configuration.
94108
// `'react-jsx'` enables the automatic JSX runtime, which doesn't require `import React`.
95109
// Since we're using Preact via aliasing, this setting works well with `preact/compat`.
96-
jsx: 'react-jsx',
110+
jsx: rolldown.transform?.jsx ?? 'react-jsx',
97111
},
98112

99113
// Module resolution configuration.
100114
resolve: {
101115
// exports condition to use
102116
conditionNames: ['rolldown'],
103117

118+
// Tell the bundler where to find node_modules.
119+
// We use our custom `NODE_MODULES`, and then the cwd's `node_modules`.
120+
modules: [await getNodeModules(), 'node_modules'],
121+
122+
...rolldown.resolve,
123+
104124
// Alias react imports to preact/compat for smaller bundle sizes.
105125
// Explicit jsx-runtime aliases are required for the automatic JSX transform.
106126
alias: {
107127
react: 'preact/compat',
108128
'react-dom': 'preact/compat',
129+
...rolldown.resolve?.alias,
109130
...config.imports,
110131
},
111-
112-
// Tell the bundler where to find node_modules.
113-
// We use our custom `NODE_MODULES`, and then the cwd's `node_modules`.
114-
modules: [await getNodeModules(), 'node_modules'],
115132
},
116133

117134
// Array of plugins to apply during the build.
@@ -123,13 +140,15 @@ export default async function bundleCode(
123140
...virtualImports,
124141
}),
125142

143+
...(rolldown.plugins ?? []),
144+
126145
// Load CSS imports via the custom plugin.
127146
// This plugin will collect imported CSS files and return them as `source` chunks.
128147
cssLoader(),
129148
],
130149

131150
// Enable tree-shaking to remove unused code
132-
treeshake: true,
151+
treeshake: rolldown.treeshake ?? true,
133152

134153
// Return chunks in memory instead of writing to disk
135154
write: false,

src/generators/web/utils/css.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ export default () => {
5959
}
6060

6161
// Read the raw CSS file from disk
62-
const source = await readFile(id, 'utf8');
62+
const source = await (lightningcss.resolver?.read ?? readFile)(
63+
id,
64+
'utf8'
65+
);
6366

6467
// Use Lightning CSS to compile the file with CSS Modules enabled
6568
const { code, exports } = await bundleAsync({

0 commit comments

Comments
 (0)