Open vjpr opened 5 years ago
I got this when trying to get Expo to work with yarn workspaces, using expo-yarn-workspaces
I've got the same issue when I tried to upgrade react-native to 0.57.0. I followed the steps mentioned the change log (https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md#057), but had no luck.
@Stephen2 me too, did you solve it?
Sorry, moved to different project
This is still a problem today with "react-native": "^0.59.2". Will there be real fix or do we need to copy/paste the workaround?
For anyone seeing this error when using expo-yarn-workspaces
, I got this and fixed it by simply deleting the auto-generated file (the file that the error points to) and deleting all the node modules and then just running yarn
again to re-install node modules and re-generate the file.
I am experiencing this on RN 0.60.5
Also fixes RN 0.61
Also fixes RN 0.61
Do you mean that on RN 0.61 it is working as expected?
Seeing the same issue as described on 0.60.5
. The workaround provided by @vjpr works - thank you! Looks like #455 should fix this. I'm curious why doesn't seem to be a bigger problem for everyone π
I made the change in ~/.config/yarn/global/node_modules/metro/src/node-haste/DependencyGraph.js
@dusan-dragon I needed the @vjpr fix to get RN 0.61 to work.
I'm having this issue on a windows 10 machine here. Same project on another dev machine with the same version of node doesn't display the issue.
put all files inside assets name of folder something like this
../../assets/beach.jpg
@donholly I am not sure why no one is flagging this issue more. I have just run in to this issue after I have setup a new terminal and cleaned up all my old node modules.
Thanks to @vjpr workaround it worked after rebuilding the app. Is this a miss on our part ? or is this being actively looked into ?
put all files inside assets name of folder something like this
../../assets/beach.jpg
This worked for me ikbal99
Works for me, 0.61.5
0.61.5 indeed works.
I also did npm i -g react-native-cli
- it updated cli to 2.0.1 version and bundling worked.
I solved this issue by using yarn start
instead of starting project withreact-native start
(it uses npm start).
I have been adding dependencies in project using Yarn add {dependencyName}
and starting project via npm. which created error of SHA-1.
I found it was an issue with me accessing the project on a second drive via a symlink on C: rather than navigating to the D: drive
I fixed it by install correct react-native-cli
:
yarn global remove react-native
yarn global add react-native-cli
Thanks @f4th4n it works for me
I had tried all the methods above but still not work for me. OS:mac Catalina node:13.3.0 watchman:4.9.0 react-native:0.61.5
the error log like this
Metro Bundler has encountered an error: SHA-1 for file /Users/.../Downloads/AwesomeProject/node_modules/metro/src/lib/polyfills/require.js (/Users/.../Downloads/AwesomeProject/node_modules/metro/src/lib/polyfills/require.js) is not computed
i had the same issue and fix it by following this steps
1- updating metro-react-native-babel-preset to version 0.57.0
2- resetCache: true in metro.config
3- removeing node modules & yarn lock file and reinstall
i had the same issue and fix it by following this steps 1- updating metro-react-native-babel-preset to version 0.57.0 2- resetCache: true in metro.config 3- removeing node modules & yarn lock file and reinstall
not work for me
I just ran into this issue while enjoying the fun task of upgrading from 0.59.1
to 0.61.5
with react-native-cli
.
My error made me realize I was running the bundler via a copy of react-native
that was installed to nvm
(Node Version Manager). Running which react-native
confirmed this: /Users/XXXXXX/.nvm/versions/node/v10.16.2/bin/react-native
I made sure to remove all 'global' installs of react-native:
Until which react-native
responded with react-native not found
Then in my project, npx react-native run-ios
worked.
--
Mac OS X 10.14.6
RN 0.61.5
npx react-native --version
3.0.4
same problem
I fixed it by install correct
react-native-cli
:yarn global remove react-native yarn global add react-native-cli
Works for me!!! :D
I fixed it by install correct
react-native-cli
:yarn global remove react-native yarn global add react-native-cli
npm start
worked for me
I made an update to jdk, version 11, and it works for me
I have installed again the react-native-cli and worked!
0.61.5 indeed works. I also did
npm i -g react-native-cli
- it updated cli to 2.0.1 version and bundling worked.
currently my project is on 0.61.5 but it showing the same error
Just got this with "react-native": "0.61.5"
, I installed react-native-cli
and init
ialized a new project today π
+1, ran into this with react-native 0.61.5 and react-native-cli 2.0.1. The only thing that's worked for me is the workaround provided by @vjpr.
I've just ran into this with react-native: 0.61.2
. @vjpr's workaround has temporarily fixed it for me.
I've tried lots of things including:
However, the above workaround is the only thing that's fixed it for me
Ran into the same issue.
In my case, it complained about not being able to create SHA-1 for timezones.json
, which is a package in my node_modules
(https://www.npmjs.com/package/timezones.json). Since this package was a dependency of another package, my solution was to rename the directory timezones.json
to timezones-json
and also change the require
in the corresponding package.
It seems that metro looks at the extension of the file and not at the file type, which caused it to think that a directory was a .json
file.
@vjpr solution worked for me, but any permanent solution for this?
@vjpr solution worked for me also. Is there a reason that code is not merged in?
I solved this issue by using
yarn start
instead of starting project withreact-native start
(it uses npm start). I have been adding dependencies in project usingYarn add {dependencyName}
and starting project via npm. which created error of SHA-1.
@bkhurjawal worked for me, thanks!!
I wrote a patch for it that works with the existing metro package.
Install the following dependency
npm install --save mod-inline
Create the following file
install.js
const fs = require('fs');
const modInline = require('mod-inline').default;
const path = require('path');
const GET_FILE_HASH = / {4}if \(!sha1\) {\n {6}return getFileHash\(resolvedPath\);/;
const GET_SHA1_FUNC = / {2}getSha1\(filename\) {((\n {4}.*|\n)+)+ {2}}/;
const IF_SHA1 = / {4}if \(!sha1\) {/;
const dependencyGraphPath = path.resolve(
__dirname,
'../node_modules/metro/src/node-haste/DependencyGraph.js'
);
const content = fs.readFileSync(dependencyGraphPath).toString();
const patched = !!modInline.isolate(
modInline.isolate(content, GET_SHA1_FUNC),
GET_FILE_HASH
);
if (!patched) {
const patchedContent = modInline.append(
content,
[GET_SHA1_FUNC, IF_SHA1],
`
return getFileHash(resolvedPath);
function getFileHash(file) {
return require('crypto')
.createHash('sha1')
.update(fs.readFileSync(file))
.digest('hex');
}`
);
fs.writeFileSync(dependencyGraphPath, patchedContent);
}
Add the following script to the package.json
{
"scripts": {
"install": "node ./install.js"
}
}
same issue, tried on several osx and only @vjpr's solution helped any other workarounds? and why is it not fixed officially?
OS:mac Catalina 10.15.4 node:10.16.3 watchman:4.9.0 react-native:0.62.2
Finally got what went wrong here, folder name has 1 upper case character in require. eg. require(../../../assets/marketPlace/banner.png)
. Here "p" was upper case here but folder was with lower case p. After changing require path it was working again.
Hello, I have this problem and then fixed it by using directly the
node_modules/react-native/scripts/launchPackager.command
instead of react-native start
If you have any further investigation on this please let me know
I have this same error with the following code:
import { createIconSet } from '@expo/vector-icons';
const glyphMap = {
'kk-logo': 0xf101,
};
const expoAssetId = require("../.cache/iconfont/iconfont.ttf");
const CustomIcon = createIconSet(glyphMap, 'iconfont', expoAssetId);
export default CustomIcon;
../.cache/iconfont/iconfont.ttf
is a custom font generated using svgs.
It was working fine, then my Macbook restarted after an update, now I get this error no matter what I do. Tried clearing caches, tmp directories, etc. but nothing works.
I created a new blank React Native app and got this same error about SHA1 and require.js
. My React Native application name had a mixed-case name, ex. MyApp
. Recreated the same app a half dozen times with different versions of node and React Native and same error each time.
Then I created the same app but named it myapp
and didn't have this problem. It just worked.
Thanks @vjpr, you saved me hours. I can't believe Github doesn't offer some sort of donation button.
Just an update on why this happens.
Here is the function that is generating the message:
https://github.com/facebook/metro/blob/master/packages/metro/src/node-haste/DependencyGraph.js#L208
getSha1(filename) {
// TODO If it looks like we're trying to get the sha1 from a file located
// within a Zip archive, then we instead compute the sha1 for what looks
// like the Zip archive itself.
const splitIndex = filename.indexOf(".zip/");
const containerName =
splitIndex !== -1 ? filename.slice(0, splitIndex + 4) : filename; // TODO Calling realpath allows us to get a hash for a given path even when
// it's a symlink to a file, which prevents Metro from crashing in such a
// case. However, it doesn't allow Metro to track changes to the target file
// of the symlink. We should fix this by implementing a symlink map into
// Metro (or maybe by implementing those "extra transformation sources" we've
// been talking about for stuff like CSS or WASM).
const resolvedPath = fs.realpathSync(containerName);
const sha1 = this._hasteFS.getSha1(resolvedPath);
if (!sha1) {
throw new ReferenceError(
`SHA-1 for file ${filename} (${resolvedPath}) is not computed`
);
}
return sha1;
}
Here is the function that gets the sha1 from the haste map:
jest-haste-map/build/worker.js
function _getSha() {
_getSha = _asyncToGenerator(function*(data) {
const sha1 = data.computeSha1
? sha1hex(_gracefulFs().default.readFileSync(data.filePath))
: null;
return {
dependencies: undefined,
id: undefined,
module: undefined,
sha1
};
});
return _getSha.apply(this, arguments);
}
When metro
resolves a file it looks for the file in a jest-haste-map
which also watches for changes to these files. There are two implementations for building a haste map (crawling the file tree from the project roots):
watchman
native (c++, rust, etc.) library.
jest-haste-map/build/crawlers/watchman.jsBoth don't support following symlinks...so if you have any symlinks in your project root that point to files outside of the project root, then they will never make it into the haste map which also means they will never be watched. It was the first feature request for metro
5 years ago and its unresolved. You can see the issue here: https://github.com/facebook/metro/issues/1#issuecomment-641633646
So there are two situations here.
a. Your symlink points to a file that is inside your project root.
b. Your symlink points to a file outside of your project root.
E.g. If you are using a pnpm-based monorepo, all your symlinks resolve to the monorepo root. So if expo
is nested inside the monorepo, then you symlinks will always point outside the project root.
For a
, your sha-1
will actually be found, because your file's realpath will be in the haste map.
For b
, your sha-1
will not be found because your file's realpath is not in the haste map.
When metro
requires a file it needs to transform it. It first checks if its transformation is cached in a metro-cache
. The sha-1
of the file is used as part of the cache key.
If its not in the cache, the file contents is actually read not from the haste map but from the file system. So if your file was symlinked to outside of a project root, it won't be in the haste map at all, and the sha1 can't be accessed...but it will still be able to be loaded fine.
extraNodeModules
If you look inside metro-resolver#resolve
you can see that extraNodeModules[packageName]
is added to the list of search paths.
allDirPaths
looks like this:
"/dev/my-monorepo/packages/app-templates/expo/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/dev/my-monorepo/packages/app-templates/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/dev/my-monorepo/packages/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/dev/my-monorepo/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/dev/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/node_modules/@babel/runtime/helpers/interopRequireDefault"
"/dev/my-monorepo/packages/app-templates/expo/node_modules/@babel/runtime/helpers/interopRequireDefault"
Note how the last path comes from the extraPaths
.
NOTE: These paths are candidate paths, not dirs to search for packages in.
The extraNodeModules
proxy hack is clever, as it allows you to take the packageName and resolve it how you would like. Similar could be done with resolveRequest
but its more complicated.
A downside though is you do not get access to where the require is being made from...so it is only really viable if your package is hoisted in yarn. This is unreliable though! If you have two packages of same version, then only one is hoisted and the other is not which could cause crazy bugs.
Overriding resolveRequest
is the much safer option.
One spanner in the works though is that inside the resolver context.doesFileExist
is called to check if the logical file path exists - not the realpath.
In pnpm:
$ realpath /dev/my-monorepo/packages/expo/node_modules/@babel/runtime/helpers/interopRequireDefault.js
/dev/my-monorepo/node_modules/.pnpm/registry.npmjs.org/@babel/runtime/7.10.2/node_modules/@babel/runtime/helpers/interopRequireDefault.js
So for a monorepo in a pnpm setup, this will prevent files being found, even if you add the monorepo root to the watchFolders
.
_getFileData(file) {
const relativePath = fastPath.relative(this._rootDir, file);
return this._files.get(relativePath);
}
Including the entirety of the monorepo as a watchFolder
may slow down the app startup. Expo will actually work without needing to include every node_module
, but then you need to make the sha1 patch and doesFileExist
patch.
We can modify ctx.doesFileExist
in the resolver#resolveRequest
metro config setting. I'm not sure if this will cause problems if resolve a logical path rather than a real path.
LATER: Maybe we could use hasteImplModulePath
option to provide a custom haste map that supports symlinks too.
In terms of a clean solution, I think it is best to ensure that all the files that you would possibly require make their way into the haste map, which I think is possible by setting watchFolders
in the metro config.
I'm leaving this long explanation here because I had completely forgotten it since I last looked at it, and was hoping there was a fix by now but it seems not.
Symlinks will not be followed, so you will need to make sure the folders they point to are added to the haste map by including them as watchFolders
.
extraNodeModules
doesn't add files to the haste map, it will only provide additional candidate resolve paths...but they will still need to be in the haste map.
getSha1
function, and you might need to patch the metro-resolve#resolve
function.I'm thinking there might be a way to monkey-patch the library without needing a patch.
Just need to intercept the require of node_modules/metro/src/node-haste/DependencyGraph.js
and override its getSha1
method. Could probably add the require hook when metro.config.js
is called...
I think I found a simple explanation for this problem. See https://github.com/facebook/jest/issues/10063#issuecomment-642356808.
When metro
talks to watchman
it sends a query
with a glob
option. When a glob
is used it prevents files and folders starting with a dot from being returned by the watchman query. There is an option to pass called glob_includedotfiles
which includes dot files.
Depending on whether the clock is available, if glob
is not used, then you are not going to get any dotfiles or dot dirs included.
So this explains the sporadic behaviour.
const relativeRoot = fastPath.relative(rootDir, root);
const query = clocks.has(relativeRoot) // Use the `since` generator if we have a clock available
? {
expression,
fields,
since: clocks.get(relativeRoot)
} // Otherwise use the `glob` filter
: {
expression,
fields,
glob
};
const response = yield cmd('query', root, query);
This explains why @SeanHayes was having a problem until his MacBook restarted.
And it also explains why pnpm
doesn't work because all its deps are found in node_modules/.pnpm
which includes a dir starting with a dot.
Its a one line fix that is in the pipeline but I feel like I went to the ends of the earth to track it down.
@vjpr
You are right about symlinks, on windows I had this problem with the "Documents" directory. It is spelt "Documenti" in Italian if you run the "yarn start" using the "Documenti" alias instead of the "Documents" it fails with the SHA-1 computed error.
So c:/users/[username]/Documenti - (Italian version) fails c:/users/[username]/Documents - works
Running the command from the "Documents" path works just fine.
I make it work for this:
npx react-native bundle --platform ...
but not work when I use like this:
react-native bundle --platform
didn't know why!
Same experience like @jinyuyoulong
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
I am using a custom
resolver.resolveRequest
function inrn-cli.config.js
. See https://facebook.github.io/metro/docs/en/configuration#resolver-options.The error message is being printed from
metro/src/node-haste/DependencyGraph.js#getSha1
, which is being called bymetro/src/Bundler.js#transformFile
:metro/src/node-haste/DependencyGraph.js#getSha1
The issue is that the file won't exist in the haste map if you are resolving it in the
resolveRequest
hook.If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can
yarn install
andyarn test
.https://github.com/vjpr/expo-v2-test-pnpm/tree/broken
You need to run
pnpm install
(the reason for the custom resolver is because symlinks are not supported by metro and hence cause problems for pnpm).What is the expected behavior?
getSha1
should compute hash if not in haste map.Please provide your exact Metro configuration and mention your Metro, node, yarn/npm version and operating system.
metro@0.45.6 node@8.9.0 pnpm@2.21.1
Workaround
Add to metro/src/node-haste/DependencyGraph.js#getSha1:
I have released a patched version here: Use
metro-pnpm@0.45.6-vjpr.2