Skip to content

Commit 7af28a7

Browse files
committed
refactor(build): replace esbuild with rolldown minify and csso
1 parent 57b2e58 commit 7af28a7

14 files changed

Lines changed: 205 additions & 420 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @file Rolldown configuration for the meander CLI bundle — one
3+
* real bundle, `dist/cli.mjs`, the consumer-install entry
4+
* (see package.json `bin`). `scripts/repo/build.mts` imports
5+
* this config and calls rolldown's `build()` with it; type
6+
* declarations are emitted separately via `tsc`.
7+
* Externals:
8+
*
9+
* - node built-ins (never bundled).
10+
* - csso / mermaid / puppeteer / rolldown / svgo — loaded dynamically by opt-in
11+
* features. Bundling them would drag in Chromium downloads (puppeteer) or
12+
* force mermaid's DOM-heavy runtime into the CLI for everyone. Consumers
13+
* install `rolldown` themselves only if they enable the JS minify pass;
14+
* `csso` and `svgo` ship as direct meander deps but stay external so their
15+
* (larger) parser code isn't duplicated into cli.mjs.
16+
* - @valtown/sdk — only used by deploy-val. Kept external so the CLI stays
17+
* small for the 90% of users who only run generate / serve / publish.
18+
*/
19+
20+
import { builtinModules } from 'node:module'
21+
import path from 'node:path'
22+
import { fileURLToPath } from 'node:url'
23+
24+
import type { BuildOptions } from 'rolldown'
25+
26+
const configDir = path.dirname(fileURLToPath(import.meta.url))
27+
const rootPath = path.join(configDir, '..', '..')
28+
29+
const nodeBuiltins = [
30+
...builtinModules,
31+
...builtinModules.map(m => `node:${m}`),
32+
]
33+
34+
/**
35+
* Optional + deploy-only deps. Never bundled.
36+
*/
37+
export const runtimeExternals = [
38+
'@valtown/sdk',
39+
'csso',
40+
'mermaid',
41+
'puppeteer',
42+
'rolldown',
43+
'svgo',
44+
]
45+
46+
/* `external` string entries match the import specifier EXACTLY — a bare
47+
* 'rolldown' entry does not cover src/minify.mts's `import('rolldown/
48+
* experimental')`. Bundling that subpath would inline rolldown's own napi
49+
* loader into cli.mjs, where its binary-lookup paths (resolved relative to
50+
* rolldown's own package dir) no longer point anywhere real. The regex
51+
* externalizes every 'rolldown' + 'rolldown/<subpath>' specifier so the
52+
* whole package stays a real runtime import. */
53+
const rolldownSpecifier = /^rolldown(?:\/|$)/
54+
55+
export const cliBuildConfig: BuildOptions = {
56+
external: [...nodeBuiltins, ...runtimeExternals, rolldownSpecifier],
57+
input: path.join(rootPath, 'src/cli.mts'),
58+
output: {
59+
banner: '#!/usr/bin/env node',
60+
// Internal dynamic imports fold into the single-file bundle
61+
// (external opt-in deps stay dynamic at runtime).
62+
codeSplitting: false,
63+
file: path.join(rootPath, 'dist/cli.mjs'),
64+
format: 'esm',
65+
minify: false,
66+
sourcemap: false,
67+
},
68+
platform: 'node',
69+
}

.config/repo/socket-wheelhouse.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,5 @@
33
"schemaVersion": 1,
44
"repoName": "meander",
55
"repo": { "type": "solo" },
6-
"build": { "from": "npm-registry", "type": "js" },
7-
"vite": {
8-
"allowEsbuild": "esbuild is a direct devDep powering the opt-in minify pass (src/minify.mts transforms inline <script> bodies via dynamic import, skipping when absent) and the deploy-val bundle step (src/deploy-val.mts); the build bundler is rolldown"
9-
}
6+
"build": { "from": "npm-registry", "type": "js" }
107
}

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
meander generates annotated code-walkthrough pages with a live comment system, deployed to Val Town.
125125

126126
- **Layout**: generator + CLI in `src/`, flat, one module per concern (`generate`, `serve`, `deploy-val`, `minify`, `crypto`/`shamir`); the Val Town runtime is `assets/val/`, shipped in the tarball.
127-
- **Build**: `pnpm run build` (rolldown via `scripts/repo/build.mts`); esbuild is a devDep the minify pass and the deploy-val bundle dynamic-import behind the `vite.allowEsbuild` opt-in.
127+
- **Build**: `pnpm run build` (rolldown via `scripts/repo/build.mts` + `.config/repo/rolldown.cli.config.mts`); the minify pass and the deploy-val bundle step both dynamic-import `rolldown` too.
128128
- **Deploy**: publishing to npm goes through the GitHub Actions pipeline only (`prepublishOnly` blocks local); Val Town deploys via `src/deploy-val.mts` (`.github/workflows/valtown.yml`).
129129
- **Commands**: `pnpm test` / `pnpm run check` / `pnpm run cover` / `pnpm run type`; the Val Town runtime tests live in `test/val/` and run with the vitest suite.
130130
- **Docs**: architecture / operating / deploying / encryption detail in `docs/*.md`.

docs/features.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -532,14 +532,14 @@ reloads.
532532
**Opt-in.** When enabled, meander runs a final minification
533533
pass against emitted assets:
534534
535-
- **Inline `<script>`** bodies — esbuild, target es2022, strips
536-
comments.
535+
- **Inline `<script>`** bodies + **`sw.js`** — rolldown's
536+
minifier, strips comments.
537537
- **Inline `<svg>`** elements — SVGO with `preset-default`
538538
(cleanupIds + removeUnknownsAndDefaults overridden off so
539539
mermaid diagrams keep their edge-to-node links and the
540540
preserveAspectRatio variants browsers read).
541-
- **External `meander.css`** + **`sw.js`** — esbuild on
542-
the file bytes before they're written.
541+
- **External `meander.css`** — csso on the file bytes before
542+
they're written.
543543
544544
Typical savings on the fixture:
545545
@@ -581,11 +581,11 @@ touch content).
581581
582582
### Dep notes
583583
584-
`svgo` ships as a direct dep — the SVG minify pass is always
585-
available. `esbuild` is loaded dynamically; if a consumer
586-
enables `config.minify.js` or `config.minify.css` without
587-
installing esbuild themselves, the pass logs + skips rather
588-
than aborting the build.
584+
`svgo` and `csso` ship as direct deps — the SVG and CSS minify
585+
passes are always available. `rolldown` is loaded dynamically;
586+
if a consumer enables `config.minify.js` without installing
587+
rolldown themselves, that pass logs + skips rather than
588+
aborting the build.
589589
590590
## Subresource Integrity (SRI)
591591

example/consumer-build/README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Consumer build integration
22

33
How to wire `meander generate` into your project's own build
4-
pipeline (CI, Makefile, esbuild bundle, whatever).
4+
pipeline (CI, Makefile, rolldown bundle, whatever).
55

66
meander is usable as a CLI **and** as a library. Pick whichever
77
matches the rest of your toolchain.
@@ -48,8 +48,9 @@ node --experimental-strip-types scripts/build-walkthrough.mts
4848

4949
## Option 3 — Minify your pages at emit time
5050

51-
meander can run inline scripts through esbuild and inline SVGs
52-
through svgo at emit time — enable via the config:
51+
meander can run inline scripts through rolldown's minifier,
52+
inline SVGs through svgo, and `meander.css` through csso at
53+
emit time — enable via the config:
5354

5455
```json
5556
{
@@ -63,16 +64,16 @@ through svgo at emit time — enable via the config:
6364

6465
Requirements:
6566

66-
- `svgo` is already installed as a meander dep — no action needed
67-
for `svg: true`.
68-
- For `js: true` or `css: true`, install esbuild in your project:
67+
- `svgo` and `csso` are already installed as meander deps — no
68+
action needed for `svg: true` or `css: true`.
69+
- For `js: true`, install rolldown in your project:
6970

7071
```bash
71-
pnpm add -D esbuild
72+
pnpm add -D rolldown
7273
```
7374

74-
meander loads it dynamically. If esbuild isn't available, the
75-
JS/CSS pass logs + skips rather than aborting the build.
75+
meander loads it dynamically. If rolldown isn't available, the
76+
JS pass logs + skips rather than aborting the build.
7677

7778
## GitHub Pages deploy
7879

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"dependencies": {
7878
"@sinclair/typebox": "catalog:",
7979
"@valtown/sdk": "1.14.0",
80+
"csso": "5.0.5",
8081
"marked": "18.0.7",
8182
"node-html-parser": "7.1.0",
8283
"svgo": "4.0.2"
@@ -90,6 +91,7 @@
9091
"@socketsecurity/lib-stable": "catalog:",
9192
"@socketsecurity/sdk": "catalog:",
9293
"@socketsecurity/sdk-stable": "catalog:",
94+
"@types/csso": "5.0.4",
9395
"@types/mdast": "catalog:",
9496
"@types/node": "catalog:",
9597
"@types/semver": "catalog:",
@@ -101,7 +103,6 @@
101103
"c8": "catalog:",
102104
"chrome-devtools-mcp": "catalog:",
103105
"ecc-agentshield": "1.4.0",
104-
"esbuild": "0.25.12",
105106
"fast-check": "catalog:",
106107
"fast-glob": "3.3.3",
107108
"magic-string": "catalog:",
@@ -154,7 +155,6 @@
154155
},
155156
"allowScripts": {
156157
"cpu-features": false,
157-
"esbuild": true,
158158
"protobufjs": false,
159159
"puppeteer": false,
160160
"ssh2": false

0 commit comments

Comments
 (0)