fix(metro-service): pass asset plugins on to Metro - #4354
fix(metro-service): pass asset plugins on to Metro#4354Bao Nguyen (giaBaoJS) wants to merge 2 commits into
Conversation
`loadMetroConfig` referenced a bare `assetPlugins` identifier that is not declared in the module, so any project configuring asset plugins crashed with `ReferenceError: assetPlugins is not defined`. The `@ts-expect-error` directive above it suppressed the `TS2304` that would have caught this. Assigning `overrides.assetPlugins` alone is not enough: on React Native 0.72 and above the default config provider returns an empty object, so `defaultConfig.transformer` is `undefined` and the assignment throws `TypeError: Cannot set properties of undefined`. Build the input config instead, keeping any transformer options the provider did return.
Tommy Nguyen (tido64)
left a comment
There was a problem hiding this comment.
Thanks for fixing this. Do you think we can pass in the getDefaultConfig function in tests instead? We can change the loadMetroConfig signature like below:
diff --git a/packages/metro-service/src/config.ts b/packages/metro-service/src/config.ts
index dead5d1b0..7faa99402 100644
--- a/packages/metro-service/src/config.ts
+++ b/packages/metro-service/src/config.ts
@@ -208,9 +208,9 @@ function getDefaultConfigProvider(
*/
export function loadMetroConfig(
cliConfig: CLIConfig,
- overrides: MetroConfigOverrides
+ overrides: MetroConfigOverrides,
+ /** @internal */ getDefaultConfig = getDefaultConfigProvider(cliConfig.root)
): Promise<ConfigT> {
- const getDefaultConfig = getDefaultConfigProvider(cliConfig.root);
const defaultConfig = getDefaultConfig(cliConfig);
if (overrides.assetPlugins) {This way we don't have to create fixtures for every edge case.
Address review feedback: loadMetroConfig now takes an internal getDefaultConfig parameter so tests can supply one directly. The per-edge-case default config fixtures are gone; a single fixture remains to stub metro-config.
|
Done, pushed. The two per default config fixtures are gone. One fixture remains because Trade off worth flagging: |
Description
loadMetroConfigthrows as soon as a project configures asset plugins.rnx-kit/packages/metro-service/src/config.ts
Lines 216 to 219 in 84d6e47
There are two problems on that one line:
assetPluginsis not declared anywhere inconfig.ts. The only binding inscope is the
overridesparameter, whose type declaresassetPlugins?: string[]at
config.ts:21.Reading the free identifier throws
ReferenceError: assetPlugins is not defined.The
@ts-expect-errorabove it suppresses the whole line, so theTS2304that would have caught this never surfaced (the directive only claims to be
silencing the read-only assignment,
TS2540).overrides.assetPluginsis still not enough. On ReactNative 0.72 and above,
getDefaultConfigProviderreturns() => ({})because
@react-native/metro-configresolves, sodefaultConfig.transformeris
undefinedand the assignment throwsTypeError: Cannot set properties of undefined (setting 'assetPlugins').This builds the input config handed to
loadConfiginstead of mutating apossibly absent nested object, and keeps whatever
transformeroptions thedefault config provider did return. The
@ts-expect-erroris no longer neededbecause nothing read-only is written to.
Reachable from
rnx-cli start:serve/kit-config.ts:45merges
assetPluginsinto the server config, andstart.ts:76-82passes them into
loadMetroConfig. Sornx-cli start --asset-plugins <list>,or a
rnx-kit.server.assetPluginsentry inpackage.json, hits it.Note that
assetPluginsis not part of Metro'sYargArguments, so spreadingoverridesintoloadConfigdoes not carry it; the explicit assignment isstill needed.
Test plan
loadMetroConfigtakes the default config provider as an optional thirdparameter (
/** @internal */ getDefaultConfig), so tests can supply onedirectly instead of needing a fixture per default config shape.
packages/metro-service/test/config.test.tscovers both shapes:transformeris absent.transformer, as returned by@react-native-community/cli-plugin-metro.One fixture under
test/__fixtures__/metro-config/remains, stubbingmetro-configso the test can inspect the config thatloadConfigwas handed.With the fix (
packages/metro-service):Reverting only the body of
loadMetroConfigto its state onmain, both gored for the right reason:
Applying only the one-word fix (
assetPluginstooverrides.assetPlugins,directive kept) shows the second problem in isolation:
yarn build,yarn test,yarn lintandyarn formatare clean inpackages/metro-service.