question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[babel-expo-preset] Can't pass options to `react-native-web` preset in a multi-platform app

See original GitHub issue

Summary

There seems to be no way to set options for the react-native-web babel plugin when using babel-preset-expo without causing the plugin to apply in native builds too, which breaks them:

  • Within babel-preset-expo, the setup of babel-plugin-react-native-web is hardcoded to have no options: https://github.com/expo/expo/blob/main/packages/babel-preset-expo/index.js#L107
  • Users can’t configure babel-plugin-react-native-web in their own babel config without it applying to all builds, breaking native builds
  • The logic within babel-preset-expo that conditionally applies babel-plugin-react-native-web only on web depends on api.caller() data that is only passed to babel-preset-expo. Knowledge of platform seems to be unavailable anywhere in own babel.config.js. There’s also nothing about platform in process.env when the build is launched through Expo’s own interface.
  • I’ve seen some mentions of web/webpack.config.js for web-specific webpack config; but web/babel.config.js is ignored; I also saw some mention somewhere of defining web.build.babel object in app.json but this caused the build to fail silently with no log output.

If the platform is only available within babel-preset-expo, there should be a way to pass config options in; if there isn’t a way to pass config options in, there should be a way to conditionally apply the plugin based on the current build’s target platform; but there’s neither.

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

managed

What platform(s) does this occur on?

Web

SDK Version (managed workflow only)

44

Environment

  expo-env-info 1.0.2 environment info:
    System:
      OS: macOS 11.6.4
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 16.1.0 - ~/.nvm/versions/node/v16.1.0/bin/node
      Yarn: 1.22.17 - ~/.nvm/versions/node/v16.1.0/bin/yarn
      npm: 8.5.3 - ~/.nvm/versions/node/v16.1.0/bin/npm
      Watchman: 2021.06.07.00 - /usr/local/bin/watchman
    Managers:
      CocoaPods: 1.10.1 - /usr/local/bin/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
      Android SDK:
        API Levels: 29, 30
        Build Tools: 29.0.2, 30.0.3
        System Images: android-29 | Intel x86 Atom_64, android-30 | Google APIs Intel x86 Atom
    IDEs:
      Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
    npmGlobalPackages:
      expo-cli: 5.3.0
    Expo Workflow: managed

Reproducible demo

// babel.config.js in a new Expo app
module.exports = function (api) {
  // This always returns undefined: platform is unavailable outside babel-preset-expo internals?
  const platform = api.caller((caller) => caller?.platform)

  // Adding 'react-native-web' plugin without a platform check breaks native builds; but platform
  // check is not possible? So plugins applied here are either "all platforms" or "no platforms"?
  const plugins = platform === 'web' ? [['react-native-web', { commonjs: true }]] : []

  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    plugins
  }
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
AlanSlcommented, Mar 21, 2022

But - I wouldn’t expect babel-preset-expo to have hardcoded support for specific individual babel-plugin-react-native-web options. That just creates maintenance burden and room for version mismatch. Rather, I’d expect either:

  1. (preferred because it opens lots of possibilities) Making platform etc available somehow in an app’s babel.config.js when an expo build is done, e.g. making it available to the app’s api.caller so it’s possible for the user to do the same conditional logic as babel-preset-expo does internally:

    // babel.config.js in a new Expo app
    module.exports = function (api) {
      const platform = api.caller((caller) => caller?.platform)
    
  2. (less preferred since it’s RNW-only) Accept an object of rnw plugin options and replace this:

    platform === 'web' && [require.resolve('babel-plugin-react-native-web')],
    

    …with something that takes an optional object of options from options.web, like:

    platform === 'web' && [require.resolve('babel-plugin-react-native-web'), web.reactNativeWeb],
    
0reactions
AlanSlcommented, Sep 26, 2022

I think this is still an issue.

(couldn’t respond within the bot’s 7 days because I was away last week)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Startupjs - Universal React Native + Web framework with ...
Go into the created project folder and start the web application with: yarn start ... Enter: pug:source.pug; Go to Core settings of atom....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found