Skip to content

refactor(website-server): Replace esbuild with Rolldown for bundling#1070

Closed
yamadashy wants to merge 3 commits intomainfrom
feat/website-rolldown-bundler
Closed

refactor(website-server): Replace esbuild with Rolldown for bundling#1070
yamadashy wants to merge 3 commits intomainfrom
feat/website-rolldown-bundler

Conversation

@yamadashy
Copy link
Owner

@yamadashy yamadashy commented Jan 3, 2026

Summary

  • Replace esbuild with Rolldown 1.0.0-beta.58 for bundling
  • Apply aggressive tree-shaking optimizations
  • Bundle size: 5.93 MB (Rolldown with minify)

Detailed Bundle Size Comparison

Overall Results

Bundler No Minify With Minify Reduction
esbuild 10.32 MB 5.15 MB 50.1%
Rolldown 9.65 MB 5.93 MB 38.5%

Tree Shaking Comparison (No Minify)

Bundler Size
esbuild 10.32 MB
Rolldown 9.65 MB

Winner: Rolldown (6.5% smaller, 0.67 MB difference)

Rolldown's aggressive treeshake: { moduleSideEffects: false } removes more unused code.

Minification Comparison

Bundler Size
esbuild 5.15 MB
Rolldown 5.93 MB

Winner: esbuild (13.1% smaller, 0.78 MB difference)

esbuild's minifier (5+ years mature) produces significantly better compression than Rolldown's oxc-based minifier.

Technical Analysis

Why Rolldown has better tree-shaking

  • moduleSideEffects: false aggressively marks modules as side-effect-free
  • Better static analysis for dead code elimination

Why esbuild has better minification

  • More sophisticated variable mangling algorithms
  • Better constant folding and expression simplification
  • 5+ years of production optimization

Conclusion

For Cloud Run cold start optimization, final bundle size matters most. Despite Rolldown's superior tree-shaking, esbuild's mature minifier wins overall.

The esbuild + minify approach was adopted in PR #1069.

Checklist

  • Run npm run test
  • Run npm run lint

Migrate the website server bundling from esbuild to Rolldown 1.0.0-beta.58.
Rolldown produces a 5% smaller bundle (10.32MB → 9.8MB) while maintaining
the same functionality.

Key changes:
- Update bundle.mjs to use Rolldown's API with inlineDynamicImports
- Remove esbuild dependency, add rolldown ^1.0.0-beta.58
Apply aggressive tree-shaking and minification options:
- treeshake.moduleSideEffects: false for aggressive dead code elimination
- compress.dropConsole/dropDebugger: true (winston handles logging)
- mangle.toplevel: true for maximum size reduction
- legalComments: 'none' to strip license comments
- minifyInternalExports: true

Bundle size reduced from 10.32 MB (esbuild) to 6.0 MB (42% reduction).
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

The pull request replaces esbuild with Rolldown as the bundler for the website server. The bundler dependency is updated in package.json, and the bundling script is reimplemented to use Rolldown with equivalent configuration parameters for tree-shaking, minification, and output formatting.

Changes

Cohort / File(s) Summary
Build Tooling Migration
website/server/package.json, website/server/scripts/bundle.mjs
Replaces esbuild with Rolldown as the primary bundler. package.json swaps dependencies; bundle.mjs replaces bundleWithEsbuild function with bundleWithRolldown, using Rolldown's API with equivalent tree-shaking, minification (treeshake, compress, mangle, dropConsole, dropDebugger), and output configuration. Banner handling and WASM collection steps preserved.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • PR #1069: Modifies esbuild minification and tree-shaking options in website/server/scripts/bundle.mjs, directly affecting the same bundling configuration now being replaced with Rolldown.
  • PR #1067: Adds Docker Compose setup and npm script for running/testing the bundled server output, which depends on the bundling workflow being updated here.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: replacing esbuild with Rolldown for bundling in the website server, which matches the core objective of the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The pull request description is comprehensive and exceeds basic requirements with detailed technical analysis, bundle size comparisons, and checklist completion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/website-rolldown-bundler

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @yamadashy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the website server's bundling process by migrating from esbuild to Rolldown. The primary goal is to leverage Rolldown's advanced optimization features, including aggressive tree-shaking and minification, to produce a more compact and efficient server bundle. This change aims to improve performance by reducing the overall size of the deployed server assets, and this specific PR is for comparison purposes.

Highlights

  • Bundler Replacement: Replaced esbuild with Rolldown (version 1.0.0-beta.58) as the primary bundler for the website server.
  • Optimization: Implemented aggressive tree-shaking and minification optimizations using Rolldown to reduce the final bundle size.
  • Bundle Size Reduction: Achieved a final bundle size of 6.0 MB, demonstrating the optimization benefits of Rolldown.
  • Purpose of PR: This pull request serves as a comparison for evaluating Rolldown and is intended to be closed.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the bundling process by replacing esbuild with Rolldown. The changes are well-contained and the new bundling script implements aggressive optimization and minification as intended. My review focuses on the implications of this change. I've suggested pinning the rolldown dependency since it's a beta version to ensure build stability. I've also added comments regarding the new rolldown configuration: one about the missing target option (which was present in the esbuild config) that could affect runtime compatibility, and another about the aggressive moduleSideEffects setting for tree-shaking which could have unintended consequences. Overall, this is a good exploratory change, and my comments are intended to highlight important considerations for using Rolldown in production.

Comment on lines +44 to 75
const build = await rolldown({
input: join(rootDir, 'dist/index.js'),
platform: 'node',
target: 'node24',
format: 'esm',
outfile: join(distBundledDir, 'server.mjs'),
external: ['tinypool', 'tiktoken'],
banner: { js: banner },
// Aggressive tree-shaking
treeshake: {
moduleSideEffects: false,
annotations: true,
},
});

await build.write({
dir: distBundledDir,
format: 'esm',
entryFileNames: 'server.mjs',
inlineDynamicImports: true,
banner,
// Minification & optimization
minify: {
compress: {
dropConsole: true,
dropDebugger: true,
unused: true,
},
mangle: {
toplevel: true,
},
},
legalComments: 'none',
minifyInternalExports: true,
sourcemap: false,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The previous esbuild configuration included target: 'node24', which ensures the bundled code is compatible with Node.js v24 by transpiling newer JavaScript syntax. The new rolldown configuration doesn't have an equivalent target option.

This means that if your source code or its dependencies use JavaScript features newer than what's supported by your target Node.js environment, the bundle might fail at runtime. While tsc handles transpilation for your own code, it might not for dependencies.

Since this PR is for comparison, this might be an acceptable difference, but it's a critical point to be aware of for production builds. You might need to ensure your tsconfig.json is configured to output compatible JavaScript, and that all dependencies are also compatible.

"@typescript/native-preview": "^7.0.0-dev.20251226.1",
"esbuild": "^0.27.2",
"rimraf": "^6.1.2",
"rolldown": "^1.0.0-beta.58",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a caret ^ with a beta version like ^1.0.0-beta.58 can be risky. Beta versions often introduce breaking changes without a major version bump. It's safer to pin the exact version to ensure reproducible builds and avoid unexpected issues. This is especially important for a bundler, which is a critical part of your build process.

Suggested change
"rolldown": "^1.0.0-beta.58",
"rolldown": "1.0.0-beta.58",

Comment on lines +49 to +52
treeshake: {
moduleSideEffects: false,
annotations: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Setting moduleSideEffects: false is a very aggressive tree-shaking strategy. It assumes that no modules in your dependency graph have side effects, which can be unsafe. If any dependency relies on module-level code execution for initialization (e.g., polyfills, global setup), it might be incorrectly removed, leading to runtime errors.

Consider using a more granular approach, like 'no-external', or providing an array of modules that are known to have side effects if you encounter issues. For a library bundle, 'no-external' is often a safer default. For an application, you need to be sure about your dependencies.

Align Rolldown minification settings with esbuild for fair comparison:
- Use simple `minify: true` instead of complex options
- Use `legalComments: 'inline'` (Rolldown doesn't support 'eof')
- Keep aggressive tree-shaking as Rolldown's strength

Bundle size comparison:
- esbuild + minify: 5.14 MB
- Rolldown + minify: 6.0 MB
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Jan 3, 2026

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: ae99656
Status: ✅  Deploy successful!
Preview URL: https://0ed65daa.repomix.pages.dev
Branch Preview URL: https://feat-website-rolldown-bundle.repomix.pages.dev

View logs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
website/server/package.json (1)

29-29: Rolldown is beta; consider pinning version for consistency.

The beta version 1.0.0-beta.58 exists and resolves correctly. However, the caret range (^) allows automatic updates to future beta releases (e.g., beta.59, beta.60), which may introduce breaking changes.

For a devDependency (build tool), consider pinning to the exact version to prevent unexpected updates during development.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 218f0db and 69945b9.

⛔ Files ignored due to path filters (1)
  • website/server/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • website/server/package.json
  • website/server/scripts/bundle.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (7)
website/server/scripts/bundle.mjs (7)

13-13: LGTM!

The import statement correctly references the Rolldown package.


29-42: LGTM!

The function rename is appropriate, and the ESM banner for CommonJS compatibility is correctly preserved.


114-114: LGTM!

The function call correctly references the new Rolldown bundler function.


44-75: Remove verification request — the actual code does not match the review snippet.

The code snippet in the review shows a nested minify object with compress and mangle fields. However, the actual code in website/server/scripts/bundle.mjs (lines 44-75) uses minify: true (a boolean) and legalComments: 'inline' instead. While Rolldown 1.0.0-beta.58 does support the nested structure described in the review, that configuration is not present in the codebase.

Likely an incorrect or invalid review comment.


62-67: The code snippet referenced in this review comment does not exist in the file. The actual bundle.mjs uses minify: true (a boolean) with Rolldown, not an object with compress: { dropConsole: true, ... }. Rolldown does not support the detailed minification configuration (dropConsole, dropDebugger, etc.) that this comment addresses.

The concern about console.log removal is not applicable here since there is no dropConsole setting configured in this build script.

Likely an incorrect or invalid review comment.


68-70: The code referenced in this review comment does not exist in the current state of bundle.mjs. Lines 68-70 contain a console.log statement and function documentation, not a mangle configuration. A search of the entire codebase confirms that no mangle: { toplevel: true } configuration exists. The bundler configuration in bundle.mjs uses Rolldown's minify: true without any mangle settings.

Likely an incorrect or invalid review comment.


48-52: Tree-shaking configuration is safe for this codebase.

moduleSideEffects: false is appropriate here because:

  • Hono middleware (compress, timeout, cors) are function imports explicitly called via app.use(), not import-time side-effect registration
  • Dependencies like hono and @hono/node-server do not declare "sideEffects": false in their package.json, so Rolldown respects their own side-effect requirements
  • No decorator patterns, global polyfills, or import-time initialization in the source code

The configuration is not aggressive in an unsafe way; it aligns with how Hono and its middleware are actually used.

Likely an incorrect or invalid review comment.

@yamadashy yamadashy closed this Jan 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant