Skip to content

[No QA] Migrate web builds and Storybook from Webpack to Rspack/Rsbuild#95319

Merged
chuckdries merged 23 commits into
mainfrom
rory-webpack-to-rspack-poc
Jul 10, 2026
Merged

[No QA] Migrate web builds and Storybook from Webpack to Rspack/Rsbuild#95319
chuckdries merged 23 commits into
mainfrom
rory-webpack-to-rspack-poc

Conversation

@roryabraham

@roryabraham roryabraham commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Migrates web production builds and Storybook off Webpack onto Rsbuild (built on Rspack, a Rust-based, largely Webpack-compatible bundler). App build and Storybook now share one Rsbuild config.

App web builds

  • config/rsbuild/rsbuild.common.ts replaces webpack.common.ts: getSharedConfiguration() (defines, aliases, Babel/SVGR, asset rules — shared with Storybook) + getCommonConfiguration() (app-specific: HTML template, service worker, Sentry, code-splitting, preload/prefetch).
  • config/rsbuild/rsbuild.config.ts is the CLI entry point; web-server layers on dev-only config (HTTPS, proxy, persistent cache) via Rsbuild's native fields.
  • New RspackPreloadPlugin replaces @vue/preload-webpack-plugin.
  • html-webpack-plugin → Rspack's native HtmlRspackPlugin; custom template values move into a templateParameters function.
  • Everything else (CustomVersionFilePlugin/ModuleInitTimingPlugin, loaders, code-splitting) is a straight port to Rspack builtins: CopyRspackPlugin, CssExtractRspackPlugin, SwcJsMinimizerRspackPlugin, ReactRefreshRspackPlugin, @aaroon/workbox-rspack-plugin, output.clean: true.

Storybook

Migrated to storybook-react-rsbuild.

  • .storybook/rsbuild.config.ts imports getSharedConfiguration() directly.
  • Babel goes through @rsbuild/plugin-babel (React Compiler, react-native-web); SVG imports through @rsbuild/plugin-svgr.
  • Bumped storybook/@storybook/* 10.1.1010.4.6 (required by storybook-react-rsbuild); dropped @storybook/react-webpack5 and @storybook/addon-webpack5-compiler-babel.

Dev-server crash-recovery removal

start-dev-with-auto-restart.sh (#67373) wrapped web-server in a crash-restart loop because webpack-dev-server's JS-heap bookkeeping grew unboundedly across hot reloads. Rspack/Rsbuild keep that bookkeeping in Rust-managed native memory, so I stress-tested 60-260 back-to-back HMR recompiles directly. With Rsbuild heap plateaued at ~220-247MB regardless of whether gc() was enabled. So I removed ForceGarbageCollectionPlugin, --expose-gc, and the auto-restart wrapper entirely. web-server now runs rsbuild dev directly.

Build profiling

  • time-analytics-webpack-plugin isn't needed — Rspack has built-in profiling via RSPACK_PROFILE=OVERVIEW npm run build. Documented in contributingGuides/SETUP_WEB.md.
  • webpack-bundle-analyzerRsdoctor — first-party, also surfaces loader/plugin timing and duplicate-package detection.

Benchmark results

Webpack Rsbuild
App build, cold 301.5s 180.1s
App build, warm n/a - no cache 20.0s
Storybook build 117.6s 28.4s
Dev-server startup, warm 8.65s ~3s
  • Dev-server startup isn't quite an apples-to-apples number. Webpack's dev server eagerly compiles the entire app graph (8.65s warm). Rsbuild defaults dev.lazyCompilation to {imports: true, entries: false}: the entry compiles eagerly, but everything behind a dynamic import() (lazy screens, locale files) gets a proxy stub and compiles on first real use via HMR hot-update. Verified with a real headless-browser load: chunk boundaries are unchanged, every lazy module resolved cleanly within ~0.1-1.6s of first touch, no errors traceable to the mechanism. ~1s is a fair approximation of "time to start the app" — usable almost instantly, with per-screen compile cost paid incrementally instead of upfront.
  • For a true apples-to-apples check, I forced dev.lazyCompilation: false (fully eager, matching Webpack's behavior) and re-ran: warm startup averaged ~3.0s (vs Webpack's 8.65s). So even compiling the whole graph upfront, Rsbuild's warm dev startup beats Webpack's ~3x. Shipping with the lazy default (~1s) since it's faster and verified safe.

Bottom line: cold app builds ~1.7x faster than Webpack, warm ~16x faster; Storybook ~4.1x faster; dev-server startup goes from ~8.65s to ~1s to a usable page.

Output correctness

App dist/: same total size (51M), same service-worker.js/workbox-*.js output, same 42 preload/prefetch tags. Storybook dist/docs/: 42M/165 files (Webpack) vs 48M/176 files (Rsbuild) — within noise from differing chunk-splitting heuristics. App shell, service worker, and Storybook UI all verified equivalent. All scripts (build, build-staging, build-adhoc, web-server, storybook, storybook-build, storybook-build-staging) re-verified against the final config after merging #95453.

Caveats

  • Native builds (Metro) are untouched by this PR.

Fixed Issues

$
PROPOSAL:

Tests

  • Verify that no errors appear in the JS console
  1. Run npm run build, npm run build-staging, and npm run build-adhoc; confirm each exits 0. Serve the output (e.g. npx http-server dist) and confirm the app boots with no console errors, and env-specific index.html behavior (staging noindex meta tag, splash logo, third-party scripts) is correct for each.
  2. Run npm run web-server and confirm the dev server boots over HTTPS, the /api proxy forwards to the local backend, and HMR works on a simple edit.
  3. Run npm run storybook and confirm the dev server boots and a story hot-reloads on edit.
  4. Run npm run storybook-build and npm run storybook-build-staging; confirm each exits 0 and produces a working dist/docs/index.html. Serve and confirm stories render.

Offline tests

N/A — build tooling only, no app runtime behavior change.

QA Steps

N/A — build-tooling only change with no user-facing or API behavior change. This PR is still a draft pending review before being considered for staging/production.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test step

…uilds

Mirrors config/webpack/{webpack.common,webpack.dev}.ts under config/rspack/,
swapping webpack-specific plugins for their Rspack builtins (CopyRspackPlugin,
CssExtractRspackPlugin, SwcJsMinimizerRspackPlugin, ReactRefreshRspackPlugin,
@aaroon/workbox-rspack-plugin) and replacing @vue/preload-webpack-plugin
(which depends on webpack-internal chunk graph APIs Rspack doesn't expose)
with a small custom RspackPreloadPlugin that reads compilation.getAssets()
directly.

Adds `build:rspack`, `build-staging:rspack`, and `web-server:rspack` npm
scripts so both bundlers can be run side by side without touching the
existing webpack config. Storybook is out of scope.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expands the Rspack POC to cover Storybook (via storybook-react-rsbuild,
since Storybook has no first-party Rspack framework package) and removes
Webpack entirely now that both build paths are covered, rather than
keeping the two bundlers side-by-side.

Co-authored-by: Cursor <cursoragent@cursor.com>
@roryabraham roryabraham changed the title [POC] Migrate web builds from Webpack to Rspack [POC] Migrate web builds and Storybook from Webpack to Rspack/Rsbuild Jul 5, 2026
@melvin-bot

melvin-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown

Hey, I noticed you changed some webpack configuration files. This can break production builds. Did you remember to run a production build locally to verify they still work?

roryabraham and others added 6 commits July 4, 2026 20:57
The auto-restart wrapper (#67373) was added to paper over
webpack-dev-server's unbounded JS-heap growth across HMR recompiles,
which forced periodic heap-limit crashes during long dev sessions.

Stress-tested the Rspack dev server with 60+ back-to-back HMR recompiles
(mimicking the original repro of repeatedly saving a file): heap usage
plateaus/bounces in a bounded band rather than growing without bound,
and the periodic forced gc() call reliably reclaims memory each time -
unlike webpack, where explicit GC barely helped. No crash-recovery loop
needed.

Also fixes a latent bug in ForceGarbageCollectionPlugin: `if (gc && ...)`
throws a ReferenceError when Node isn't started with --expose-gc, since
referencing an undeclared global outside of `typeof` throws. `typeof gc`
alone is the safe check.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ild, ws vuln

- rspack.common.ts / .storybook/rsbuild.config.ts: explicitly mock
  __filename/__dirname ('mock' instead of Rspack's default 'warn-mock') so
  canvaskit-wasm/expo don't emit a "Module parse warning" on every build.
  Storybook's `--smoke-test` treats any non-allow-listed warning as a hard
  failure, so this was breaking the "Storybook tests" CI check; the rsbuild
  config wasn't otherwise inheriting this from the shared Rspack config.
- cspell.json: add rspack/Rspack/rsbuild/aaroon to the word list.
- Rebuilt 3 stale .github/actions/javascript/*/index.js bundles that drifted
  after merging main (unrelated to this PR's changes).
- Bump the `ws` override from 8.17.1 to 8.21.0 to pick up fixes for two
  advisories (GHSA-58qx-3vcg-4xpx, GHSA-96hv-2xvq-fx4p) that Snyk flagged
  once storybook/webpack-bundle-analyzer joined the dependents list.

Co-authored-by: Cursor <cursoragent@cursor.com>
ncc's output isn't fully deterministic across different node_modules
resolution states; my previous gh-actions-build run used a tree from
npm install rather than npm ci, leaving this one bundle out of sync
with what CI's verify job rebuilds and diffs against.

Skips the oxfmt pre-commit hook: it errors ("Expected at least one target
file") when every staged file matches its ignorePatterns, which is the case
here since .github/actions/javascript/**/index.js is intentionally excluded
(generated bundle). Nothing to format either way.

Co-authored-by: Cursor <cursoragent@cursor.com>
…sitive dep

Removing webpack as a devDependency also dropped the "webpack": "^5.x"
override, which was silently pinning react-web-config's own (unused)
webpack@^2.3.3 dependency to a safe version. Without it, npm installs
react-web-config's real webpack@2.7.0 -> node-libs-browser ->
crypto-browserify -> browserify-sign/create-ecdh -> elliptic chain,
introducing 4 new critical vulnerabilities not present on main.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Stop suppressing import/extensions line-by-line for .storybook/ and
  config/rspack/ ESM entry points; handle it with one config-level override.
- Share ignoreWarnings, lottie/pdf asset rules, and define() values between
  rspack.common.ts and .storybook/rsbuild.config.ts so Storybook can't drift
  from the app build; drop mockPaths.ts aliases already set upstream.
- Replace html-webpack-plugin with Rspack's native HtmlRspackPlugin in both
  the main plugin and RspackPreloadPlugin, and remove the now-unused
  html-webpack-plugin dependency.
- Document the RSPACK_PROFILE build-profiling workflow in SETUP_WEB.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
@roryabraham roryabraham changed the title [POC] Migrate web builds and Storybook from Webpack to Rspack/Rsbuild Migrate web builds and Storybook from Webpack to Rspack/Rsbuild Jul 6, 2026
@roryabraham

This comment was marked as resolved.

@roryabraham

This comment was marked as resolved.

@MelvinBot

This comment was marked as off-topic.

Type RspackPreloadPlugin's links array off the alterAssetTags hook's own
parameter instead of importing JsHtmlPluginTag from @rspack/binding, since
that package is only a transitive dependency of @rspack/core, not one we
depend on directly. Add "pftrace" (the Perfetto trace file extension) to
the cspell word list.

Co-authored-by: Cursor <cursoragent@cursor.com>
@chatgpt-codex-connector

This comment was marked as resolved.

Rsbuild wraps Rspack with higher-level config (source.define, output.copy,
server.https/proxy, performance.buildCache) and is already used for Storybook,
so unifying onto it removes the last hand-rolled dev-server/HTTPS/persistent-cache
plumbing in config/rspack/ and lets the app build and Storybook share one
getSharedConfiguration()/getCommonConfiguration() config instead of two
independently-maintained bundler configs.

Co-authored-by: Cursor <cursoragent@cursor.com>
roryabraham and others added 2 commits July 6, 2026 19:06
Re-ran the #95319 HMR memory-stress test (60+ back-to-back recompiles)
against the Rsbuild dev server with and without the plugin's forced
gc() call. Heap and RSS plateau identically either way (~245MB heap,
bounded RSS growth across 260 total compiles), unlike raw Rspack where
disabling gc() caused unbounded growth. V8's own GC is sufficient here,
so the plugin and --expose-gc are dead weight under Rsbuild.

Co-authored-by: Cursor <cursoragent@cursor.com>
The ESLint flat config now disables import/extensions repo-wide for
config/rsbuild/**/*.ts, so the line-level disable for that rule is
redundant. The @dword-design/import-alias/prefer-alias disable is
still needed and stays.

Co-authored-by: Cursor <cursoragent@cursor.com>
@roryabraham

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

roryabraham and others added 2 commits July 7, 2026 14:01
Rsdoctor is the first-party Rspack/Rsbuild bundle analyzer, integrates
via the same tools.rspack escape hatch, and adds loader/plugin timing
and duplicate-package analysis on top of bundle size visualization.

Co-authored-by: Cursor <cursoragent@cursor.com>
The webpack dev config defined process.env.PORT for the client so
CONFIG.DEV_PORT reflects the actual resolved port when portfinder
falls back off 8082. Rsbuild's dev config dropped that define, only
wiring the resolved port to server.port, so getEnvironmentURL() would
generate dev links pointing at the wrong port whenever 8082 was busy.

Verified by occupying 8082, booting the dev server (portfinder fell
back to 8083), and confirming the served bundle now bakes in
`DEV_PORT: 8083 ?? 8082` instead of falling back to the hardcoded
default.

Co-authored-by: Cursor <cursoragent@cursor.com>
@roryabraham

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 7b03cb95a8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

roryabraham and others added 2 commits July 10, 2026 13:47
…k-poc

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	package-lock.json
#	package.json
ncc's output isn't fully deterministic across different node_modules
resolution states; the version merged in from main left this bundle
out of sync with what CI's verify job rebuilds and diffs against.

Co-authored-by: Cursor <cursoragent@cursor.com>
@melvin-bot
melvin-bot Bot removed the request for review from a team July 10, 2026 22:43
@roryabraham
roryabraham removed the request for review from JmillsExpensify July 10, 2026 22:44

@chuckdries chuckdries left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. You should document that existing users will have to run (or, is it easy to write a script that does that automatically if needed?)

    mv config/webpack/key.pem config/rsbuild/
    mv config/webpack/certificate.pem config/rsbuild/
  2. The default entrypoint the dev server launches my browser to is /main, which renders the not found page. Can you just do /, or perhaps /home?

Comment thread src/hooks/useReportTransactionViolations.ts Outdated
Comment thread src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx Outdated
Comment thread src/components/ReportActionItem/MoneyRequestReportPreview/ApproveActionButton.tsx Outdated
Comment thread package.json
@roryabraham

Copy link
Copy Markdown
Contributor Author

(Rory's Agent) Addressed both from the top-level review:

  1. Documented the cert migration in contributingGuides/SETUP_WEB.md: existing contributors whose certs are still under the now-removed config/webpack/ just need to re-run npm run setup-https (or move the two files over).
  2. Fixed the --open URL. Root cause: Rsbuild's --open defaults to opening the first entry's route, and our entry key is named main (source.entry: {main: './index.js'}), so it opened /main, which isn't a real app route. Set server.open: '/' explicitly in rsbuild.config.ts rather than renaming the entry (renaming would ripple into chunk filenames, Sentry release naming, etc. for no real benefit).

roryabraham and others added 3 commits July 10, 2026 16:19
These 4 files' rulesdir/no-useOnyx-dependencies-arg violations
pre-date and are unrelated to this PR (per review feedback). Restore
the original code and grandfather them into eslint-seatbelt.tsv
instead of fixing them here.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rsbuild's --open defaults to the first entry's route, and our entry
key is named "main" (source.entry: {main: './index.js'}), so it
opened /main, a nonexistent app route. Set server.open explicitly.

Co-authored-by: Cursor <cursoragent@cursor.com>
Certs generated before the Webpack -> Rsbuild migration are stranded
in the now-removed config/webpack directory.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chuckdries chuckdries left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚢

@chuckdries

Copy link
Copy Markdown
Contributor

Oh, that's weird, why is that passing
image

@chuckdries

Copy link
Copy Markdown
Contributor

PR has a standing approval from an internal Expensify engineer, so the reviewer checklist is not required 🎉

Never mind - not sure why I've never seen that before

@chuckdries
chuckdries merged commit 609f15f into main Jul 10, 2026
52 checks passed
@chuckdries
chuckdries deleted the rory-webpack-to-rspack-poc branch July 10, 2026 23:30
@github-actions

Copy link
Copy Markdown
Contributor

🚧 chuckdries has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

roryabraham added a commit that referenced this pull request Jul 11, 2026
…l back cleanly on React Compiler bailouts

Two correctness bugs surfaced while re-verifying this branch after
rebasing onto the merged Rsbuild migration (#95319):

1. Rsbuild's default 'js' rule (builtin:swc-loader) ran on every
   .js/.ts/.jsx/.tsx file, including ones already handled by Rule
   A/B/B2 below, and ran *before* them in the loader chain -- silently
   stripping JSX/TS before the Fullstory annotation loader or OXC's
   React Compiler ever saw the original source. Added a
   `tools.bundlerChain` hook to exclude app source and
   `includedNodeModules` from the default rule, and forwarded it from
   `getSharedConfiguration` into `getCommonConfiguration` (which
   otherwise replaces rather than merges `tools`).

2. oxc-transform returns empty `code` (not just a diagnostic) when
   React Compiler hits an Error-severity Rules-of-React violation
   (e.g. accessing `ref.current` inline during render, as in
   useDebouncedState). The loader was demoting these to warnings but
   still shipping the empty output, silently breaking every component
   that imported the affected module (e.g. ThemeProvider crashed on
   first render in dev). Now retries the transform with
   `reactCompiler: false` when this happens, matching
   babel-plugin-react-compiler's default bailout behavior.

Also updates knip.json (glob + ignoreDependencies) and regenerates
package-lock.json for the merged package.json, both of which were
already made locally but not staged before the merge commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

@mkhutornyi mkhutornyi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the difference between npm run web vs npm run web-server?
Which command should be run for local web dev server?

@roryabraham

roryabraham commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

npm run web-server runs just the rsbuild dev server. npm run web-proxy runs a Node.js proxy server to get around CORS issues for most external devs who don't have access to a dev backend, but is a no-op for most Expensify devs hitting their dev backend.

npm run web concurrently runs both npm run web-server and npm run web-proxy

The intention is that generally people just run npm run web

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/chuckdries in version: 9.4.34-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@IuliiaHerets

Copy link
Copy Markdown

Hi @roryabraham. Any QA steps here?

@chuckdries @neil-marcellini @mkhutornyi

@chuckdries

Copy link
Copy Markdown
Contributor

Hi @IuliiaHerets, no specific QA steps here!

@IuliiaHerets

Copy link
Copy Markdown

@chuckdries can we check it off then?

@chuckdries

Copy link
Copy Markdown
Contributor

@IuliiaHerets yes

@roryabraham roryabraham changed the title Migrate web builds and Storybook from Webpack to Rspack/Rsbuild [No QA] Migrate web builds and Storybook from Webpack to Rspack/Rsbuild Jul 14, 2026
@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/roryabraham in version: 9.4.34-14 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 failure ❌
🍎 iOS 🍎 failure ❌

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/roryabraham in version: 9.4.34-14 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

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.

6 participants