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

Proposal for sharing source between apps #3436

Closed
bradfordlemley opened this issue Nov 10, 2017 · 7 comments
Closed

Proposal for sharing source between apps #3436

bradfordlemley opened this issue Nov 10, 2017 · 7 comments

Comments

@bradfordlemley
Copy link
Contributor

This proposal is to support a simple and generic way to share code between create-react-app apps.
It can support monorepos and arbitrary source directory layout (e.g. for cleaning up relative import paths).

Example:

monorepo
  |--cra-app1
     |--package.json: srcPaths: [“../shared”]
     |--src
       |--file1.js: import comp1 from ‘comp1’ ← ok, shared/comp1
       |--file2.js: import comp1 from ‘../../shared/comp1’  ← naughty, fails
  |--cra-app2
     |--package.json: srcPaths: [“../shared”, "./packages"]
     |--src
       |--file1.js: import comp1 from ‘comp1’ ← ok, shared/comp1
       |--file2.js: import comp3 from ‘comp3’ ← ok, packages/comp3
     |--packages
       |--comp3
  |--shared
    |--comp1
    |--comp2

Proposal:

  • srcPaths are specified in package.json.
  • Modules found in srcPaths are treated essentially the same as /src modules.
    ** transpiled using same cra config
    ** do not have their own package.json, do not specify own dependencies, .babelrc, etc.
    ** all tests in modules are included when running app tests
  • Modules in a srcPath are imported between /src or another srcPath using absolute import paths.
  • Keep us sane?...don't allow overlapping srcPaths

The implementation to support this has a smallish footprint:

More info on this proposal including a working monorepo is here:
https://github.com/bradfordlemley/cra-share

I think the best part of this proposal is that it puts a lot of flexibility and power within the grasp of a novice developer. I think it works approximately how a novice developer would expect shared source to work. ...but...what are the issues with this proposal that I'm not seeing?

@rmhartog
Copy link

What do you see as the major differences between your proposal and something like Yarn Workspaces (https://yarnpkg.com/blog/2017/08/02/introducing-workspaces/)? I think it will become a more 'conventional' approach to javascript monorepo's and offers enough flexibility for novice developers to be productive with.

@bradfordlemley
Copy link
Contributor Author

bradfordlemley commented Nov 10, 2017

@rmhartog
Longer-term, the js community will surely come up with a generic way to manage source package dependencies, but it doesn’t seem to have arrived yet.

Yarn workspaces is a step in that direction, but I think if you try to do this with yarn workspaces, you’ll find it’s not (yet) ideal for this use case. In my opinion, the root of the problem is that npm packages don’t carry the necessary metainfo to be used as source packages...they are intended as buildable libraries. Package.json could carry that extra metainfo, and I think it probably will in the future. But, that’s just my theory on yarn workspaces, I haven’t put time into proving it out, maybe you or someone else can add more info or disprove my theory.

On the other hand, I think this srcPaths proposal provides an instant developer-friendly experience for create-react-app users -- basically, everything works the same as your standard /src, just from a different spot. The major drawback is probably that it doesn’t support dependencies of included srcPaths -- it totally punts to the top-level includer to have all of the dependencies of the srcPaths that in includes. I convinced myself to be ok with this because: (1) that’s the same as any other sources under /src, (2) if the included thing has a lot of dependencies, maybe it does belong in its own package, and (3) dependency management is hard. Dependency management would be (is?) a major win for using yarn workspaces.

@raycohen
Copy link

Would there be a way to have versioned dependencies managed through package.json with this approach? Say for example you have two CRA projects in separate repos, and a one-way dependency, could you publish one to npm, add it to package.json from the other and consume it from a srcPath inside node_modules?

@bradfordlemley
Copy link
Contributor Author

@raycohen I don't think that will work because the build won't be able to pick up cra2's dependencies (from cra1/node_modules/cra2/node_modules). (If cra1 contained cra2's dependencies, I think it would work, but I don't think that's what you were asking.)

@tlvince
Copy link

tlvince commented Nov 20, 2017

@bradfordlemley, thanks for kicking this off. I've successfully given it a try, but have a few questions:

Given the following project structure (a Lerna monorepo):

packages
├── parent-app
├── component-1
└── component-2

All packages are bootstrapped with Create React App and parent-app's package.json contains:

"srcPaths": [
  "../component-1/src",
  "../component-2/src"
]
  1. If both component-1 and component-2 contain e.g. a User component, can they both be imported in parent-app? I would assume one would take precedence over the other and so we'd need a way to namespace imports, maybe:
"srcPaths": {
  "component1": "../component-1/src",
  "component2": "../component-2/src"
}
  1. When using separate repos (not a monorepo), can we include node_modules without transpiling? It appears something like the following is unsupported (due to Enable babel-preset-env for node_modules that target newer Node versions #1125):
"srcPaths": {
  "node_modules/component-1/src"
}

@bradfordlemley
Copy link
Contributor Author

@tlvince

  1. You could achieve that w/ srcPaths=[".."], then import User1 from 'component-1/src/User'. Or you could add another dir under component-x/src, e.g. component-1/src/comp1/User, then import User1 from 'comp1/User'. The namespace/aliasing suggestion could make the import a bit prettier without adding the extra dir (import User1 from 'component1/User'), but I think it would complicate the dev experience, e.g. to debug that import, you'd normally look for a component1 directory somewhere, but it wouldn't exist.
  2. This should work, but I haven't tried it. (Files from "node_modules/component-1/src" would be transpiled -- I think that's what you were asking.) The catch is that component-1's dependencies would not be available, so, e.g. if component-1 needs moment.js, moment would have to be included in the top-level app's dependencies. (some other comments in this thread also discuss this dependencies issue.)

@Timer
Copy link
Contributor

Timer commented Dec 8, 2017

Closing as dupe of #1492. Please add new proposals there.

@Timer Timer closed this as completed Dec 8, 2017
@lock lock bot locked and limited conversation to collaborators Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants