Skip to content

Stub out react-native-svg fetchData on web to drop buffer polyfill#11097

Open
mozzius wants to merge 2 commits into
mainfrom
samuel/stub-rnsvg-fetchdata
Open

Stub out react-native-svg fetchData on web to drop buffer polyfill#11097
mozzius wants to merge 2 commits into
mainfrom
samuel/stub-rnsvg-fetchdata

Conversation

@mozzius

@mozzius mozzius commented Jul 8, 2026

Copy link
Copy Markdown
Member

Why

The buffer polyfill (~55KB stat size, plus base64-js + ieee754) was landing in the initial web bundle. The only importer is react-native-svg's utils/fetchData.js, which uses Buffer.from(x, 'base64') to decode base64 data URIs for SvgUri/SvgXml remote loading – a feature we don't use anywhere. The package has no sideEffects field, so webpack can't tree-shake it out of the barrel export. (It also doesn't declare buffer as a dependency – it only resolves via hoisting from unrelated packages.)

How

  • Alias the absolute path of react-native-svg/lib/module/utils/fetchData to false in webpack.config.js. The key must be an absolute path because the package imports it via a relative path internally. Webpack replaces the module with an empty stub, so fetchText becomes undefined – if SvgUri/SvgXml remote loading ever sneaks in, it throws immediately rather than silently bloating the bundle.
  • Register our webpack.config.js in cache.buildDependencies.config. Expo only registers its own internal config, so edits to ours (like this alias) didn't invalidate the persistent filesystem cache and the alias was silently ignored on cached rebuilds.
  • Add webpack.config.js to the ESLint ignore list (Node.js config file, was never linted before the flat-config migration and fails no-nodejs-modules + type-checked rules).

Verification

Built with EXPO_PUBLIC_GENERATE_STATS=1 and confirmed via stats.json: buffer, base64-js, and ieee754 are gone; fetchData shows as a 15-byte (ignored) module. Also grepped the emitted chunks for the polyfill's signature strings – no matches.

Screenshot 2026-07-08 at 16 14 09

🤖 Generated with Claude Code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 8, 2026

Copy link
Copy Markdown

Claude finished @mozzius's task in 1m 33s —— View job


PR Review

I read the repo CLAUDE.md and .github/claude-review-prompt.md, then reviewed the full diff against origin/main. This is a web-only build config change, so the blast radius is the web bundle only — native builds don't run webpack.config.js.

This PR looks good. The approach is sound and the reasoning in the description holds up. No blocking findings.

What I checked:

  • Premise is valid. Grepped the whole source tree for SvgUri, SvgXml, fetchText, fetchData, LocalSvg, WithLocalSvg, SvgFromUri, SvgFromXml — the only hits are inside the new comment in webpack.config.js itself. Nothing in src/ consumes the remote-loading path, so stubbing fetchData to false can't break any code we actually ship. fetchText is only referenced inside the SvgUri/SvgXml component bodies at runtime (not at module-eval time), so the react-native-svg barrel still evaluates fine and our normal Svg icon usage is unaffected.
  • false alias semantics. Setting an alias value to false is the supported webpack idiom for "resolve to an empty module," so fetchText becomes undefined and any accidental future call throws immediately rather than silently — matching the stated intent (webpack.config.js:75-78).
  • The cache.buildDependencies.config fix is the important part. It's correctly guarded with optional chaining and appends __filename to Expo's existing array rather than clobbering it (webpack.config.js:57-62). Without this, the alias would be silently dropped on cached rebuilds — good catch, and it makes future edits to this file reliable too.
  • Cross-platform path. path.join(__dirname, 'node_modules/...') normalizes separators, so the absolute-path alias key resolves correctly on the Linux CI builder.
  • ESLint ignore (eslint.config.mjs:41) is consistent with the adjacent eslint.config.mjs entry — a Node config file that isn't meant to pass the app's type-checked/no-nodejs-modules rules.

One non-blocking note (not a defect): the alias key hard-codes the internal path node_modules/react-native-svg/lib/module/utils/fetchData. If a future react-native-svg upgrade relocates that file, the alias silently stops matching and buffer quietly returns to the bundle — no crash, just a regression of this PR's own goal. Since the PR description mentions verifying via stats.json, it may be worth a brief comment pointing a future upgrader at that check, or leaving a note in the SVG-related code. Not worth blocking on.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
Old size New size Diff
8.5 MB 7.73 MB -794.77 KB (-9.13%)

@mozzius mozzius requested a review from vineyardbovines July 8, 2026 13:15
@claude

claude Bot commented Jul 10, 2026

Copy link
Copy Markdown

Claude finished @mozzius's task in 1m 34s —— View job


PR Review

  • Read repo guidelines and review prompt
  • Review the diff against origin/main
  • Post review findings

This is a web-only build-config change (webpack.config.js doesn't run for native or in tests), so the blast radius is the web bundle. The PR looks good — no blocking findings.

What I checked:

  • Premise holds. Grepped the tree for SvgUri, SvgXml, fetchText, LocalSvg, WithLocalSvg, SvgFromUri, SvgFromXml — zero hits outside the new comment. Our SVG usage is all vector icons and react-native-qrcode-styled, none of which touch the base64/remote-loading path. Stubbing fetchData to false can't break shipped code; fetchText is only dereferenced inside SvgUri/SvgXml component bodies at runtime, so the barrel still evaluates.
  • false alias + absolute-path key. Correct webpack idiom for an empty module, and the key correctly uses path.join(__dirname, ...) since RN-svg imports the util via a relative path internally — a bare specifier wouldn't match. Cross-platform-safe on the Linux CI builder.
  • cache.buildDependencies.config fix (webpack.config.js:57-62) is the load-bearing part: guarded with optional chaining and appends __filename rather than clobbering Expo's array. Without it the alias is silently dropped on cached rebuilds.
  • ESLint ignore (eslint.config.mjs:41) is consistent with the neighboring babel.config.js/metro.config.js/eslint.config.mjs Node config entries.

One non-blocking note (unchanged from the prior review, not a defect): the alias key hard-codes node_modules/react-native-svg/lib/module/utils/fetchData. If a future react-native-svg bump relocates that file, the alias silently stops matching and buffer quietly returns to the initial bundle — no crash, just a regression of this PR's own goal. Worth a note for a future upgrader to re-check stats.json. Not worth blocking on.

Note: node_modules isn't installed in this CI checkout, so I couldn't confirm the exact internal path still resolves at 15.12.1 firsthand — but that's exactly what the stats.json verification in the PR description confirms, and the earlier build-size CI comment (-23 KB) corroborates it.

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.

3 participants