Skip to content

feat(dev-server): default linux dev to the rspack server - #1229

Merged
Harry19081 merged 2 commits into
developfrom
feat/rspack-linux-webkitgtk
Sep 3, 2026
Merged

feat(dev-server): default linux dev to the rspack server#1229
Harry19081 merged 2 commits into
developfrom
feat/rspack-linux-webkitgtk

Conversation

@Raymond8196

Copy link
Copy Markdown
Collaborator

Problem

Linux desktop development still runs the webpack dev server, while macOS has
been on rspack since #1174. On the current develop commit that costs Linux
developers, per measurement below: an 18.0 s cold compile, 1.9-3.1 s per HMR
round-trip, 3.55 GiB idle RSS, and pnpm tauri:dev not serving main.js
until ~27.9 s.

Linux was excluded from #1174 for a concrete reason, not an oversight:
config/rspack.config.js did not carry the three WebKitGTK accommodations
that config/webpack.config.js has (lines 35-48, 589-590, 694-717). Linux dev
runs under WebKitGTK, which cannot load App as a runtime dynamic-import
chunk (commit 291f95b) and stalls on the injected <script> tag; and an
eval-* devtool inlines every module's source into main.js, pushing it past
the ~80 MB WebKitGTK can load.

Solution

Two commits, in order:

  1. feat(rspack-config): support the linux webkitgtk dev path — port the
    three platform gates from config/webpack.config.js into
    config/rspack.config.js: retryMainScriptLoad (external retrying loader
    instead of an injected <script>, so html.inject: false), eagerDevApp
    (App inlined into main.js via webpackMode: "eager", wired through
    DefinePlugin as the inline process.env.ORGII_DEV_EAGER_APP expression
    that src/index.tsx:208 constant-folds against), and
    devtool: "cheap-source-map" when eager, so source maps go to separate
    .map files.

  2. feat(dev-server): default linux dev to the rspack server — flip
    createFrontendScriptName in scripts/dev/tauri-dev-processes.cjs from
    rspack ?? platform === "darwin" to rspack ?? platform !== "win32", and
    update its unit test.

Resulting invariant: macOS and Linux resolve to dev:frontend:rspack, Windows
stays on dev:frontend. ORGII_RSPACK=true/false, --rspack/--webpack, and
pnpm tauri:dev:webpack still override the platform default in both
directions; --light still wins over both.

Windows is deliberately left on webpack because it has never been exercised on
rspack. Production builds are untouched — they stay on webpack.

Measured on Linux / WebKitGTK 2.50.4, same commit, both bundlers cold with no
cache, sequential runs (not concurrent, to avoid the contention swing #1174
documented):

Metric webpack rspack
Cold compile 18,016 ms 3,159 ms
HMR round-trips 3061 / 1987 / 1930 ms 446 / 395 / 440 ms
Idle RSS 3.55 GiB 1.41 GiB
pnpm tauri:dev main.js ready 27,857 ms (last recorded run, 2026-07-27) 3,711 ms (measured today)

Note the rspack cold compile improved from the 9.8 s recorded on 2026-09-01 to
3.2 s today. That is not from this change — develop has since migrated to
Tailwind CSS v4 and removed unused exports, shrinking the module graph. Both
bundlers benefit, so the comparison above still holds; only the absolute
numbers moved.

Potential risks

  • Windows is unverified on rspack and is therefore excluded from the new
    default. If a Windows developer opts in with --rspack, the WebKitGTK gates
    correctly evaluate to false there, but nothing else has been exercised.
  • dev/prod bundler divergence. Dev now runs rspack on two of three
    platforms while production builds stay on webpack, so "compiles in dev" no
    longer implies "compiles in the production pipeline". This divergence was
    introduced by build(dev-server): add rspack dev server, default on macos #1174; this PR widens it to Linux.
  • Two dev configs to keep in sync. config/rspack.config.js duplicates
    aliases, splitChunks, loader rules, and the env-key list from
    config/webpack.config.js by hand. A change to one that misses the other
    produces silent dev/prod drift.
  • Pre-existing, not introduced here: the rspack path does not read a
    repository-root .env file.
    config/webpack.config.js:599 uses
    dotenv-webpack with systemvars: true, which reads both the .env file
    and the process environment; config/rspack.config.js:44-58 uses a
    hand-written 12-key whitelist read straight off process.env, and
    scripts/dev/rspack-server.js never loads dotenv. Shell-exported variables
    still work; only the .env file is missed. Blast radius is limited to
    developers who override the backend URL or run a self-hosted Supabase auth
    project — the defaults (public OSS Supabase project, hosted login off) are
    unaffected. This is platform-independent and has been live for macOS since
    build(dev-server): add rspack dev server, default on macos #1174. It will be fixed in a separate PR rather than folded in here.
  • Long-session stability is not measured. Verification covered one full
    boot and three HMR round-trips, not a multi-hour session, so memory drift or
    HMR degradation over a working day is unknown.
  • No persistent cache. rspack's is still experimental and stays behind
    ORGII_RSPACK_CACHE=persistent, so every cold start pays the full ~3.2 s.
    That is still well under webpack's warm-cache time, so this is a tradeoff,
    not a regression.
  • Rollback is a one-line revert of the createFrontendScriptName
    expression, and any individual developer can opt out immediately today with
    pnpm tauri:dev:webpack without a code change.

Verification

All on Linux, WebKitGTK 2.50.4 (libwebkit2gtk-4.0-37 and 4.1-0 are both
2.50.4-0ubuntu0.22.04.1 on this machine), against this branch rebased onto
origin/develop.

  • node --test scripts/dev/tauri-dev-processes.test.cjs12/12 pass.
  • Resolved defaults, via createFrontendScriptName: linux and darwin
    dev:frontend:rspack, win32dev:frontend; {rspack: false, platform: "linux"}dev:frontend.
  • Config evaluated on Linux after the rebase: devtool: cheap-source-map,
    html.inject: false, html.retry: true,
    process.env.ORGII_DEV_EAGER_APP: "true".
  • pnpm dev:frontend:rspack cold, no cache — compiled in 3,159 ms, 8011
    modules, no errors or warnings; served main.js at 26,999,850 B.
  • pnpm dev:frontend (webpack) cold, node_modules/.cache/webpack removed —
    compiled in 18,016 ms; the comparison numbers in Solution come from these
    two runs plus three HMR round-trips each.
  • Real WebKitGTK load probe (offscreen WebKit2.WebView, not a Tauri
    process): 0 ms watchdog → 1 ms loader attempt → 30 ms fetch → 973 ms loaded, load-failed: None, scripts: [] (confirming the retry-loader blob
    path rather than an injected tag), rootChildren: 2,
    rootHtmlLen: 92757 — React mounted a 92 KB DOM. The console errors in that
    run are all Tauri IPC unavailable, expected with no __TAURI_INTERNALS__.
  • Full pnpm tauri:dev boot: launcher selected the Rspack dev server;
    [DevStartup +3.71s] main.js HTTP readyfrontend ready; opening WebView;
    cargo Finished dev profile in 12.91s; [DevStartup +115.21s] backend HTTP server ready. The two error matches in that log are false positives — the
    Rust type name ScanError inside a warning snippet.
  • Window capture of the running app: complete IDE UI — native menubar (no
    GNOME white-bar artifact), session list, populated file tree, editor pane
    with syntax highlighting, Git/AGENT timelines, status bar. Confirms lazy
    chunks beyond the eager App resolve under WebKitGTK. No image is embedded
    because this is a dev-tooling change with no UI diff to show; the capture was
    a liveness check, and both bundlers render the same UI.
  • npx eslint on the three changed files — 0 errors (3 warnings are
    "file ignored by config", not findings).
  • npx prettier --check flags scripts/dev/tauri-dev-processes.test.cjs at
    lines 113-120, inside a test this PR does not touch. git show origin/develop:scripts/dev/tauri-dev-processes.test.cjs fails the same
    check, so it is pre-existing and deliberately left alone rather than
    smuggled in as unrelated formatting.
  • pnpm install was required (develop added sass-embedded); it left
    pnpm-lock.yaml unchanged, so this PR carries no dependency change.

Not run: Windows on rspack; any multi-hour session; production build paths
(unchanged by this PR); the .env-file path described under Potential risks.

The rspack config hardcoded the three dev knobs to their macOS values, so
`ORGII_RSPACK=true` on Linux produced a bundle WebKitGTK cannot boot. Port
the gates from config/webpack.config.js (lines 35-48) verbatim:

- eagerDevApp -> DefinePlugin ORGII_DEV_EAGER_APP, so src/index.tsx inlines
  App via `webpackMode: "eager"` instead of emitting a runtime chunk that
  WebKitGTK fails to load.
- retryMainScriptLoad -> HtmlWebpackPlugin `inject: false` plus the option
  the index.html retry loader reads.
- devtool -> `cheap-source-map` when eager, keeping main.js well under the
  ~80 MB WebKitGTK limit that eval-* source maps would blow past.

Platform selection is unchanged: createFrontendScriptName still defaults
Linux to the webpack server, and `ORGII_RSPACK=true` opts in.

Verified on Linux (X11, WebKitGTK 2.50.4) against the webpack dev server on
the same machine, run sequentially: cold compile 9.8 s vs 22.6 s (webpack
had a warm 2.4 GB filesystem cache, rspack none), HMR 0.55 s vs 1.95 s,
peak RSS 1.67 GiB vs 3.51 GiB, main.js 27.0 MB vs 32.9 MB. A real
`ORGII_RSPACK=true pnpm tauri:dev` boot renders the full IDE UI, so
lazy-loaded chunks resolve under WebKitGTK, and two consecutive edits hot
replaced without a page reload (workspace tree state survived).

Pre-commit hook ran. Total eslint: 0, total circular: 0
config/rspack.config.js now carries the WebKitGTK eager-App + retry-loader
path, verified against a real Tauri boot on WebKitGTK 2.50.4: full IDE UI
rendered, lazy chunks resolved, HMR confirmed a hot replace (state kept).

Measured on Linux, 2026-09-02, same commit, both bundlers cold with no
cache, sequential runs: cold compile 3.2s vs 18.0s, HMR 0.40-0.45s vs
1.9-3.1s, idle RSS 1.41GiB vs 3.55GiB, 'pnpm tauri:dev' main.js ready
3.7s (webpack's last recorded run: 27.9s).

Windows keeps the webpack default: it has not been exercised on rspack.
ORGII_RSPACK=false / --webpack / 'pnpm tauri:dev:webpack' still opt out.

Pre-commit hook ran. Total eslint: 0, total circular: 0
@Harry19081
Harry19081 self-requested a review September 3, 2026 03:59
@Harry19081
Harry19081 merged commit 65a292b into develop Sep 3, 2026
6 checks passed
@Harry19081 Harry19081 added enhancement New feature or request performance Performance, responsiveness, or resource-usage work dev-tooling Developer tooling, build, CI, tests, diagnostics, or release labels Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev-tooling Developer tooling, build, CI, tests, diagnostics, or release enhancement New feature or request performance Performance, responsiveness, or resource-usage work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants