Skip to content

perf(backend): switch bundler from rollup to rolldown#94

Merged
gmaclennan merged 2 commits into
mainfrom
migrate/rolldown
Jun 22, 2026
Merged

perf(backend): switch bundler from rollup to rolldown#94
gmaclennan merged 2 commits into
mainfrom
migrate/rolldown

Conversation

@gmaclennan

Copy link
Copy Markdown
Member

Replaces rollup 4 with rolldown 1.1.2 for the on-device backend bundle.

Drops @rollup/plugin-{node-resolve,alias,commonjs,json,esm-shim} and rollup-plugin-esbuild in favour of rolldown built-ins (platform: node, resolve.alias, native cjs/json, output.minify). The custom plugins (addon-loader, sentry debug-ids, copy-assets, relocate-sourcemaps) and @sentry/rollup-plugin are unchanged — they run on rolldown's rollup-compatible hooks. rollup.config.ts is renamed to rolldown.config.ts.

Full backend build (Android debug + release + iOS) drops from ~36s to ~5s, roughly 6.9x.

Output verified equivalent: identical native addon rewrites (same 7 modules + pinned versions), static assets copied, sourcemaps relocated out of the asset trees, sentry debug ids embedded with the relocate plugin's sanity check passing, all 34 backend tests pass, and the minified entry is slightly smaller than rollup's.

Notes:

  • Plugin filenames are left as rollup-plugins/rollup-plugin-*.js (bundler-agnostic; renaming is cosmetic).
  • Not exercised on-device (needs nodejs-mobile); equivalence is static/structural.

🤖 Generated with Claude Code

Replaces rollup 4 with rolldown 1.1.2 for the on-device backend bundle.
Drops @rollup/plugin-{node-resolve,alias,commonjs,json,esm-shim} and
rollup-plugin-esbuild in favour of rolldown built-ins (platform: node,
resolve.alias, native cjs/json, output.minify). Custom plugins
(addon-loader, sentry debug-ids, copy-assets, relocate-sourcemaps) and
@sentry/rollup-plugin are unchanged — they run on rolldown's
rollup-compatible hooks.

Full backend build (Android debug + release + iOS) drops from ~36s to
~5s (~6.9x). Output verified equivalent: identical native addon
rewrites, static assets, relocated sourcemaps, embedded sentry debug
ids; all 34 backend tests pass; minified entry slightly smaller.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@socket-security

socket-security Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedrolldown@​1.1.2911007899100

View full report

@socket-security

socket-security Bot commented Jun 20, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @emnapi/runtime is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: backend/package-lock.jsonnpm/@comapeo/core@7.1.0npm/rolldown@1.1.2npm/@emnapi/runtime@1.11.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@emnapi/runtime@1.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@gmaclennan gmaclennan merged commit b86cb1d into main Jun 22, 2026
12 checks passed
@gmaclennan gmaclennan deleted the migrate/rolldown branch June 22, 2026 08:51
gmaclennan added a commit that referenced this pull request Jun 22, 2026
* main:
  perf(backend): switch bundler from rollup to rolldown (#94)
  fix: start fastify listening (#93)
gmaclennan added a commit that referenced this pull request Jun 22, 2026
…list (#106)

## Problem

The e2e **Build (Android)** and **Build (iOS)** jobs started failing on
`main` after #96
([run](https://github.com/digidem/comapeo-core-react-native/actions/runs/27943787594)):

```
While trying to resolve module `@comapeo/core-react-native` … this package itself
specifies a `main` module field that could not be resolved
(`apps/e2e/node_modules/@comapeo/core-react-native/build/index.js`). … none of these files exist
```

#96 added `--ignore-scripts` to the npm installs to stop dependency
install scripts (e.g. `better-sqlite3`) from building. But
`--ignore-scripts` is blunt: it **also skips this package's own
`prepare`**, which runs `expo-module build` to produce `build/`. The e2e
app imports `@comapeo/core-react-native` via the metro symlink in
`apps/e2e/metro.config.js` → the repo root, whose `main` is
`build/index.js`, so metro had nothing to resolve.

(#94 passed e2e fully — this was introduced by #96, not pre-existing.
`android-tests` and `ios-tests` were unaffected: their JVM unit tests /
debug instrumented APKs and the example-app iOS path don't bundle the
module's JS `main`.)

## Fix

Use npm's allowlist model instead of the blunt flag, which skips
**dependency** scripts while letting a package's **own** lifecycle
scripts run:

- **Upgrade CI npm to ≥ 11.16** (runners ship 11.13, which silently
ignores `strict-allow-scripts`).
- **Add `.npmrc` (`strict-allow-scripts=true`) + denied `allowScripts`**
to `apps/example` and `apps/e2e` — npm doesn't inherit a parent dir's
`.npmrc` for nested installs. (Root + `backend` allowlists already
landed in #96.) Every script-bearing dependency is denied; none are
needed, since native artifacts come from the prebuild pipeline, not
install scripts.
- **Drop `--ignore-scripts`** from all install steps and remove the
temporary explicit build step.
- **Bump `devEngines` npm floor** to `^11.16.0`.

## Bonus fix

Under `--ignore-scripts`, `apps/e2e`'s own `patch-package` postinstall
was also being skipped, so its `@mapeo/mock-data` patches weren't
applied. Strict mode runs own-package scripts, so those patches now
apply again.

## Validation

Locally on npm 11.17: root, `backend`, `apps/example`, and `apps/e2e`
all install cleanly under strict mode — dependency scripts skipped,
`better-sqlite3` not built, root `prepare` builds `build/`, and e2e's
mock-data patches apply. No lockfile churn.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
gmaclennan added a commit that referenced this pull request Jun 22, 2026
## Optic Release Automation

This **draft** PR is opened by Github action
[optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action).

A new **draft** GitHub release
[v1.0.0-pre.2](https://github.com/digidem/comapeo-core-react-native/releases/tag/untagged-c499977757c9745e56b2)
has been created.

Release author: @gmaclennan

#### If you want to go ahead with the release, please merge this PR.
When you merge:

- The GitHub release will be published

- The npm package with tag pre will be published according to the
publishing rules you have configured



- No major or minor tags will be updated as configured


#### If you close the PR

- The new draft release will be deleted and nothing will change

## What's Changed
* Android Testing Infrastructure & Bug Fixes by @gmaclennan in
#3
* chore: prebuild example/android; harden instrumented tests by
@gmaclennan in
#10
* Integrate @comapeo/core via IPC over Unix sockets by @gmaclennan in
#5
* chore: adjust repo setup by @achou11 in
#12
* chore: minor fixes based on expo-doctor by @achou11 in
#13
* Add iOS support & test infrastructure by @gmaclennan in
#6
* chore: add architecture docs & plans by @gmaclennan in
#11
* update some native deps used in backend by @achou11 in
#14
* iOS Phase 1: unified JS bundle + smoke test (simulator-only) by
@gmaclennan in
#15
* iOS Phase 2: xcframework Embed & Sign for native addons by @gmaclennan
in #16
* Phase 2 Android: jniLibs packaging + unified rollup loader plugin by
@gmaclennan in
#17
* chore: post-Phase-2 cleanup — comments, plan docs, agents.md by
@gmaclennan in
#33
* android: read abiFilters from reactNativeArchitectures (#30) by
@gmaclennan in
#35
* refactor: simplify build-backend.ts; rollup writes directly to native
asset trees by @gmaclennan in
#34
* chore: fix eslint configuration by @achou11 in
#41
* android: audit 16 KB page alignment on every shipped .so by
@gmaclennan in
#43
* Add rootkey persistence and lifecycle state management by @gmaclennan
in #36
* chore: move example app into apps directory by @achou11 in
#18
* refactor: per-component lifecycle state with derived ComapeoState by
@gmaclennan in
#47
* android: fold waitForFile into connect retry loop by @gmaclennan in
#52
* chore: add e2e testing app by @achou11 in
#49
* fix(android): drop setUnlockedDeviceRequired from rootkey wrapper key
by @gmaclennan in
#57
* fix(backend): cache stopping/error frames for late joiners by
@gmaclennan in
#58
* fix(ios-tests): wait for STOPPING before signalling node exit by
@gmaclennan in
#59
* fix(android): drain JNI stdio pumps before returning from node::Start
by @gmaclennan in
#60
* Sentry integration: Phase 1 + Phase 2a + Phase 2b by @gmaclennan in
#54
* feat(backend): polywasm-backed undici on iOS, re-enable maps plugin by
@gmaclennan in
#62
* ci: drop unreliable Android emulator snapshot caching by @gmaclennan
in #64
* feat(sentry): land Phase 3 — backend loader + RPC tracing by
@gmaclennan in
#63
* fix(ios-tests): serialise STOPPING/STOPPED observers in
testFullLifecycleStateTransitions by @gmaclennan in
#71
* use npm list instead of custom traversal to get native module versions
by @achou11 in
#70
* feat(sentry): land Phases 6 + 7a — Android exit reasons & iOS
MetricKit app-exit telemetry by @gmaclennan in
#72
* fix(sentry): make exit telemetry lossless and stop cross-process
clobbering by @gmaclennan in
#84
* chore(e2e): add e2e tests on browserstack via Maestro by @achou11 in
#56
* feat(sentry): migrate to @sentry/react-native v8; exit telemetry as
Application Metrics by @gmaclennan in
#73
* Map server integration by @gmaclennan in
#86
* chore(deps): upgrade to Expo SDK 56 (React Native 0.85) by @gmaclennan
in #87
* chore(ci): add release workflow by @gmaclennan in
#90
* chore: fix npm script and release build script by @gmaclennan in
#91
* chore(pack): don't try to package build files by @gmaclennan in
#92
* fix: start fastify listening by @gmaclennan in
#93
* perf(backend): switch bundler from rollup to rolldown by @gmaclennan
in #94
* fix(ci): ignore-scripts in ios npm installs by @gmaclennan in
#96
* fix(ci): replace --ignore-scripts with npm strict-allow-scripts
allowlist by @gmaclennan in
#106
* feat(config): let the consuming app supply the default project config
by @gmaclennan in
#95
* chore(release): merge prerelease branch. by @gmaclennan in
#110

## New Contributors
* @achou11 made their first contribution in
#12

**Full Changelog**:
https://github.com/digidem/comapeo-core-react-native/commits/v1.0.0-pre.2

<!--

<release-meta>{"id":342868678,"version":"v1.0.0-pre.2","npmTag":"pre","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta>
-->
@gmaclennan gmaclennan added the performance Performance improvement (changelog) label Jun 22, 2026
gmaclennan added a commit that referenced this pull request Jun 22, 2026
## Optic Release Automation

This **draft** PR is opened by Github action
[optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action).

A new **draft** GitHub release
[v1.0.0-pre.2](https://github.com/digidem/comapeo-core-react-native/releases/tag/untagged-352a6c41c12fd02dec37)
has been created.

Release author: @gmaclennan

#### If you want to go ahead with the release, please merge this PR.
When you merge:

- The GitHub release will be published

- The npm package with tag pre will be published according to the
publishing rules you have configured



- No major or minor tags will be updated as configured


#### If you close the PR

- The new draft release will be deleted and nothing will change

<!-- Release notes generated using configuration in .github/release.yml
at 7fe80b4 -->

## What's Changed
### 🚀 Features
* Integrate @comapeo/core via IPC over Unix sockets by @gmaclennan in
#5
* Add iOS support & test infrastructure by @gmaclennan in
#6
* iOS Phase 1: unified JS bundle + smoke test (simulator-only) by
@gmaclennan in
#15
* iOS Phase 2: xcframework Embed & Sign for native addons by @gmaclennan
in #16
* Phase 2 Android: jniLibs packaging + unified rollup loader plugin by
@gmaclennan in
#17
* android: read abiFilters from reactNativeArchitectures (#30) by
@gmaclennan in
#35
* Add rootkey persistence and lifecycle state management by @gmaclennan
in #36
* Sentry integration: Phase 1 + Phase 2a + Phase 2b by @gmaclennan in
#54
* feat(backend): polywasm-backed undici on iOS, re-enable maps plugin by
@gmaclennan in
#62
* feat(sentry): land Phase 3 — backend loader + RPC tracing by
@gmaclennan in
#63
* feat(sentry): land Phases 6 + 7a — Android exit reasons & iOS
MetricKit app-exit telemetry by @gmaclennan in
#72
* feat(sentry): migrate to @sentry/react-native v8; exit telemetry as
Application Metrics by @gmaclennan in
#73
* Map server integration by @gmaclennan in
#86
* feat(config): let the consuming app supply the default project config
by @gmaclennan in
#95
### 🐛 Bug Fixes
* fix(android): drop setUnlockedDeviceRequired from rootkey wrapper key
by @gmaclennan in
#57
* fix(backend): cache stopping/error frames for late joiners by
@gmaclennan in
#58
* fix(ios-tests): wait for STOPPING before signalling node exit by
@gmaclennan in
#59
* fix(android): drain JNI stdio pumps before returning from node::Start
by @gmaclennan in
#60
* fix(ios-tests): serialise STOPPING/STOPPED observers in
testFullLifecycleStateTransitions by @gmaclennan in
#71
* fix(sentry): make exit telemetry lossless and stop cross-process
clobbering by @gmaclennan in
#84
* fix: start fastify listening by @gmaclennan in
#93
* fix(ci): ignore-scripts in ios npm installs by @gmaclennan in
#96
* fix(ci): replace --ignore-scripts with npm strict-allow-scripts
allowlist by @gmaclennan in
#106
* fix(release): stop `npm pack --dry-run` leaking dry-run into backend
install by @gmaclennan in
#129
### ⚡ Performance
* perf(backend): switch bundler from rollup to rolldown by @gmaclennan
in #94
### ⬆️ Dependencies
* update some native deps used in backend by @achou11 in
#14
* chore(deps): upgrade to Expo SDK 56 (React Native 0.85) by @gmaclennan
in #87
### 🏗️ Maintenance
* Android Testing Infrastructure & Bug Fixes by @gmaclennan in
#3
* chore: prebuild example/android; harden instrumented tests by
@gmaclennan in
#10
* chore: adjust repo setup by @achou11 in
#12
* chore: minor fixes based on expo-doctor by @achou11 in
#13
* chore: add architecture docs & plans by @gmaclennan in
#11
* chore: post-Phase-2 cleanup — comments, plan docs, agents.md by
@gmaclennan in
#33
* refactor: simplify build-backend.ts; rollup writes directly to native
asset trees by @gmaclennan in
#34
* chore: fix eslint configuration by @achou11 in
#41
* android: audit 16 KB page alignment on every shipped .so by
@gmaclennan in
#43
* chore: move example app into apps directory by @achou11 in
#18
* refactor: per-component lifecycle state with derived ComapeoState by
@gmaclennan in
#47
* android: fold waitForFile into connect retry loop by @gmaclennan in
#52
* chore: add e2e testing app by @achou11 in
#49
* ci: drop unreliable Android emulator snapshot caching by @gmaclennan
in #64
* use npm list instead of custom traversal to get native module versions
by @achou11 in
#70
* chore(e2e): add e2e tests on browserstack via Maestro by @achou11 in
#56
* chore(ci): add release workflow by @gmaclennan in
#90
* chore: fix npm script and release build script by @gmaclennan in
#91
* chore(pack): don't try to package build files by @gmaclennan in
#92
* chore(release): merge prerelease branch. by @gmaclennan in
#110
* ci(e2e): retry BrowserStack builds on infra-class flakes by
@gmaclennan in
#113
### Other Changes
* ci: derive changelog labels from PR titles + add Dependabot by
@gmaclennan in
#114

## New Contributors
* @achou11 made their first contribution in
#12
* @optic-release-automation[bot] made their first contribution in
#112

**Full Changelog**:
https://github.com/digidem/comapeo-core-react-native/commits/v1.0.0-pre.2

<!--

<release-meta>{"id":342970724,"version":"v1.0.0-pre.2","npmTag":"pre","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta>
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Performance improvement (changelog)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant