Tree shaking: getNativeInjectionCode emits raw ESM, hermesc fails with 'requires module mode'
Maintainer thường phản hồi trong vòng 3 ngày
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 18/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- react-native, typescript
- Lĩnh vực
- build-system, mobile-dev
Hướng nghiên cứu
Start with the getNativeInjectionCode function in the injection-code module, which emits the virtual module as an ESM string. Check PR #419, which is already open against this issue, before doing anything else. To reproduce, run the Expo export with the two tree-shaking flags and confirm the hermesc 'requires module mode' error. Done means that build compiles to bytecode with the flags on and the injection module survives the optimize-graph pass.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
getNativeInjectionCode() emits its virtual module as a raw ESM string. Under Expo's experimental Metro tree shaking the serializer re-emits modules from their ESM form, so that module reaches the concatenated bundle with import/export intact. hermesc compiles the bundle in script mode, so both statements are hard errors and no production build can be produced.
Versions
react-native-css3.0.7nativewind5.0.0-preview.4expo57.0.1,@expo/cli57.0.13,@expo/metro-config57.0.7metro0.84.4,react-native0.86.0
Reproduction
EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH=1 EXPO_UNSTABLE_TREE_SHAKING=1 \
npx expo export --platform android
Failed to generate Hermes bytecode for: node_modules/expo-router/entry.js
index.js:844745:1: error: 'import' statement requires module mode
index.js:853525:1: error: 'export' statement requires module mode
hermesc ... exited with non-zero code: 2
Adding --no-bytecode succeeds, and running hermesc by hand on that output pins it to a single line:
entry-<hash>.js
5663:14: error: 'import' statement requires module mode
5663:128908: error: 'export' statement requires module mode
That line:
"use strict";import{StyleCollection}from"react-native-css/native-internal";
StyleCollection.inject({s:[["pointer-events-auto",...]]});
...
},5259,[244]);export{};
Cause
dist/commonjs/metro/injection-code.js:
function getNativeInjectionCode(cssFilePaths, values) {
const importStatements = cssFilePaths.map(f => `import "${f}";`).join("\n");
const contents = values.map(v => `StyleCollection.inject(${JSON.stringify(v)});`).join("\n");
return Buffer.from(
`import { StyleCollection } from "react-native-css/native-internal";\n` +
`${importStatements}\n${contents};export {};`
);
}
Without the flags this synthetic source is transformed to CJS like any other module, so the problem is invisible. With EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH + EXPO_UNSTABLE_TREE_SHAKING it is not.
Ruled out
| Hypothesis | Test | Result |
|---|---|---|
| Expo Atlas instrumentation perturbs the serializer | reran with EXPO_ATLAS unset |
same failure |
| Only multi-platform exports affected | Android alone | same failure |
| The bundle is fine, bytecode step at fault | ran hermesc by hand on --no-bytecode output |
same two errors, so the bundle really does contain ESM |
Unrelated to expo/expo#41620 — the build fails at bytecode generation, well before an app runs.
Impact
Measured on a production app, comparing plain JS both ways so the two sides are like-for-like:
| Android bundle | Bytes |
|---|---|
| Baseline | 15,968,353 |
| Tree-shaken | 13,007,862 |
| Delta | -2,960,491 (-18.54%) |
Module count is 7,828 either way, so this is dead-export elimination inside modules. That 18.54% is unreachable for any app using this package until the injection module survives the pass.
Possible fix
Emit the injection module as CJS, or register it so the optimize-graph pass runs it through the ESM to CJS transform before concatenation. Happy to test a patch.
- Ngôn ngữ chính
- TypeScript
- Star
- 166
- Fork
- 45
- Merge trung bình
- 13 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của nativewind/react-native-css
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nativewind/react-native-css#545 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nativewind/react-native-css#544 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nativewind/react-native-css#543 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
nativewind/react-native-css#540 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
nativewind/react-native-css#538 ·
Maintainer thường phản hồi trong vòng 3 ngày
Tất cả issue của nativewind/react-native-css
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
better-auth/better-auth#12132 · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
o8 next debug build aborts on Glass to Dark appearance switch (nil identifier messaged before check)Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
hurttlocker/o8#5112 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
webrecorder/wabac.js#386 ·
-
needs-triage
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 92/100
agent-of-empires/agent-of-empires#5098 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày