React-native: Upgrade to RN 0.49 - bundling failed: Error: require() must have a single string literal argument

Created on 5 Oct 2017  路  72Comments  路  Source: facebook/react-native

Is this a bug report?

yes

Have you read the Contributing Guidelines?

yes

Environment

react-native.cmd info
Scanning folders for symlinks in D:\code\msu.Reading\node_modules (18ms)

Environment:
OS: Windows 10
Node: 7.0.0
Yarn: 1.0.2
npm: 3.10.9
Watchman: Not Found

Steps to Reproduce

  1. having production app in RN 0.48
  2. upgrade to RN 0.49 and react 16.0.0-beta.5

react-native run-android:

Expected Behavior

Normal app start

Actual Behavior

error: bundling failed: Error: require() must have a single string literal argument
    at pushDependency (D:\code\msu.Reading\node_modules\react-native\node_modules\metro-bundler\src\JSTransformer\worker\extract-dependencies.js:39:13)
    at CallExpression (D:\code\msu.Reading\node_modules\react-native\node_modules\metro-bundler\src\JSTransformer\worker\extract-dependencies.js:50:9)
    at NodePath._call (D:\code\msu.Reading\node_modules\babel-traverse\lib\path\context.js:76:18)
    at NodePath.call (D:\code\msu.Reading\node_modules\babel-traverse\lib\path\context.js:48:17)
    at NodePath.visit (D:\code\msu.Reading\node_modules\babel-traverse\lib\path\context.js:105:12)
    at TraversalContext.visitQueue (D:\code\msu.Reading\node_modules\babel-traverse\lib\context.js:150:16)
    at TraversalContext.visitMultiple (D:\code\msu.Reading\node_modules\babel-traverse\lib\context.js:103:17)
    at TraversalContext.visit (D:\code\msu.Reading\node_modules\babel-traverse\lib\context.js:190:19)
    at Function.traverse.node (D:\code\msu.Reading\node_modules\babel-traverse\lib\index.js:114:17)

image

Related

https://github.com/realm/realm-js/issues/1342
https://github.com/realm/realm-js/pull/1346

Locked

Most helpful comment

I have same issue with <Image /> component from react-native.

Example:

import {Image} from 'react-native';
...
const imageUri = '../../../assets/images/bg.png';
...
<Image source={require(imageUri)} />

And Metro bundler throw this Error:
TransformError: require() must have a single string literal argument. (null)

All 72 comments

its fixed in the new version of realm ("realm": "1.13.0"). this is not reactnative issue

I don't use realm

which lib has the problem? i had the same issue in Realm and Moment. and both i needed to find a work around for them. you might need to find the require line and fix it. :/

the screenshot is all I'm seeing

@forki Are you using moment js?
The bug is in the bundler: https://github.com/facebook/metro-bundler/issues/65

react-native-modal-datetime-picker@^4.11.0:
  version "4.11.0"
  resolved "https://registry.yarnpkg.com/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-4.11.0.tgz#bd2eb3a21cda584c6a018b11f6aed4bf4d020aca"
  dependencies:
    moment "^2.18.1"
    prop-types "15.5.10"
    react-native-modal "3.1.0"

@jeremistadler so what should I do?

@forki Try moment:"git+https://github.com/tqc/moment.git#no-dynamic-import"

I added the following to package.json

"dependencies": {
  "buffer": "^5.0.7",
  "core-js": "^2.5.1",
  "react": "16.0.0-beta.5",
  "react-native": "0.49.1",
  "react-native-modal-datetime-picker": "^4.11.0",
  "react-native-image-picker": "0.26.7",
  "react-native-image-resizer": "1.0.0",
  "react-native-camera": "0.10.0",
  "moment": "git+https://github.com/tqc/moment.git#no-dynamic-import",
  "react-native-signature-view": "https://github.com/forki/react-native-signature-view.git#patch-1"
},

but now yarn gives me two entries for moment:

moment@^2.18.1:
  version "2.18.1"
  resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"

"moment@git+https://github.com/tqc/moment.git#no-dynamic-import":
  version "2.18.1"
  resolved "git+https://github.com/tqc/moment.git#7fb40264e87ff7c8d167c6ccda9aecac70516302"

that doesn't seem right and also doesn't fix it

I'm having the same issue with moment. I use react-native-datepicker, which uses moment as its subdependency. Is there a way I can point the react-native-datepicker's moment to the "git+https://github.com/tqc/moment.git#no-dynamic-import"?

@binchik I think you need to fork react-native-datepicker and change it there to fix it.. 馃槩

@albinekb Yeah just did that, thanks. Here is my fork, for anyone having the same issue. https://github.com/binchik/react-native-datepicker

Same error reproduced. For me, I have the package moment-timezone. Was fine on RN 0.48.1.

+1 this has broken so many dependencies. I'm hosed until we have a fix.

@anwarhamr Same.

+1

Metro Bundler breaks again.

I reverted to 48.4 and working again. I hope this is fixed soon. 馃拑

ok is someone from RN team able to explain the strategy to fix it completely?

It's so recent, and I think should be fixed asap. By upgrading to 0.49.1, on first build I got this error on load image with require(imageLocation), and second build got complain from moment.

it's happening when you require an image?! wtf

/cc @alfonsogarciacaro looks like you had the right idea. unfortunately

yeah, basically you'll get the error if doing this against RN 0.49.1:

let packageOrImageLocation = 'path/to/the/target';
require(packageOrImageLocation); //here require not see single string literal

So it's big problem if the image comes from backend response.

Yep unfortunately moment.js has a require that isn't a string literal, will also be reverting to .48 until this gets sorted 馃槙

With @willymulyana 's example. Is dynamic imports correct Javascript? If so, there's no excuse for "it not being supported" especially when it breaks popular libs like Moment.

@hramos any official statement from the RN team?

There's a lot more discussion about this here https://github.com/facebook/metro-bundler/issues/65

@binchik
I have the same issue and stupid question if there are, (i'm a beginner) but to install your fork, I have to do :
npm install --save binchik/react-native-datepicker ?
Probably not, has it doesn't work...

I am facing the same issue while using react-native-gifted-chat.
Hope it will be fixed soon.

@johanschram Yes, that should work. I use yarn add binchik/react-native-datepicker in my own project. Maybe there is another dependency using moment in your project?

The issue is discussed here : https://github.com/facebook/metro-bundler/issues/65

You can apply the fix to the Metro Bundler : https://github.com/facebook/metro-bundler/pull/69

@Crash-- shouldn't this be done in more general fashion? Like release a RN update or retract the current version?

Of course yes! I just pointed out a global workaround for this issue until we find how to fix it in RN release

+1
(Upgraded to 0.49.2)

got bitten by this as well

For those of you who need to get unstuck right now and are only running into this issue with moment - this worked for me:

yarn remove moment; yarn add https://github.com/tqc/moment.git#no-dynamic-import

One this PR gets merged, you should be able to revert back to just the original moment

@dwilt is moment also the reason why people can't use images anymore?

@forki No, I don't believe so. I'm on RN 0.49.3 and haven't run into this issue that others have mentioned -- just the moment one. I'm using images all over my application too. Are you dynamically importing them?

require(`${someVar}/file.png`)?

@binchik : seems to be a npm issue. It worked perfectly with yarn.
Thanks !

Another way to work around this issue is using yarn 1.0+ and in package.json

"resolutions": {
    "moment": "git+https://github.com/tqc/moment.git#no-dynamic-import"
  },
  "dependencies": {
    "moment": "^2.18.1",
[...]

In my case, moment is installed as dependency for react-native-gifted-chat.
I tried uninstall moment manually and then reinstalled https://github.com/tqc/moment.git#no-dynamic-import, but still get the same

@gurudev51 did you add

"resolutions": {
  "moment": "git+https://github.com/tqc/moment.git#no-dynamic-import"
}

to your package.json first? (and make sure you use yarn)

Still the same issue, I can't see what's fixed here.
I removed moment manually, added again using yarn from https://github.com/tqc/moment.git#no-dynamic-import but still get "require() must have a single literal argument" error in node_modules/moment/moment-with-locales.min.js

@mschipperheyn Still no problem solved

"resolutions": {
"moment": "git+https://github.com/tqc/moment.git#no-dynamic-import"
},
"dependencies": {
"antd-mobile": "^1.6.11",
"async-validator": "^1.8.1",
"dva-core": "^1.1.0",
"lodash": "^4.17.4",
"moment": "^2.18.1",
"rc-form": "^1.4.8",
"react": "^16.0.0-beta.5",
"react-native": "^0.49.3",
"react-native-snap-carousel": "^3.3.3",
"react-native-webp": "^0.3.1",
"react-navigation": "https://github.com/react-community/react-navigation.git",
"react-redux": "^5.0.6",
"redux-logger": "^3.0.6",
"redux-persist": "^4.10.1"
},

Just put comment the require('./locale/' + name); in the \node_modulesmoment.js

Hey everyone, you should be able to resolve this issue now by pointing to the new version of metro-bundler using Yarn's selective dependency resolutions. Here's an example of what it should look like in your package.json:

  "dependencies": {
    "react": "16.0.0-beta.5",
    "react-native": "0.49.3"
  },
  "resolutions": {
    "react-native/metro-bundler": "0.20.0"
  },

Read more about Yarn's selective dependency resolutions here if you'd like to understand why this would work, vs adding the new version of metro-bundler directly into your dependencies block.

is there no way for FB to push a hotfix in RN?

@forki I think it comes down to how many commits made it into the latest version of metro-bundler and whether or not additional breaking changes could be introduced by hot fixing RN. Will leave to @grabbou to weigh in on a potential hot fix.

Fixed in moment 2.19.0, working for me with RN 0.49.3.

https://github.com/moment/moment/blob/develop/CHANGELOG.md

There appears to be an issue with metro-bundler 0.20.0 right now so a hot fix to RN is probably not a good idea until that gets figured out. If your issue is with moment specifically, the new version of moment that @tonybennett called out is probably the safest route for now.

EDIT: the issue I was talking about: https://github.com/facebook/metro-bundler/issues/73

nice so no need to put a comment on the require('./locale/' + name); in the \node_modulesmoment.js

  1. add "resolutions": {
    "moment": "2.19.0"
    },

  2. delete "react-native/metro-bundler": "0.20.0"

To solve the

thank @tonybennett

@gurudev51
I'm having the same problem "require() must have a single literal argument" error in node_modules/moment/min/moment-with-locales.min.js

It looks like only "moment.js" was fixed in moment 2.19.0.
"min/moment-with-locales.min.js" still has a require() that RN 0.49 doesn't like.

upgrading to 0.49 is a pain going to wait till later versions since a handful of dependancies broke.

any update? moment was upgraded to 2.19 but I'm still facing this error.

How can I discover which packages causes this error?

Bundling `index.js`  [development, non-minified]  99.4% (1401/1405), failed.
error: bundling failed: Error: require() must have a single string literal argument
    at pushDependency (/home/prado/projects/fitfood-app/node_modules/metro-bundler/src/JSTransformer/worker/extract-dependencies.js:39:13)
    at CallExpression (/home/prado/projects/fitfood-app/node_modules/metro-bundler/src/JSTransformer/worker/extract-dependencies.js:50:9)
    at NodePath._call (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/home/prado/projects/fitfood-app/node_modules/babel-traverse/lib/index.js:114:17)

Changing
import moment from 'moment/min/moment-with-locales.min';
to
import moment from 'moment/min/moment-with-locales';

seems to work for me.

Suggest ignoring this version and not upgrading to 4.9.x

release There are bugs

I have this bug in RN 0.50.3

I have this bug in RN 0.50.4

trying metro-bundler 0.22.1 resolutions using yarn. but getting this exception

this._opts.getModulesRunBeforeMainModule is not a function

https://github.com/facebook/metro/issues/101

"resolutions": {
    "react-native/metro-bundler": "0.22.1",
  },

Working on RN 0.51.0. Finally! 馃憤

I have same issue with <Image /> component from react-native.

Example:

import {Image} from 'react-native';
...
const imageUri = '../../../assets/images/bg.png';
...
<Image source={require(imageUri)} />

And Metro bundler throw this Error:
TransformError: require() must have a single string literal argument. (null)

I am on RN 0.51 even with moment 2.19.0 and the bug persists.

I have exact same error as @joaom182. Dynamic import for an Image

@grabbou you closed this - but it still persists in RN 0.53

@joaom182 @jpmoyn This is not a bug, dynamic image imports via require have never been supported.

See https://facebook.github.io/react-native/docs/images.html#images-from-hybrid-app-s-resources

@kyle-ssg the problem is that require now only accepts string literals - not strings that have been computed. that used to work.

@forki Sorry but I'm going to have to correct you, I found out this 2-3 years ago attempting to use computed strings. This is due to the way react native packages assets and is not a require related issue. See this 3 year old doc https://github.com/facebook/react-native/blob/0.5-stable/docs/Image.md

we need to find a way to know statically which images are being used in the app. To do that, we introduced a marker on require. The only allowed way to refer to an image in the bundle is to literally write require('image!name-of-the-asset') in the source.

@kyle-ssg I have code, with UI Tests, that work /shrug

For requiring images ? Well I'd love to see how you managed that 馃槃

Upgrade to 0.53.0 a couple things changed but, everything is smooth!

@kyle-ssg I have a theory about why it may have worked for us. What if the image files were already bundled? Then the "static marker" would not be needed, right? Then require may have just worked as no-op and would have transported the computed file name to the image component. With the change that now require only accepts literals, this behaviour broke. Does this sound plausible?

For guys having troubles with images - to do dynamic import you need to require different images in advance and based on some conditions later you put what you want:

function Arrow(prop) {
  const imgUpDirection = <Image source={require('./triangleUp.png')} />;
  const imgDownDirection = <Image source={require('./triangleDown.png')} />;
  const imgRightDirection = <Image source={require('./triangleRight.png')} />;
  let appliedDirection = imgUpDirection; // by default it is up
  if (prop.val === 0) {
    appliedDirection = imgRightDirection;
  } else if (prop.val < 0) {
    appliedDirection = imgDownDirection;
  }
  return (
    <Text>
        {appliedDirection}
    </Text>
  );
}

then

Just import moment from 'moment'; worked for me.

Was this page helpful?
0 / 5 - 0 ratings