Note from Maintainers: see https://github.com/facebookincubator/create-react-app/issues/1492#issuecomment-358170489 for the latest thinking on this.
Say I have two sibling CRA apps, Foo
and Bar
. What is the best practice for sharing a common component, Baz
between the two apps?
It would make sense to have a sibling folder Baz
with it's own package.json
, and to use npm link
to access it from Foo
and Bar
.
But it seems that npm link has bigger issues, so maybe we should explore alternatives. One example is wml, which simply watches and copies files.
Even when npm link
works fine, the JSX in Baz
has not been compiled.
Per this discussion, I think we should compile separate modules like Baz
independently, but that will require boilerplate such as babel config. CRA helps avoid this for full apps, but we don't yet have create-react-component
to help manage the boilerplate of shared components.
There are a few ways to clean this up, but I'm curious what people think is the current best practice. What is the ideal developer experience?
Prior art worth considering: insin/nwb, specifically Developing React Components and Libraries with nwb
Ah, I hadn't seen nwb
. It looks like a smooth experience!
Does it make more sense to add integrations and compatibility with nwb new react-component
? Or should we make a create-react-component
that stays in sync with CRA? It could live in the same repo and share configs like babel.
There are a few things that I would have done differently for CRC, in comparison to nwb new react-component
:
I can't stress how much I need this feature. My core problem is I have 3 apps: marketing-site
, 'customer-app', and 'employee-app'. I am keeping them separate to make them as performant as possible, but there are many shared components, for instance the logo.
My current solution has been having a fourth app that gets imported into each, and then using yarn link
, but as mentioned above this is painful, and has issues.
With each layer of separation, my development experience goes down. Having this built into create-react-app
would significantly simplify my life.
What artifacts would such a feature produce? CommonJS, Harmony Modules, UMD, AMD?
Something I've been wanting/thinking about for a while now. There are actually a few levels you can look at this:
There are some pretty complex considerations I think in here. We have a big stack right now with about 25 packages inside it using lerna. But I'd love to release the 8 or so that are more ready for public consumption.
Problem is, I don't want to sacrifice all the niceness of using Lerna now: shared configs, always in sync, can edit them locally easily, automatically linked together.
So, I've just started on repoman which honestly I'm not sure how will solve all this stuff.
My initial idea is to let your packages define a repoScripts
key that points to a github repo, which then has some shared dotfiles/scripts that can be run. Will check into nwb more. If it only handled auto-linking things together + easy standardized/ejectable configurations would be nice.
@izakfilmalter It's not ideal but here's my solution https://github.com/facebookincubator/create-react-app/issues/1084#issuecomment-267725239
Ok, @gaearon, based on your previous comments, it seems that this issue is pretty ripe for fixing.
Please poke this proposal full of holes 😄
We may want to give people more tools like CRA in the future, but it isn't desirable to force people to install a new global dependency for each tool.
Instead, I'd like to propose one tool to rule them all: create-react
:
npm install -g create-react
# This is equivalent to `create-react-app MyApp`
create-react app MyApp
# Now we can support:
create-react component Foo
Behind the scenes, this tool will look up the latest npm package to do the heavy lifting. For example, create-react app
actually is implemented by the react-creator-app
package. The react-creator-component
package would define the behavior of create-react component
.
This opens up more innovation in the space, because a random company could publish react-creator-mycompany-project
, and everybody can easily try out their environment by running create-react mycompany-project
.
Also, this could replace react-native init
, which could become create-react mobile
, create-react native
or something.
One of the new creators would be the 'component' creator, which creates a new React component package.
Like a CRA app, it includes scripts as devDependencies
, and has local commands like npm run build
, which builds using the standard Babel configuration. It would output whatever module standard is expected by standard CRA apps.
One major difference is that npm start
will build the component and watch for changes, rather than launching a server.
At this point, developers could use npm start
alongside linklocal to hack on their components from a neighboring react app.
One huge argument for doing this is to improve tooling for React Native components. Currently, most RN libraries publish uncompiled code, which has become a nightmare when attempting to share libraries or components in other environments that expect node_modules
to be compiled. By introducing a common set of library scripts, we can build a comfortable path forward to compiled modules.
The only bad part about the above experience is the manual usage of linklocal
and the npm start
for each component you may want to hack on.
In the future, the react-scripts
of CRA could be upgraded to automatically run linklocal
, so that changes made in neighboring modules are immediately reflected in the development app.
Then, react-scripts
can detect when an app's linked component is supported by the same scripts, and can automatically run the watch-and-build behavior for each of the compatible components.
So, if I had Foo
and Bar
as independent apps that each depended on a sibling Baz
component, I could run either app and still see the updates as I make changes to Baz
.
Let me ping a few more smart people who have a lot of context on this: @cpojer @thejameskyle @skevy @taion @ljharb
I'm excited to work on this because I've felt this pain a lot- especially when trying to share code between React Native and web/CRA.
Please let me know if you think this makes sense! I'm happy to put together a prototype, if people like this approach.
I'm not sure I understand - isn't the solution to sharing Baz
between two apps, "publish it to npm"? npm link
is fine for developing, but something that works across two apps deserves to be a separate package - if not published publicly, then to an internal npm registry (sinopia is free, for example, and using an npm registry gives you semver benefits that git installs don't).
Can you help me understand what the problem is here that needs solving?
@ljharb, I don't think most people who use CRA know about sinopia. If that is the recommended solution, then we can at least do a better job on education. Lots of people seem to like the lerna approach, and/or linklocal.
Aside from the reported issues about npm link
, it can be a pain to start up a dev server for each package that you want to edit. If you're codebase is nicely decoupled, you usually have a ton of separate modules. Ideally we could get CRA apps to automatically watch and re-build these other modules when they change.
And yes, publishing is another aim. If we have a CRA-like thing for react native components, we can fix that problem you always rightfully complain about: the RN ecosystem is publishing tons of uncompiled modules that is wreaking havoc on people who try to share code between universes. If we encourage them to use our devDependencies and scripts, their published library/component/nativeModule can easily evolve with best practices.
For the rest of the React ecosystem, it may be handy to publish a component without any build configuration.
So I would (personally) summarise the problem domain as the same one as create-react-app, just with respect to painlessly creating a component without any of the build concerns etc as @ericvicenti has stated. Having previously used sinopia (not picking on it) - but its now not even in maintenance mode (last commit was over a year ago) https://github.com/rlidwka/sinopia/issues/376 and it is a solution that adds another cog in the toolchain rather than making it easier to develop imho.
@ericvicenti that approach outlined in the RFC, looks good to me, by the way.
Why not just:
Components
SharedComponent.js
App1
app1.js
package.json (3rd-party app1's dependencies)
App2
app.js
package.json (3rd-party app2's dependencies)
Run the packager from the root (Projects), when bundling it will only include files that are used. E.g. if SharedComponent.js is only imported / required by app2.js, it will only be included in app2's bundle.
If SharedComponent uses a 3rd-party dependency, all apps using ShareComponent should include that dep in their package.json.
@mkonicek, there is no npm start
that is available outside of App1
and App2
, so there is no way to "run the packager from the root". How can developers set that up?
Also, what if App1
is React Native and uses RN packager, while App2
is made with CRA and uses webpack?
@admmasters, yes exactly. My aim is to deliver a good development experience for standalone components, just like CRA delivers a great dev experience for apps.
Also semi-related: #741 #1065
@gaearon, does the src/node_modules
proposal aim to fix the same problem? I'm curious what the DX would look like in that world, as a developer shares a component between two apps.
I like the solution discussed in #741:
A packages/
(node_modules
?) folder inside a repo created by create-react-app
.
I think it's a great approach to co-locate components with the app mostly driving them. In early dev stage, this allows juggling code between app and component as things evolve in a seamless manner - without nasty versioning/publish/download overhead.
When ready, packages can be published by create-react-app
.
If there's only components and no app, just have a wrapper app in /src
and the components in packages
.
No need for a separate create-react-component app in this case.
Remains just the problem of using it in another app. Some node/npm related solutions mentioned above (publish, sinopia, link local, NODE_PATH) could be just fine.
@ericvicenti It's related but it's solving a slightly different problem: avoiding relative imports inside the project rather than sharing components between projects. Since people don't use Haste in open source, they have this issue of ../../../../components/abc
which is often obnoxious. Whatever solution we settle on, I think we should consider both problems since they're similar.
@bebbi, I'm still confused. What would my directory structure look like? I need two independent apps "Foo" and "Bar", which each share a component "Baz". Baz may be an independent repo, but I would like to easily edit it while developing my Foo and Bar apps.
@gaearon, Gotcha, I agree that the problems are related and should be thought about together. I'm spoiled by using Haste at FB. Its not perfect but it means we never worry about this sort of thing.
It's a partial solution for your scenario. But with the assumption that often one project is driving any given components dev, it might still be a nice one.
If Foo's the driver and we call the components folder packages
for now:
cra_Foo
src
packages
Baz
cra_Bar
src
and Bar
accesses Baz
through some less direct way, e.g. via NODE_PATH
or publish etc.
CRA could publish Foo
as an app including Baz
, but there would be a script building Baz
and anything else in packages
as components.
I use git submodules to share components placed in src/Baz
of every app. In this way you can edit Baz
in Foo
, push
it and then just git submodule update
in Bar
.
Ok, it seems that there is enough support to give this a try, so I'm going to implement parts one and two of my proposal as a PR to this repo.
That way we will have create-react component Baz
, which will create a nice experience around developing a component.
I heartily recommend including react-storybook in any component tool: you could have npm start
launch the stories. We created our own create-react-component tool in-house that is basically CRA with a custom template and Babel config that we use to transpile and publish shared components to internal npm (originally Sinopia, now Artifactory) but it's limited. But because it's based on CRA we get all the other useful stuff like Jest, webpack, etc.
I'm a bit late to the party but I think WebPack (and now the React Native packager too) support symlinks?
So with this setup:
/sharedJSComponents
/myWebApp
/myReactNativeApp
Can I just 'npm link' the sharedComponents
into both myWebApp/node_modules
and myReactNativeApp/node_modules
? Then we don't need anything else, right?
@mkonicek, yes but how will you configure the build for those shared components?
Also, npm link
is non-ideal because it clobbers the global installation, in comparison to linklocal
which lets you use relative dependencies and link them in for development.
@ericvicenti since global installations are only for command line binaries, not requireable things, what global installation of a requireable thing (that is thus non-requireable, and thus useless) are you concerned with clobbering?
We're working on something for this as well in a generic way over here if
anyone's interested:
https://github.com/motion/repo-man
On Fri, Feb 10, 2017 at 10:38 AM Jordan Harband notifications@github.com
wrote:
@ericvicenti https://github.com/ericvicenti since global installations
are only for command line binaries, not requireable things, what global
installation of a requireable thing (that is thus non-requireable, and thus
useless) are you concerned with clobbering?—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/facebookincubator/create-react-app/issues/1492#issuecomment-279027952,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAvRGVuIX91IcOCvgltXl5ZKEUZP_Lwks5rbK6cgaJpZM4L42Uw
.
@ljharb, Different projects on your computer could use the same module names, and they collide when linked globally.
@ericvicenti that seems like a naming problem, not a tooling problem :-/ names should be unique.
Yes but we need namespacing tools to avoid duplicate names. Like on my computer, I can have two files with the same name, just not in the same folder. I'm not going to tell people that they have to worry about namespace conflicts across the whole the computer.
IIRC symlinks also confuse watchman (which we rely on through Jest). Not sure if I'm right though.
@gaearon, yeah I think you're right. Pretty sure that is why the RN packager doesn't support symlinks. So I guess that would mostly affect the results of npm test --watch
Symlinks also do not currently play well with packager:
https://github.com/facebook/react-native/issues/637
So I guess that would mostly affect the results of npm test --watch
We default to watch mode so it's essential that it works well.
cc @insin on the off chance that he hasn't seen this issue
I think if I could easily extend paths.appSrc (maybe via package.json
properties?) to point to paths in my monorepo, I could share all the code I need in my lerna-based monorepo and have a happy development experience. At least with yarn start
and yarn build
, not sure how it'd work with tests.
@ericvicenti What’s your thoughts on this? Do you plan to pursue a proof of concept?
Yep, apologies for the lack of communication! I've hacked on this a bit with @skevy, and we have a partial prototype. It is mainly lacking storybook support. I'll get that done within the next day or two and put up a PR.
This is my planning doc for the scope of this new tool: https://gist.github.com/ericvicenti/b69ba80d22aa3f39f3d4cb5606ae8c9f
You can see the progress here:
https://github.com/ericvicenti/create-react-app/tree/master/packages/react-component-scripts
For my use-case, I'm not sure the component scripts would do since my projects are structured differently. Please correct me if I'm wrong though. For instance, I have multiple create-react-app's in my lerna monorepo. I might take a stab at my suggestion if I can get a thumbs up on it from a few others. Otherwise, I'll just eject and hack it. /cc @gaearon
I don't know if it necessarily makes sense to duplicate so much logic/structure and fork into a new react-component-scripts
.
I feel like react-scripts
could serve both purposes, simply introducing new component-build
, component-start
, and component-test
commands.
Can you provide me with a [brief] reason for forking the scripts?
@arnihermann, Im hesitant to add lerna-specific things at this point
@Timer, I was unsure how much code would actually need to be shared, but at this point I tend to agree with you. @gaearon, what do you think about adding the features of react-component-scripts
into react-scripts
?
I don't think it would make sense to have a separate package for this.
If we can agree on how it works, react-scripts
is the place to put this in IMO.
We just need to make sure there is a reasonable story after ejecting (since you'd lose react-scripts
at that point).
When ejecting we could skip irrelevant files -- e.g. app skips and component matches ^component-
tasks.
Ok lets consolidate things to react-scripts
. We could apply a naming convention for ejecting, so that you only get component files when ejecting a component and only get app files when ejecting an app, in addition to the shared files.
@ericvicenti even though I use lerna, my proposed solution doesn't rely on it (I think):
Imagine having a git repo with the following folder structure (somewhat similar to my use case):
admin-app/
create-react-app applicationmobile-web-app/
create-react-app applicationmobile-app/
react-native applicationshared-ui/
react components that can be shared between CRA projectsredux/
reducers and actions that can be shared between CRA and RN projectsMakefile
scripts to collectively run builds and test across projectsThis is sort of what I had in mind. I feel this could be achieved with small changes to CRA and RN. Then admin-app
and mobile-web-app
then depend on shared-ui
and redux
packages and mobile-app
depends on the redux
package. In the case with lerna, the dependency is encoded properly but it doesn't have to be if these packages don't pull in any 3rd party and can be built entirely by the CRA and RN packages.
I'm definitely not sure this is a good way to go, I just wanted to throw it out there.
How would you share a common component between admin-app
and mobile-web-app
? The proposal for CRC would enable create-react-component my-component
. Then, both apps could refer to file:../my-component
. During development, you'd use linklocal
to make sure changes to the component are visible within the app.
@ericvicenti see https://github.com/facebookincubator/create-react-app/issues/1492#issuecomment-283697135 -- by changing include to be an array and support reading additional source paths in the project package.json
.
Do you think this would not work?
I do not think we should be adding any semantics on top of the package.json
standard.
If you can get it to work with local dependencies, I think that would be awesome!
I relate to your feelings about avoiding changing npm-package semantics. The reason I tested this out was because I'm trying to avoid any kind of additional linking step. I feel any kind of solution we come up with will be superseded once npm/yarn comes with a better support for library development without a publishing/linking step.
I'm more than willing to help with any part of this, just let me know how to contribute!
@Timer, awesome, I'm glad you're excited! I gave you commit access to my CRA fork, want do do the honors of rolling react-component-scripts
into react-scripts
? It shouldn't conflict too bad with my roadmap item of adding storybook support.
@ericvicenti if it's okay I'm thinking I want to wait for https://github.com/facebookincubator/create-react-app/pull/1433 to land so that we don't conflict with it; if you want to keep progressing with this, feel free -- I'm more than happy to help once that has landed :)
I have just run into this in setting up a new project, glad to have found this issue - @ericvicenti - thanks for kicking off! Is there any news on progress?
It looks like no answer found in the thread.
I have two repos. First is a UI library (jsx files, not compiled). I need to use this UI library in my second repo - React project. I tried to create symlink, but in this case nom start
doesn't compile UI library and fails. I tried to create symlink to the UI library in the node_modules
- the same result. Only working solution that I have found - copying entire UI library directory to my React project and run npm run
- in this case it works correct, compiling UI library jsx files as expected.
Is it possible to create a symlink to mu UI library directory to work in the same way, as when I copy entire directory with UI library? Because for me it's more convenient to edit file in a first repo and have reflected changes in my second repo (React project) that is running all the time in dev mode.
Thanks.
Any ETA when this will become available and/or pointers on to how to test the in-development script? I'd love to try it out if there's a straightforward way to test on my projects
https://medium.com/@lokhmakov/best-way-to-create-npm-packages-with-create-react-app-b24dd449c354
@lokhmakov thanks for the article. I think the issue is more to do with local parallel development of components and using them without having to publish to NPM. Correct me if I'm wrong.
@pixelstew I think we have only one proper way to share some code between different apps it's - npm packages.
Another way if you are talking about subsystems inside one app and there is no this problem - only place it inside on of ./src/node_modules
and use it everywhere.
If u create symlinks or doing other hacks - it's not reusable and hard to maintain because not standard way.
Any update on this issue?
I've just started using CRA and having the possibility to develop 2 or more apps while being able to re-use node_modules and shared components (and even redux?) would be very welcome.
Is there a 'generic way' to set this up? I've just read these issues and it seems there isn't or am I missing something/a conclusion?
Also, let me express my gratitude for CRA. Regardless of this issue, it's been super handy and informative for my react development.
Hi @MatthiasDebaere!
We're currently hard at work attempting to cut a 0.10 release so we don't have time to evaluate and work on this issue (yet).
It'll most likely be one of our next considerations for the next major version of CRA.
Unfortunately, I don't believe there's any simple workaround to get this working currently ... sorry!
Okay, thanks for the info! Looking forward to the updates :)
@lokhmakov your tutorial worked for me except the component does not receive it's imported css styles in the project, any ideas what would cause this? Thank you for sharing!
@aheci Need to look on code. Feel free to DM me or you can enter https://www.reactiflux.com/ community and ask me in Discord to quickly find solution.
@1st this is the exact situation that I am facing. I have symlinked the UI library in the node_modules, but the transpiling seems to fail. would love to see a solution for this :)
my case:
I have project with component react-lazy-load
and examples/basic
folder inside, which is CRA project. I want to use
"react-lazy-load": "../../../react-lazy-load"
in examples/basic/package.json
. But this doesn't work
UPD: so CRA solution is to use this
cd ../..
yarn link
cd examples/basic
yarn link react-lazy-load
which is not that nice solution in that case
UPD2:
endep up with using symlink ln -s ../../../src/ src/react-lazy-load
+1. Kind of blocked by this issue.
Is there a way to help to push this feature?
Man I hoped there would be a solution by the time I scrolled to the bottom. Boy, did my dreams shatter.
To be clear, I just want to publish packages from create-react-app without the need of reusing webpack configs and other scripts etc.
Well, hope @ericvicenti's PR will help, in the meantime I'll have to copy all my configs =(
Guys, solution is here.
Assume you have 3 React apps:
cd to root directory of GoodComponent
npm link
cd to root directory of FooApp
npm link good-component
cd to root directory of BarApp
npm link good-component
In the code of FooApp or BarApp, if you want to use GoodComponnet, you can just import it as below:
import GoodComponent from 'good-component/src'
Here we go! You can now have your own temporary npm module. You can reuse it just as an npm module without publishing it.
Using npm link
should works.
Check this article: https://medium.com/@BrodaNoel/how-to-create-a-react-component-and-publish-it-in-npm-668ad7d363ce
Forget the part about "and share it in npm", just check how the example works (it's sharing the component using npm link
and npm link component-name
.
@shiyang-fei it's not a solution if you want internal components published to internal repository
@5angel I consider the npm link creates an internal repository on local as a dev solution. If you are really looking for a long term internal respository solution, you can define a git repo url to a dependency like this.
Hope this can help you.
@shiyang-fei not really. When I say internal repo, I mean we have a private npm registry from which we distribute packages to different teams in the company. And doing the whole webpack routing for every little shared component is just tedious.
I only need the publish feature, that's all.
Is there a way to help to push this feature?
Yes, by implementing a proof of concept addressing all the different issues in this thread. It is very unlikely we'll get time to work on this, so it's really up to the community.
We made some progress on repoman a while ago, but haven't touched it in a while. The structure of the project itself though is laid out well for someone wanting to fork.
It's basically a lot of Lerna but instead of per-project, it's per-computer (it controls a folder for you, default is ~/projects
).
So repoman get motion/pundle
would clone into ~/projects/motion/pundle
.
Then you could have a monorepo and run repoman eject ./packages/some-package
and it would move it out and into a parent folder, and symlink it in.
It also has a subset Lerna functionality baked in, so you can have it cross-link and install and such. It needs some love in terms of someone taking care of it, testing it it and probably patching a couple things and focusing it's scope.
What about webpack alias
?
alias: {
'my-local-package': path.resolve( __dirname, '..', '..', 'to', 'local', 'modules', 'MyPackage', 'src' )
}
That work for me. Just and to postcss
(if u use it)
{
loader: 'postcss-loader',
options: {
config: {
path: 'path/to/postcss.config.js'
}
}
}
Also i add package.json and babel config for each local module.
My colleague tried yarn workspaces to share code between projects and he used the following steps:
node_modules
and move it back to packages
, but dev-server compains about building index.He did however tried thess starters (https://github.com/emyann/typescript-webpack-starter, https://github.com/vikpe/react-webpack-typescript-starter) and they work. Does anyone know what could be the cause of this?
For anyone who ends up here an looking for a good React library starting point that uses create-react-app
for an example project, check out react-modern-library-boilerplate.
I just submitted a proposal (https://github.com/facebookincubator/create-react-app/issues/3436) that I think could support the original use case called out in this issue and some others that have come up in this thread.
The proposal is to allow apps to specify additional source roots in package.json.
The app can then import the "shared" modules as absolute imports and they are treated the same as if they were under /src (transpiled, etc.).
monorepo |--app1 |--package.json: srcPaths: ["../shared"] |--src |--file.js: import comp1 from 'comp1' <-- ok, shared/comp1 |--file.js: import comp1 from '../../shared/comp1' <-- fail, not permitted |--app2 |--package.json: srcPaths: ["./components", "../shared"] |--src |--file.js: import comp2 from 'comp2' <-- convenience absolute import, components/comp2 |--file.js: import comp1 from 'comp1' <-- from shared/comp1 |--components |--comp2 |--shared |--comp1
The proposal is implemented, a working monorepo and more info is here: https://github.com/bradfordlemley/cra-share
Update: @arnihermann -- Just realized this basically implements what you had proposed earlier in this thread. Wondering if you have already done it this way and if you've run into any issues doing it this way? I agree with your comments about publishing/linking/building/complication being an issue with some other solutions.
Update2: added convenience absolute import example (in app2 above)
Hi, any updates?
I'll close since so far nobody took ownership of this.
Hi, any updates?
No, if there were any updates, they would be on this issue.
(that said, I think https://github.com/facebookincubator/create-react-app/issues/1333 is still on the roadmap and is sort of related)
I think the most recent thinking on this is:
For the main use case in this thread (sharing components between apps), https://github.com/facebookincubator/create-react-app/issues/1333 is the proposed solution. We even have https://github.com/facebookincubator/create-react-app/pull/3741 as a PR and although we probably won’t go with that specific approach, we’ll probably merge something in that spirit.
If you just need to share a React component you created don’t forget you can just publish it to npm (including a custom registry). I think this thread may give people searching for a solution a wrong impression it’s impossible. People publish React components on npm all the time, and you can use tools like nwb or Neutrino React Component preset to automate the build setup.
Hope this helps!
I just wanted to chime in here, it was pretty easy for me to set up a tiny webpack build, and just leverage the react-scripts setups from inside a fresh create-react app.
babel-preset-react-app
to the top level node modules."build:lib": "NODE_ENV=production ./node_modules/react-scripts/node_modules/.bin/webpack",
Here's the webpack.config.js file.
module.exports = {
entry: { main: "./src/lib" },
output: {
path: __dirname + "/dist",
filename: "[name].js",
libraryTarget: "umd",
library: "<lib name>",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: { loader: "babel-loader" },
},
],
},
externals: { react: "react" },
};
I split my src
folder in to demo
and lib
. Then use the "app" part of create-react-app to run the demo. then src/index.js
just exports the default from the demo directory for the main app.
https://github.com/sorahn/react-fuse
edit: added link to github repo
Most helpful comment
Ok, @gaearon, based on your previous comments, it seems that this issue is pretty ripe for fixing.
RFC of a cohesive solution
Please poke this proposal full of holes 😄
Part I: The new meta Creator
We may want to give people more tools like CRA in the future, but it isn't desirable to force people to install a new global dependency for each tool.
Instead, I'd like to propose one tool to rule them all:
create-react
:Behind the scenes, this tool will look up the latest npm package to do the heavy lifting. For example,
create-react app
actually is implemented by thereact-creator-app
package. Thereact-creator-component
package would define the behavior ofcreate-react component
.This opens up more innovation in the space, because a random company could publish
react-creator-mycompany-project
, and everybody can easily try out their environment by runningcreate-react mycompany-project
.Also, this could replace
react-native init
, which could becomecreate-react mobile
,create-react native
or something.Part II: The Component Dev Setup
One of the new creators would be the 'component' creator, which creates a new React component package.
Like a CRA app, it includes scripts as
devDependencies
, and has local commands likenpm run build
, which builds using the standard Babel configuration. It would output whatever module standard is expected by standard CRA apps.One major difference is that
npm start
will build the component and watch for changes, rather than launching a server.At this point, developers could use
npm start
alongside linklocal to hack on their components from a neighboring react app.One huge argument for doing this is to improve tooling for React Native components. Currently, most RN libraries publish uncompiled code, which has become a nightmare when attempting to share libraries or components in other environments that expect
node_modules
to be compiled. By introducing a common set of library scripts, we can build a comfortable path forward to compiled modules.Part III: Improve experience within an app
The only bad part about the above experience is the manual usage of
linklocal
and thenpm start
for each component you may want to hack on.In the future, the
react-scripts
of CRA could be upgraded to automatically runlinklocal
, so that changes made in neighboring modules are immediately reflected in the development app.Then,
react-scripts
can detect when an app's linked component is supported by the same scripts, and can automatically run the watch-and-build behavior for each of the compatible components.So, if I had
Foo
andBar
as independent apps that each depended on a siblingBaz
component, I could run either app and still see the updates as I make changes toBaz
.Thoughts?
Let me ping a few more smart people who have a lot of context on this: @cpojer @thejameskyle @skevy @taion @ljharb
I'm excited to work on this because I've felt this pain a lot- especially when trying to share code between React Native and web/CRA.
Please let me know if you think this makes sense! I'm happy to put together a prototype, if people like this approach.