Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect resolve js file as directory #2825

Closed
chentsulin opened this issue Sep 18, 2015 · 17 comments
Closed

Incorrect resolve js file as directory #2825

chentsulin opened this issue Sep 18, 2015 · 17 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@chentsulin
Copy link
Contributor

In my project, I have directories structure like below:

/project-name
    /native
        /ios
        index.ios.js
    /src
        /containers
            App.js

And I require App.js in my index.ios.js:

var App = require('../src/containers/App');

I get a warning:

Unable to resolve module ../src/containers/App.js from /Users/username/Projects/project-name/native/index.ios.js

I thought we should not hide detail information about a happened error here:

// node_modules/react-native/packager/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js`

const forgive = (error) => {
      if (error.type !== 'UnableToResolveError') {
        throw error;
      }

      console.warn(
        'Unable to resolve module %s from %s',
        toModuleName,
        fromModule.path
      );
      return null;
};

Anyway, I add a console.error(error) for this, and see following error message print out:

{ [UnableToResolveError: Invalid directory /Users/username/Projects/project-name/src/containers/App]
  message: 'Invalid directory /Users/username/Projects/project-name/src/containers/App',
  name: 'UnableToResolveError',
  type: 'UnableToResolveError' }

Why require('../src/containers/App') will try to resolve a directory there? I expected it should resolve ../src/containers/App.js.

@mkonicek
Copy link
Contributor

@martinbigio Any ideas?

@brentvatne
Copy link
Collaborator

I believe the problem is that you cannot traverse up from the packager root. Whether this is desirable or not I am not sure...

@chentsulin
Copy link
Contributor Author

Actually, I work on a demo project and want to show people that we can use most of same flux (redux) code and different components files to build app for DOM(web and desktop apps which using electron), iOS, android and terminal (using react-blessed) at the same time.

So I reuse almost the same code as my ios-android demo, but moved src to the parent folder.

@chentsulin
Copy link
Contributor Author

I already have some successful attempts on DOM and terminal, but this approach break the react-native by this issue.

@cgilboy
Copy link

cgilboy commented Nov 12, 2015

From reading the react-native packager documentation, it seems like you may be able to specify an extra projectRoot (path to JS files) that points to /project-name/src if you launch the packager manually. This should allow the packager to see App.js.

To do this, you would edit the script portion of the package.json file in /project-name/src/ to look like this:
"scripts": { "start": "node_modules/react-native/packager/packager.sh --root ../src" },

Then you will need to manually run the packager via npm start from /project-name/native. Note that the React.xcodeproj does not use npm start to launch the packager, so if you do not manually start the packager, it will not see the extra source files.

I am not sure exactly what your require path would need to look like for this. Possibly:
var App = require('./containers/App');

It is entirely possible that this will run into some other issues with resolving the dependencies because the relative path does not match reality. This is an issue in my project because we are using Typescript which is perfectly happy to traverse up the file system to find other modules, but it chokes on the 'fake' relative path that would be needed here.

@mkonicek
Copy link
Contributor

Yup, if you're running the packager from within /project-name/native this won't work.

You can easily debug this by looking at the packager logs, it prints:

"Looking for JS files in ..."

It's only possible to require files that are under that path. You might be able run the packager from the top-level directory though by passing it the root (haven't tried this, please let us know if that works).

@mc-zone
Copy link

mc-zone commented Dec 7, 2015

@mkonicek I've try to set --root arg to parent path. And an error has occur.

2015-12-07 5 19 19

And there is my script use to launch application:

//start.js
var spawn = require('child_process').spawn;
var path = require('path');

spawn('sh', [
    path.resolve(__dirname, 'node_modules/react-native/packager', 'packager.sh'),
    '--projectRoots',
    process.cwd(),
    '--root',
    path.resolve(__dirname, '../'), //up to parent
], {stdio: 'inherit'});

Is it a babel transformer problem? Now I can't find the reason or solution for it. Any idea? Looking forward to your reply.

@brentvatne I think maybe traverse up from the packager root is desirable. For the reason of my team development progress, we have use two versions RN to our project: v0.10 to iOS and v0.14 to Android. So we have to keep two project for each other. And now I want to use some common files which should saved at parent path. Just like:

/project
    /ios
        index.ios.js
        package.json
    /android
        index.android.js
        package.json
    /common
        common.js

So maybe we need to consider how to implement it. Any advice or discuss about it? 😄

@bozzmob
Copy link
Contributor

bozzmob commented Dec 7, 2015

+1 I had the same issue. What I did was re-factor/re-arrange my folder structure, so that it'll work 😢

@martinbigio
Copy link
Contributor

It's not possible to traverse outside the default project root or the additional roots you specify as we need to cache a lot of the file system information to make the queries to the packager performant enough. In regards to the const error, I don't think the transformer has const/let enabled (transform-es2015-constants). @mkonicek we should consider upgrading the default transformer we provide to the community, should be quite easy :)

@martinbigio
Copy link
Contributor

I'll close the issue as we don't plan supporting being able to require files that are not included on the roots. Please re-open if you don't agree :)

@chentsulin
Copy link
Contributor Author

@martinbigio which folder structure you will suggest for a project that contains mobile and also web?

@martinbigio
Copy link
Contributor

how about @mc-zone proposal? I think he was running into an error just because the plugin transform-es2015-constants is not included on transformer.js

@mc-zone
Copy link

mc-zone commented Dec 9, 2015

@martinbigio Yes, but not all. I've fall into a trap dug myself.

As I mentioned above. I ran packager at my iOS project folder(v0.10, not support const), and set --root to parent folder. But I found it also pack my Android project files(v0.14 and support const, under the same folder with iOS project) into the jsbundle.

So maybe something was wrong with dependences resolve when traverse outside the root. And I've know it's not support on this way. I didn't continue to track it.

Currently, I've already achieve it through a workflow by self: write once at a folder, watch changed files and copy to each project (use Gulp temporarily).

And I also think it is cool if we can support it. Anyway, thank you for your reminder.

@martinbigio
Copy link
Contributor

@mc-zone could you share your configuration in case anyone else runs into this same issue?
@mkonicek this looks like an issue many people could run into. It would be great if we could either make watchman follow symbolic links (which is very hard to implement), Make the packager somehow support this use case, or provide better guidelines on what to do to solve the issue. IMHO having a ios/xplat and android/xplat copied from xplat could make the trick for now.

It's funny that at the moment I'm writing this answer the proposed watchman solution is #1 on product pains (https://productpains.com/post/react-native/symlink-support-for-packager/)

Anyways just wanted to flag this this for you :)

@zackify
Copy link

zackify commented Apr 24, 2017

I disagree with this being closed. The reason is simple. I have a react native app and web app in the same project. I would like to have the folder structure be: 'app' 'web' 'shared'

This way I can put redux, and other shared logic between the apps in one place instead of copy and pasting. I don't see an easy way to do this currently?

@SteveMellross
Copy link

I agree with zackify. It seems like a very common structure to have something along the lines of:

\project
    \app
    \web
    \common

Whatever the solution, I think it really needs to be compatible with IDE autocomplete. flow, lint, etc.

A (minor) problem with creating symlinks for the common folder in the app and web folders in the example above is that IDEs will show multiple copied of all the files in searches and other look-ups.

@AvishyBD
Copy link

check out this: #12241

Hope this helps...

@facebook facebook locked as resolved and limited conversation to collaborators Jul 21, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests