This repo is to help develop monorepo support in create-react-app.
Shared components in monorepos are supported in react-scripts 2.0.0-alpha!
-
See Monorepo Section in User Guide for more info.
-
Follow 2.0.0 roadmap for more alpha release info.
There are two main issues regarding monorepo support in CRA:
- Issue 3031: Can't run create-react-app in workspace
- This issue is mainly just that monorepo tools (yarn/lerna) can hoist react-scripts to a top-level node_modules which breaks some create-react-app code that expects react-scripts to be in app's node_modules.
- This is fixed by PR 3435 (rmhartog's fork).
- Issue 1333: Support Lerna and/or Yarn Workspaces
- This is the issue for actually supporting shared source in monorepos.
- See PR 3741 (merged)
- Monorepo with cra-compatible and non-cra-compatible components
- Cra-comps w/ source not at root (e.g. nwb components)
- Apps that include a cra-comp, but don't want to build it.
- Cra-comps from private registry (instead of monorepo)
- Discourage/prevent cra-comps from being published (non-standard in ecosystem)
- Cra-comps as transitive dependencies (app depends on cra-comp2, cra-comp2 depends on cra-comp1)
monorepo
|--packages.json: workspaces: ["apps/*", "comps/*", "cra-comps/*"] <-- (yarn workspace)
|--lerna.json: packages: ["apps/*", "comps/*", "cra-comps/*"] <-- (lerna w/o yarn workspace)
|--apps
|--cra-app1 <-- basic cra-app, doesn't use any monorepo comps
|--cra-app2 <-- basic cra-app, doesn't use any monorepo comps
|--cra-app3 <-- uses some monorepo comps
|--package.json: dependencies: ["comp1": <vsn>, "comp2": <vsn>]
|--comps
|--comp1 <-- standard shared comp, ok!
|--package.json: main: comp1.js
|--comp1.js
|--comp1.test.js
|--comp2 <-- comp with dependency on another cra-comp, ok!
|--package.json: dependencies: ["comp1"]
|--index.js: import comp1 from 'comp1'
|--index.test.js
|--comp3 <-- comp w/ built output, ok, but will (unnecessarily) transpile
|--package.json: main: build/index.js
|--build/index.js <-- don't transpile?
|--index.js
|--index.test.js <-- don't test?
|--comp4 <-- cra-comp w/ source under /src, not handled (tbd)
|--package.json: dependencies: ["comp1"]
|--src
|--index.js: import comp1 from 'comp1'
|--index.test.js
|--comp5 <-- comp with its own build and test, not handled (tbd)
|--package.json: dependencies: ["comp1"]
|--index.js: import comp1 from 'comp1'
|--index.test.js
- Should tests from cra-comps run when running app tests?
- Should files from cra-comps be linted when building app?
- Should a directory structure be enforced for cra-comps?
- How to flag components that should not be treated as cra-comps? (or should cra-comps be by convention?)
- this monorepo uses lerna w/ yarn workspaces
- this repo currently uses an alpha release of react-scripts
- git clone https://github.com/bradfordlemley/cra-monorepo-examples
- cd cra-monorepo-examples
- yarn
- cd apps/cra-app3 (or any of the apps) and do anything you'd normally do, e.g. yarn start/build/test.
Forking react-scripts in a maintainable way is a challenging endeavor because it is part of a monorepo and it has dependencies on other packages in the monorepo. See monorepo structure in CRA contributing guide.
The first steps are easy:
- Fork create-react-app
- Make changes, usually in packages/react-scripts
Now, how do you use it or test it?....
- Option 1: Point to your forked react-scripts repo
- Unfortunately, you can't just point your app's react-scripts dependency to your forked repo because it is not the react-scripts repo, it is the create-react-app repo.
- React-scripts is inside somewhere, but there's no way to tell npm/yarn where it is.
- Option 2: Link to local clone
- You can npm/yarn link to a local clone of your create-react-app/react-scripts:
- git clone fork ${cra_fork} <-- local clone of create-react-app fork
- cd ${cra_repo}/packages/react-scripts && yarn link <-- register forked react-scripts
- cd ${app} && yarn link react-scripts <-- use forked react-scripts
- But there is a subtle limitation:
- Your fork must be based on the same version of react-scripts that the app lists in its dependencies.
- This is because you need to have all of the same react-scripts dependencies' versions installed.
- Mainly, you run into an issue when your linked react-scripts uses a different jest version than the app's original react-scripts.
- You can npm/yarn link to a local clone of your create-react-app/react-scripts:
- Option 3: Publish your own version of react-scripts
- You can publish your own version of react-scripts, preferably scoping it like @myorg/react-scripts.
- This works well as long as you don't need to change any of the other packages in the create-react-app monorepo -- you just use the packages that are released by the upstream.
- Option 4: Publish your own version of all create-react-app packages
- If you want to have a truly independent fork without the caveats of above solutions
- Publish your own versions of all the packages in create-react-app, preferably scoping all of them like @myorg/pkg.
- For reference, see this commit with scoping change.
- For better or for worse, now you're your own maintainer with full control: 😄 or 😧 ?
- See setting up local copy in CRA contributing for more info on using local cra.
- Unfortunately, there doesn't seem to be an easy way to point your existing app to use the local fork. For may cases, you can link react-scripts (see option 2 above), but with the same caveats. Or, publish it first.
Tests to verify monorepo support (Issue 1333)
- Test cra-app3 in this monorepo
- Install this monorepo as described above
- Open terminal at apps/cra-app3
- Verify npm start/build/test run correctly
Tests to verify "create-react-app" works (Issue 3031)
- "create-react-app" works in workspace
- Open terminal at workspace root.
- /path/to/forked/packages/create-react-app cra-newapp <-- create app
- Update src/App.js and public/index.html to have "New App" in titles
- cd cra-newapp
- yarn start <-- verify app runs in browser with "New App" titles
- yarn build <-- verify build succeeds
- yarn test <-- verify test succeeds
- "create-react-app" works outside of workspace
- Open terminal somewhere outside workspace root.
- /path/to/forked/packages/create-react-app newapp <-- create app
- Verification similar to above
- "npm run create-react-app" works when running from create-react-app dev repo
- Open terminal at root of forked create-react-app repo
- npm run create-react-app newapp <-- create app
- Verification similar to above
- "npm run start/build/test" work when running from create-react-app dev repo
- Open terminal at root of forked create-react-app repo
- npm run start/build/test
- Verification similar to above, ensure template files are used