Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

babelLoader always uses hermes-parser, unlike Metro — 90s on one prebuilt file

Aperta
#1,447 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
react-native, typescript

Direzione di ricerca

Inizia da packages/repack/src/loaders/babelLoader/babelLoader.ts:89-96 e confronta la selezione del parser con il comportamento del preset descritto per babel-plugin-syntax-hermes-parser. Usa il file segnalato di @lottiefiles/dotlottie-react e alcuni esempi Flow per verificare la selezione, quindi conferma che l'output del bundle rimanga identico a livello di byte e che i file non-Flow evitino il rallentamento di hermes-parser.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

The problem

babelLoader parses every non-TypeScript file with hermes-parser (packages/repack/src/loaders/babelLoader/babelLoader.ts:89-96):

const sourceAst = isTS || isTSX
  ? parseSync(src, babelConfig)
  : hermesParser.parse(src, { babel: true, ... });

Metro does not. @react-native/babel-preset passes parseLangTypes: 'flow' to babel-plugin-syntax-hermes-parser, which skips hermes-parser when a file has no @flow pragma and lets @babel/parser handle it:

// babel-plugin-syntax-hermes-parser/dist/index.js:56
if (parseLangTypes === 'flow' && !/@flow/.test(code)) { return; }

So Re.Pack ignores the preset's own parseLangTypes, and a dependency that is free under Metro can cost minutes here.

What it cost us

We bundle the Expensify app with Re.Pack. Our cold production iOS build was ~114s, against Metro's ~83s. One file accounted for 94s of that:

@lottiefiles/dotlottie-react/dist/browser/index.js — 502 KB, 22 lines, prebuilt minified ESM, no @flow pragma.

parser time
hermes-parser 90.1s
@babel/parser 0.1s

That is not the parse itself. parse(src, {babel: false}) takes 0.1s; all 88s is in hermes-parser's Hermes-AST to Babel-AST conversion, which is quadratic in the number of sibling nodes: every node replacement copies the whole sibling array. This file has one ArrayExpression with 128,834 elements. Reported upstream with a profile and a minimal repro: facebook/hermes#2158.

Because it is one serial task, it set a minimum time for the whole build no matter how many workers we gave it.

It was also hard to spot: no warning, and nothing showed up in per-loader timings. We only found it by bisecting.

Across our whole babel lane (3522 files), 2779 have no pragma. Those parse in 1.1s with @babel/parser versus 4.7s with hermes-parser — and hermes-parser fails on 2 of them.

Why not simply switch parsers

hermes-parser is still needed for the other files. @babel/parser fails on 241 files in react-native 0.86, which use Flow syntax it cannot read (as casts, component(...) types). The pragma check is the fix, not a swap.

Suggested fix
const sourceAst = isTS || isTSX
  ? parseSync(src, babelConfig)
  : /@flow/.test(src)
    ? hermesParser.parse(src, { babel: true, ... })
    : parseSync(src, babelConfig);

Better still, read the preset's parseLangTypes instead of hard-coding the check, so parseLangTypes: 'all' still sends everything to hermes-parser.

We have tested this

We run it in our app through the existing hermesParserPath option, which babelSwcLoader passes through. Our replacement parser checks for @flow and picks hermes-parser only then.

  • bundle output is byte-identical, apart from the sourcemap filename
  • build time is flat, because we had already moved that package to another loader
  • the file above: 90.1s → 0.1s

Identical output on a 35 MB bundle shows the check does not change what gets built.

Happy to open a PR.

Related

#1422 covers Flow in the SWC-native lane (getJsTransformRules). This report is about the babel lane that the templates use, so they do not overlap, but both come down to how Flow is detected.

Environment

@callstack/[email protected], Rspack 2.1.3, [email protected], @babel/[email protected], react-native 0.86, Node 26.5.0, macOS arm64.

Lingua principale
TypeScript
Stelle
1.9k
Fork
167
Merge medio
4g 10h
PR unite (30g)
7

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di callstack/repack

Tutte le issue di callstack/repack

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.