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

Support importing files from outside of the root folder #5563

Closed
shaneosullivan opened this issue Oct 25, 2018 · 26 comments
Closed

Support importing files from outside of the root folder #5563

shaneosullivan opened this issue Oct 25, 2018 · 26 comments
Labels

Comments

@shaneosullivan
Copy link

Is this a bug report?

No

The current stance of CRA to disallow importing files from outside the root folder of an app forces the most involved users, those with multiple projects, to jump through hoops that should be unnecessary in order to share code, both components and utils.

Current options are

  • Symlink folders. This apparently is flakey (Symlink behaviour #3547) and can potentially cause issues running on Windows
  • Copy the source files into multiple locations every time they are modified, and check in many copies of hundreds of files. This is our current approach at my company as it works well in CI, but results in human error when newbs edit the copied file rather than the original, and is messy with hundreds of unnecessary copies existing in the codebase.

If we can allow CRA project to just act as another non-special folder in a larger mono-repo, and import files from outside it's root folder, it would greatly improve the experience of working with many CRA projects while keeping all the benefits of not ejecting.

@bugzpodder
Copy link

My best experience is w/ using yarn workspaces.

@miraage
Copy link

miraage commented Oct 25, 2018

It was made intentionally to prevent users from importing something wrong.
You can either use workspaces or eject and remove ModuleScopePlugin from the resolve.plugins option in both dev/prod configuration.

@audiolion
Copy link

I personally am having one hell of a time getting CRA to work with yarn workspaces.

With the following setup:

packages/graphql - all my graphql fragments, queries, mutations, subscriptions
packages/controllers - shared JSX code between web/native
packages/web - cra 2.0
packages/native - react native

CRA says, oh you want to do graphql just use babel-plugin-macros with graphql.macro except that library only supports relative path imports, not an import like @monorepo/graphql/queries/user.graphql

CRA also doesn't support monorepo so I have to setup webpack, parcel, or something similar to bundle my JSX, but also to run the babel macros and have it all compiled so react can import it. It just seems to defeat the purpose of CRA, I want my imported code to run under the same config options that CRA has and not have to duplicate it all and have a separate bundler running in packages/controllers.

If I don't use a monorepo to share my code, then I am publishing a private npm package every time I make a change.

@shaneosullivan
Copy link
Author

@miraage I know it was intentional, and there were reasons. I'd like to see those reasons revisited given the inordinate amount of hacks it requires to work with multiple projects, which I presume was not fully appreciated at the time the decision was made.

A config option to let projects opt out of this feature would be sufficient, where the majority of people still get the same behavior but power users do not have arbitrary barriers to good hygiene put in their way

@eddiemonge
Copy link
Contributor

If I don't use a monorepo to share my code, then I am publishing a private npm package every time I make a change.

You don't have to publish the package. In your package.json just specify the local path to module

@audiolion
Copy link

You don't have to publish the package. In your package.json just specify the local path to module

so I currently have a package.json everywhere, but because these are located outside the cra folder root, they aren't compiled, so I am currently running babel src --watch --out-dir dist in my other packages and using graphql-tag.macro to compile graphql

@shaneosullivan
Copy link
Author

@eddiemonge a few points about multiple repos:
1 - A small portion of our overall code base should not dictate how we choose to store and share code. We use monorepos for very good reasons, and CRA gets in the way of that. If it forces us to choose between our monorepo and ejecting, we'll eject, but we really don't want to.
2 - Using multiple repos just for CRA apps makes it work differently to every other piece of code we use. It works differently in CI, each new engineer needs to know it's a special case etc. None of this is necessary.
3 - This current limitation is a design choice. It can be removed at any time with minimal to no issues being caused. This decision should be discussed at length by the React team based on feedback from the community. Discussing the various workarounds is not overly helpful - they're all hacks around a limitation that can be removed, thereby removing the need for bad code organization

@stale
Copy link

stale bot commented Nov 25, 2018

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label Nov 25, 2018
@shaneosullivan
Copy link
Author

OK, here's some recent activity. This feature still makes sense and prevents clean usage of more than one CRA project per code repo. Any movement on this?

@stale
Copy link

stale bot commented Jan 18, 2019

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label Jan 18, 2019
@shaneosullivan
Copy link
Author

OK, here's some recent activity. This feature still makes sense and prevents clean usage of more than one CRA project per code repo. Any movement on this?

@stale stale bot removed the stale label Jan 18, 2019
@sezeregrek
Copy link

Any improvements or suggestions in here?

@humancatfood
Copy link

humancatfood commented Feb 21, 2019

@shaneosullivan

This worked for me. Given this structure:

▽ monorepo-folder
  ▽ common-folder
    thing.js
  ▽ create-react-app-folder
    .env
  ▷ other-folder

Add this entry to the create-react-app-folder/.env file

NODE_PATH='./../'

Now you can import common stuff in the cra code:

import Thing from 'common/thing';
import OtherThing from 'other-folder';

It's still a bit of a work-around, but it's the cleanest solution I've managed so far.

@shaneosullivan
Copy link
Author

@humancatfood amazing, that works!! Thanks so much!

@ianqueue
Copy link

ianqueue commented Mar 1, 2019

What about just using npm link? I have an external library that i'd like to actively develop inside the consuming CRA, but I have to restart the app every time to see the changes. Angular CLI has had a flag when running in dev mode for a while... --follow-symlinks

@sezeregrek
Copy link

@humancatfood, @shaneosullivan

How can you convert these outside components to ES5?

@humancatfood
Copy link

@ianqueue I'm sure you can get something more scalable working with npm links, but I never managed to get my head around those and the NODE_PATH solution is good enough for my purposes.

@sezeregrek I don't know.. same as everything else?

@humancatfood
Copy link

humancatfood commented Apr 1, 2019

Hi again @ianqueue & @shaneosullivan,

so I did get my head around this in the meantime (or at least I think I did..)

You don't need to npm link anything at all (nor do you have to feck around with any environment variables): in your cra folder, simply do

npm install <path/to/your/external/module>

This should create an entry in package.json like this:

  "dependencies": {
    "your-external-packages-name": "file:<path/to/your/external/module>",
    // other deps
  }

You can now import it in your cra code:

import bla from 'your-external-packages-name';

If you make changes to your external package it should propagate to the cra app and without you having to reload.

@ghost
Copy link

ghost commented Apr 4, 2019

Does the method described by @humancatfood require that code in the common and other folders be pre-compiled or will CRA compile them with webpack?

@humancatfood
Copy link

Nope, it'll all get compiled together by the CRA.

What I suggested simply lets you import stuff from another location than before, it doesn't change anything about what happens to that stuff after that, ie compiling, babel-ing, etc.

@bjerkins
Copy link

@humancatfood could you provide dummy repository example of your setup ? yarn add path/to/ui-lib for example, where lib is a shared components library and then import Component from 'ui-lib' sure gives me compiler errors

@humancatfood
Copy link

humancatfood commented Apr 12, 2019

@bjerkins

It's not like I don't have an actual job that needs doing, but ok, here you go:

https://github.com/humancatfood/outside-imports

The crucial step is in this commit:

https://github.com/humancatfood/outside-imports/commit/a956f08fdac1b1f86dbc2be0459e333825cac0df

And here it is deployed:

https://humancatfood.github.io/outside-imports/

After playing around with this for a bit longer, I think using npm link is actually better though

@bjerkins
Copy link

@humancatfood right. Thanks for taking the time to show what you meant.

Does the method described by @humancatfood require that code in the common and other folders be pre-compiled or will CRA compile them with webpack?

If you're importing e.g shared React components, then yes. @humancatfood 's example doesn't handle that, unfortunately.

@humancatfood
Copy link

@waynebloss Apologies, I was thinking of minification, etc.

If you want to import .jsx, then yes, you need to precompile it.

Or eject and define your own loaders.

Or write React in standard js of course: https://github.com/humancatfood/outside-imports/commit/9589f66b53fca9c3688376735aa6e561452a4976

@stale
Copy link

stale bot commented May 13, 2019

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

@stale stale bot added the stale label May 13, 2019
@stale
Copy link

stale bot commented May 18, 2019

This issue has been automatically closed because it has not had any recent activity. If you have a question or comment, please open a new issue.

@stale stale bot closed this as completed May 18, 2019
@lock lock bot locked and limited conversation to collaborators May 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

9 participants