Open rovansteen opened 7 years ago
I'm using a create-react-app
created app within a lerna monorepo and am quite pleased with it. Steps:
~/someRepo/packages$ create-react-app app
~/someRepo/packages$ cd ..
~/someRepo$ lerna bootstrap
~/someRepo$ cd packages/app
~/someRepo/packages/app$ npm run start
:tada:
You can require
your other packages by name within the create-react-app after adding them to app
's package.json
and running lerna bootstrap
.
This is pretty nice. Does Babel transpilation still work in this case though?
The individual packages under packages/
need to do a transpilation step. They'll be linked via lerna but the main entrypoints still need to be ES5.
I would prefer to not have to transpile all our packages when used in an overall app and yet I know that when we publish to npm we need them to be ES5-consumable.
For me the holy grail of Lerna support with CRA would look something like,
/web-clients
├── package.json
└── packages
├── api
│ └── package.json
├── components
│ └── package.json
├── cra-app-1
│ └── package.json
├── cra-app-2
│ └── package.json
└── something-else
└── package.json
The idea here is that we have a monorepo for web clients that can contain multiple CRA-based apps as peers that have access to a few shared other packages (e.g. a lib of shared presentational components, maybe a lib with some api calling utils, anything else). The CRA apps should be able to require code from the other packages and Babel should know to transpile such code coming from within the monorepo automatically.
Is this possible with Lerna and CRA at the moment? Any related issues or info I can look at?
While I'm no longer using create-react-app
(using next.js), this is how we do it in nteract for various components and the notebook-preview-demo
(the next.js app): https://github.com/nteract/nteract/tree/master/packages
Yarn added workspaces in 1.0 recently, don't know how it impacts this but thought it might be worth mentioning.
@gaearon I've got babel transpilation working alongside Lerna in a private fork of CRA.
Add something like this to the end of /config/paths
:
module.exports.lernaRoot = path
.resolve(module.exports.appPath, '../')
.endsWith('packages')
? path.resolve(module.exports.appPath, '../../')
: module.exports.appPath
module.exports.appLernaModules = []
module.exports.allLernaModules = fs.readdirSync(
path.join(module.exports.lernaRoot, 'packages')
)
fs.readdirSync(module.exports.appNodeModules).forEach(folderName => {
if (folderName === 'react-scripts') return
const fullName = path.join(module.exports.appNodeModules, folderName)
if (fs.lstatSync(fullName).isSymbolicLink()) {
module.exports.appLernaModules.push(fs.realpathSync(fullName))
}
})
Webpack configs:
// before
{
include: paths.appSrc
}
// after
{
include: paths.appLernaModules.concat(paths.appSrc)
}
Jest config:
// before
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$'],
// after
transformIgnorePatterns: [
// prettier-ignore
'[/\\\\]node_modules[/\\\\](?!' + paths.allLernaModules.join('|') + ').*\\.(js|jsx|mjs)$'
]
Don't have the time to make a PR & add tests, comments, etc. but should be easy for someone else to do
Great!! @ashtonsix . I also have the lerna set up with CRA based on your code.
My folder structure is
lerna
-- packages
-- local package 1 (not published to npm registry)
-- local package 2
-- local package 3
-- local package ...
-- real app (created with CRA)
-- lerna.json
For anyone else, the key for webpack in CRA app to transpile jsx is add lerna packages absolute path in include
of babel-loader
BTW: I have it done without forking CRA, but used a mechanism to extend CRA webpack config, you may find more detail steps in https://github.com/facebookincubator/create-react-app/issues/1328#issuecomment-338447062
I've created an example monorepo and PR 3741 that adds support for it.
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
|--comp3 <-- not a cra component?
|--package.json: main: build/index.js
|--build/index.js <-- don't transpile?
|--index.js
|--index.test.js <-- don't test?
|--cra-comps
|--comp1 <-- standard-ish cra component with JSX
|--package.json: main: comp1.js
|--comp1.js
|--comp1.test.js
|--comp2 <-- cra component with dependency on other cra-comp in monorepo
|--package.json: dependencies: ["comp1"]
|--comp2.js: import comp1 from 'comp1'
|--comp2.test.js
I assume that it is agreed that cra-comps should be transpiled just like app src (including JSX) since that seems to be the request from above comments, but some further questions about desired functionality:
Is this the correct place to try to get the answers for those questions?
Without having tried to setup a monorepo with CRapp I'm having trouble visualising the problems, and thus, the workarounds. Here are some silly questions:
I've tried using the src directory with Lerna, but that conflicts with not ignoring node_modules directory inside the src directory, so it gives a ton of lint errors when you do so.
@rovansteen Is this due to the difficulties in globbing (include/exclude folders) in monorepo directory structure vs a regular package structure?
@bradfordlemley RE: Directory structure - Whats your thinking in enforcing a package folder structure (e.g. apps
and comps
)?
Background: My instinct would be to just keep the root level super thin, and let the user put whatever they want in packages/
// <root>/package.sjon
"scripts": {
"app1:start": "cd packages/app1/; yarn start",
"app1:test": "cd packages/app1/; yarn test",
"styleguide:build": "cd packages/styleguide/; yarn build",
"colors:build": "cd packages/colors/; yarn build",
"test": "lerna exec -- yarn test # Scales poorly!"
}
@AshCoolman PR 3741 is a working implementation of monorepo support in CRA. It doesn't enforce any directory structure. It does support the top-level scripts like you described above. It includes some monorepo usage info in the user guide.
That user guide section describes how monorepos would work for that particular PR approach, and might be a good basis for considering how you want monorepos to work.
It seems like there are a lot of folks who want a solution for shared components, but I'm not seeing much input for details of how they want monorepos to work. I encourage you to provide more input if you can.
@bradfordlemley thanks for very welcome work. I've tried the yarn workspaces described in README for 2.0.0-next.9754a231
.
What seems strange is that when importing a component, comp1/index.js
is indeed picked up but only if there is no comp1/build/index.js
- if the latter exists, it is picked up instead and comp1/index.js
ignored. This changes between runs of yarn start
.
This is a pity as I was hoping to set up a repo where comp1/index.js
just contains a re-export of comp1/src/index.js
, and nwb
is used to build components into comp1/build/index.js
and publish them.
If it's just a matter of search priority, how about switching it around to prefer comp1/index.js
if both are available?
@bebbi This is probably happening because your comp1/package.json has a module or main entry, eg:
"module": "build/index.js"
It is possible to ignore that entry (and perhaps would be reasonable in this case), but it wouldn't pick up the files from /src without some extra sauce, basically because there's not a way for your package.json to specify its source location, so how would we know to get index.js from /src?
BTW, what's the problem with using build/index.js? ... is it that it doesn't automatically get rebuilt when comp1 sources change? something else? Have you tried adding a watcher to rebuild your component? Is that just too painful to coordinate throughout the monorepo?
Happy to try to make this work conveniently for your use case. Can you provide more info on your repo structure/usage/workflow (to avoid any incorrect assumptions about your use case)? Is it just a standard nwb react component that you want to use in a cra app in the same monorepo and also publish?
@bradfordlemley Thanks - yes exactly, the use-case is developing an app in a "single codebase experience" and publish a few modules out of it. Modules are react or plain js.
My biggest need really is for a single, consistent CRA dev experience, ideally without duplicating the dev toolchain (error overlay, settings for lint, babel, webpack loaders, ..) I assume that's what many people are hoping for. I realize that some of this does require duplication as we need to use a non-CRA toolchain to enable lib output, and for many devs this probably means that within above use-case, there will be different behaviours within the same codebase (e.g. wp loaders) unless your wp configs keep pace with cra development.
So I'm mainly trying to understand for which aspects the new workspaces support further reduces that burden of duplication or non-uniform behaviour.
Re src
, agreeing on a src
convention for code is likely overkill for someone just interested in absolute path imports. But my comp/index.js
has a export { default } from './src'
which will do for now.
Yes, I can go with the lib
(or es6
) approach with watching. As cra builds are slow, I assume it'll probably be one line per app e.g. like below:
"start-app1": "concurrently --kill-others \"lerna run start --scope app1 --stream\" \"lerna run build:watch --ignore app1 --ignore app2 --parallel --stream\"
@bradfordlemley
Hm.. running yarn start
in the cra app1
and adding the lines
const a = {hello: 'there' }
const b = { ...a }`
to comp1/index.js
triggers a Syntax error:
Failed to compile ../comp1/index.js
Syntax error: [...]/packages/comp1/index.js: Support for the experimental syntax 'objectRestSpread' isn't currently enabled (2:13)`
[...]
Add @babel/plugin-proposal-object-rest-spread (https://git.io/vb4Ss) to the 'plugins' section of your Babel config to enable transformation.
That doesn't happen when adding it inside the app1/index.js
code.
Oh, this hasn't been released yet, it didn't make it into 2.0.0-next.9754a231 that you mentioned. I believe next alpha (soon?) should have it.
Update: available in react-scripts@2.0.0-next.47d2d941, see https://github.com/facebook/create-react-app/issues/3815#issuecomment-363631534.
I think that it is really dangerous to use different pipelines for testing a component locally and publishing it.
I don’t think we should support using nwb for publishing but compiling with CRA pipeline in development. This doesn’t make sense to me. It will introduce subtle bugs.
My suggestion was that if we see a script called build
in the component’s package.json, we should treat it as a third-party dependency, since presumably you use a different build mechanism. Another field we could use as a heuristic is private
(presumably anything “public” must be compiled before publishing so we shouldn’t attempt that).
I know some people don’t like heuristics like this very much. I’m open to other options.
Not adding much to the future of this conversation, but I just hit this issue. Ended up using https://github.com/dashed/react-app-rewire-babel-loader to add the additional packages in my workspaces that needed the compilation step.
Seems to be working (for now).
Hi, I am currently using CRA (1.x) in a mono-repo with shared components via nwb. Just FYI, maybe its interesting for the discussion and I do not know if this thing (testing in shared components) is mentioned how to do it. I share the tests from react-scripts with the build-process in nwb for my shared packages:
// in package.json
"scripts": {
"build": "nwb build-react-component",
"test": "react-scripts test --env=jsdom"
}
Regarding the different heuristic-approaches: you could also check the "module"
-field. I think this would be bether than checking for a build
-script-entry, but worse than a check for a private
-package.
private
seems to be the cleanest solution, If there is no possibility to explicitly name the packages that have to be considered.
@gaeron of course, very true.
Just a few practical experiences of using workspaces support in a monorepo a couple days. Happy if someone detects a flaw in the approach.
Ceterum censeo a cra module build feature would rock.
(Re heuristics above, "module" sounds like the key most clearly correlated to publishable to me. "build" sounds slightly less clear as CRA has one too, and "private" could be used for other stuff, like avoiding accidental publishing before it's mature.
Has anyone considered the TypeScript case where you can use path mappings to point to packages? Since the packages are not under the apps you get the following error:
Module not found: You attempted to import /Users/agroza/Projects/bbp/sauron/packages/common/src which falls outside of the project src/ directory. Relative imports outside of src/ are not supported. You can either move it inside src/, or add a symlink to it from project's node_modules/.
What would be the solution for this case?
Can you give an example? This looks like you're just trying to import from outside src (which is not supported), nothing to do with typescript.
@bradfordlemley yes, of course. See cra-workspaces, it's the same example that also causes problems with jest (and a few other problems).
@rolandjitsu I think this yarn workspace support in react-scripts should support that use case (when it presumably gets ported into react-scripts-ts), without using tsconfig.json paths. Your monorepo is roughly:
monorepo/
app/
src/
App.js: import packageA from 'package-a'
packages/
package-a/
package-b/
which is basically the same as examples discussed above.
There are still some details being discussed, like if/how to support src dirs under the shared packages, if shared packages should be publishable, how to detect shared packages that should not be built. Note, it doesn't allow package names to be remapped. Also, you can take a look at this cra-monorepo-examples which is trying to present the issues and open questions. It'd be great if you could comment here to help ensure it will meet your use case.
If you really want tsconfig.json paths support, probably best to follow up on the react-scripts-ts paths issue.
What is the current status of this ? Is there a simple solution for transpiling imported code in a simple use case:
project
| ----- lerna.json
| ----- package.json
| ----- packages
|-------- myapp (built using create-react-app myapp)
|-------- shared (built using create-react-app shared)
myapp
has shared dependecy and import a component (FormItemTitle
) from shared
:
> react-scripts start
Starting the development server...
Failed to compile.
../shared/src/atoms/FormItemTitle/FormItemTitle.js
Module parse failed: Unexpected token (27:18)
You may need an appropriate loader to handle this file type.
|
| class FormItemTitle extends Component {
| static propTypes = {
| title: PropTypes.string.isRequired
| };
How to solve the transpilation issues here?
@renatonmendes It is supported in 2.0 alpha, see https://github.com/facebook/create-react-app/issues/3815 for install info. It only supports yarn workspaces (you should have "workspaces" in project/package.json).
If you have both of those and it's still not working, can you write back and add the contents of project/package.json, myapp/package.json, and shared/package.json, and also the import statement you're using in myapp?
well, I´ve managed to make it work according to the @ashtonix code from [above](Module build failed: Error: No ESLint configuration found.), with some changes:
$ create-react-app myapp
$ cd myapp
$ npm run eject
Then in config/paths.js
:
module.exports.lernaRoot = path
.resolve(resolveApp('.'), '../')
.endsWith('packages')
? path.resolve(resolveApp('.'), '../../')
: resolveApp('.')
module.exports.appLernaModules = []
module.exports.allLernaModules = fs.readdirSync(
path.join(module.exports.lernaRoot, 'packages')
)
fs.readdirSync(module.exports.appNodeModules).forEach(folderName => {
if (folderName === 'react-scripts') return
const fullName = path.join(module.exports.appNodeModules, folderName)
if (fs.lstatSync(fullName).isSymbolicLink()) {
module.exports.appLernaModules.push(fs.realpathSync(fullName))
}
})
For some reason the latest create-react-app does not export an appSrc
, so this was changed to resolveApp('.')
Then same as original post:
At Webpack configs (config/webpack.config.dev.js
, config/webpack.config.prod.js
)
// before
{
include: paths.appSrc
}
// after
{
include: paths.appLernaModules.concat(paths.appSrc)
}
Jest config:
And in project´s package.json
in section "jest"
:
// before
transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$'],
// after
transformIgnorePatterns: [
// prettier-ignore
'[/\\\\]node_modules[/\\\\](?!' + paths.allLernaModules.join('|') + ').*\\.(js|jsx|mjs)$'
]
All fine, I got the code transpiled, but now I´m facing problems with EsLint when including the shared component:
$ npm run myapp
Starting the development server...
Failed to compile.
../shared/src/FormItemTitle/FormItemTitle.js
Module build failed: Error: No ESLint configuration found.
Any ideas of what is still missing ?
@bradfordlemley , should I install workspaces
where ? In the shared
project, in the myapp
project that uses shared
or in lerna package.json ?
BTW: I´m using Windows and npm. I´ve never used yarn, so will that work on my environment ?
Have a look at 2.0 User Guide's monorepo section, it shows an example of a workspaces entry in the top-level package.json, as well as the rest of the tree. (I just noticed that it incorrectly shows [] instead of {} for dependencies and devDependencies, should use {})
Thanks @bradfordlemley for hints. After a lot of pain, I could make my Lerna workspace to work:
$ lerna init
package.json
{
"workspaces": ["*"],
"private": true,
"devDependencies": {
"lerna": "^2.9.0"
}
}
lerna.json
{
"lerna": "2.9.0",
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
"packages/*"
],
"version": "0.0.0"
}
My packages:
Auth package (packages/auth):
{
"name": "@myorganization/auth",
"version": "3.0.0",
"author": "Myself",
"license": "UNLICENSED",
"dependencies": {
"@myorganization/ux": ">=3.0.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "2.0.0-next.47d2d941"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
UX package (packages/ux):
{
"name": "@myorganization/ux",
"version": "3.0.0",
"author": "Myself",
"license": "UNLICENSED",
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "2.0.0-next.47d2d941"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Boostrapped:
$ lerna bootstrap --hoist
I can run the ux library fine.
$ cd ux
$ yarn start
But when I´m trying to run my project that has the dependency, I got the following error:
$ cd auth
$ yarn start
yarn run v1.5.1
$ react-scripts start
Failed to compile.
../ux/src/atoms/ActivityItem/ActivityItem.js
Syntax error: D:\project\packages\ux\src\atoms\ActivityItem\ActivityItem.js: Support for the experimental syntax 'classProperties' isn't currently enabled (34:20):
32 | class ActivityItem extends Component {
33 |
> 34 | static propTypes = {
| ^
35 | showHeader: PropTypes.bool,
36 | timestamp: PropTypes.number,
37 | username: PropTypes.string,
Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
This ActivityItem
is from imported code:
import ActivityItem from '@myorganization/ux/src/atoms/ActivityItem/ActivityItem'
Seens that babel configuration is not being loaded correctly on imported module, as the plugin is installet at lerna root node_modules
folder.
Should I create a .babelrc for each project in the monorepo? Will react-scripts start
correctly configure babel for all projects, including the imported one?
Not sure if I´m doing something wrong or if this is an issue... Ways to solve that ?
EDIT:
I'm experiencing the same behaviour in cra-mongorepo-examples project. Check here
I'm frustrated. After 3 days still in same point - cannot import a component to create-react-app
....
After not being successfull, I´ve tried to eject again the project in order to solve that on scripts.
As I´m now using monorepo, my current setup is:
project
|-------- node_modules
|-------- lerna.json
|-------- package.json
|-------- packages
|----------- auth
|------- node_modules
|------- src
|------- packages.json
|----------- ux
|------- node_modules
|------- src
|------- packages.json
lerna.json:
{
"lerna": "2.9.0",
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
"packages/*"
],
"version": "3.0.0"
}
Lerna root package.json:
{
"name": "myorganization",
"version": "3.0.0",
"license": "UNLICENSED",
"workspaces": ["packages/*"],
"private": true,
"scripts": {
"clean": "lerna clean -f --yes && rm -rf node_modules",
"reset": "yarn run clean && yarn",
"auth": "cd packages/auth && yarn start"
},
"devDependencies": {
"lerna": "^2.9.0"
}
}
ux package.json: (ux was not ejected)
{
"name": "@myorganization/ux",
"version": "3.0.0",
"author": "Me",
"private": true,
"license": "UNLICENSED",
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "2.0.0-next.9754a231"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"browserslist": {
"development": [
"last 2 chrome versions",
"last 2 firefox versions",
"last 2 edge versions"
],
"production": [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 11"
]
},
"devDependencies": {
"eslint": "^4.19.0",
"eslint-plugin-react": "^7.7.0"
}
}
auth package.json:
{
"name": "@myorganization/auth",
"version": "3.0.0",
"private": true,
"author": "Me",
"license": "UNLICENSED",
"dependencies": {
"@myorganization/ux": "^3.0.0",
"@babel/core": "7.0.0-beta.38",
"@babel/runtime": "7.0.0-beta.38",
"autoprefixer": "7.2.5",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "8.2.1",
"babel-jest": "22.1.0",
"babel-loader": "8.0.0-beta.0",
"babel-preset-react-app": "4.0.0-next.9754a231",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "2.3.0",
"css-loader": "0.28.9",
"dotenv": "4.0.0",
"dotenv-expand": "4.0.1",
"eslint-config-react-app": "3.0.0-next.9754a231",
"eslint-loader": "1.9.0",
"eslint-plugin-flowtype": "2.41.0",
"eslint-plugin-import": "2.8.0",
"eslint-plugin-jsx-a11y": "6.0.3",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.6",
"fs-extra": "5.0.0",
"html-webpack-plugin": "2.30.1",
"identity-obj-proxy": "3.0.0",
"jest": "22.1.2",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.10",
"promise": "8.0.1",
"raf": "3.4.0",
"react": "^16.2.0",
"react-dev-utils": "6.0.0-next.9754a231",
"react-dom": "^16.2.0",
"react-router-dom": "^4.2.2",
"style-loader": "0.19.1",
"svgr": "1.6.0",
"sw-precache-webpack-plugin": "0.11.4",
"thread-loader": "1.1.2",
"uglifyjs-webpack-plugin": "1.1.6",
"url-loader": "0.6.2",
"webpack": "3.10.0",
"webpack-dev-server": "2.11.0",
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"
},
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom"
},
"browserslist": {
"development": [
"last 2 chrome versions",
"last 2 firefox versions",
"last 2 edge versions"
],
"production": [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 11"
]
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
],
"setupFiles": [
"<rootDir>/config/polyfills.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
],
"testEnvironment": "node",
"testURL": "http://localhost",
"transform": {
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"'[/\\\\]node_modules[/\\\\](?!' + paths.allLernaModules.join('|') + ').*\\.(js|jsx|mjs)$'",
"^.+\\.module\\.css$"
],
"moduleNameMapper": {
"^react-native$": "react-native-web",
"^.+\\.module\\.css$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"web.js",
"mjs",
"js",
"json",
"web.jsx",
"jsx",
"node"
]
},
"babel": {
"presets": [
"react-app"
]
},
"eslintConfig": {
"extends": "react-app"
},
"devDependencies": {
"eslint": "^4.19.0",
"eslint-plugin-react": "^7.7.0"
}
}
Then I´ve changed the config/paths
to grab the referenced packages, adding the following code at the end of it:
module.exports.lernaRoot = path
.resolve(resolveApp("."), "../")
.endsWith("packages")
? path.resolve(resolveApp("."), "../../")
: resolveApp(".");
module.exports.appLernaModules = [];
module.exports.appLernaNodeModules = path.join(
module.exports.lernaRoot,
"node_modules"
);
fs.readdirSync(module.exports.appLernaNodeModules).forEach(folderName => {
if (folderName === "react-scripts") return;
if (folderName.substr(0, 1) === ".") return;
let fullName = path.join(module.exports.appLernaNodeModules, folderName);
if (folderName.substr(0, 1) === "@" && fs.lstatSync(fullName).isDirectory()) {
fs.readdirSync(fullName).forEach(subFolderName => {
let subFullName = path.join(fullName, subFolderName);
if (fs.lstatSync(subFullName).isSymbolicLink()) {
let src = fs.realpathSync(subFullName);
module.exports.appLernaModules.push(src);
}
});
}
if (fs.lstatSync(fullName).isSymbolicLink()) {
module.exports.appLernaModules.push(fs.realpathSync(fullName));
}
});
And changed the webpack.config.dev and webpack.config.prod to:
"use strict";
const autoprefixer = require("autoprefixer");
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin");
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin");
const WatchMissingNodeModulesPlugin = require("react-dev-utils/WatchMissingNodeModulesPlugin");
const eslintFormatter = require("react-dev-utils/eslintFormatter");
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
const getClientEnvironment = require("./env");
const paths = require("./paths");
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
const publicPath = "/";
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz.
const publicUrl = "";
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
const postCSSLoaderOptions = {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: "postcss",
plugins: () => [
require("postcss-flexbugs-fixes"),
autoprefixer({
flexbox: "no-2009"
})
]
};
console.log(paths.appLernaModules.concat(paths.appSrc));
// This is the development configuration.
// It is focused on developer experience and fast rebuilds.
// The production configuration is different and lives in a separate file.
module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
devtool: "cheap-module-source-map",
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
entry: [
// We ship a few polyfills by default:
require.resolve("./polyfills"),
// Include an alternative client for WebpackDevServer. A client's job is to
// connect to WebpackDevServer by a socket and get notified about changes.
// When you save a file, the client will either apply hot updates (in case
// of CSS changes), or refresh the page (in case of JS changes). When you
// make a syntax error, this client will display a syntax error overlay.
// Note: instead of the default WebpackDevServer client, we use a custom one
// to bring better experience for Create React App users. You can replace
// the line below with these two lines if you prefer the stock client:
// require.resolve('webpack-dev-server/client') + '?/',
// require.resolve('webpack/hot/dev-server'),
require.resolve("react-dev-utils/webpackHotDevClient"),
// Finally, this is your app's code:
paths.appIndexJs
// We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh.
],
output: {
// Add /* filename */ comments to generated require()s in the output.
pathinfo: true,
// This does not produce a real file. It's just the virtual path that is
// served by WebpackDevServer in development. This is the JS bundle
// containing code from all our entry points, and the Webpack runtime.
filename: "static/js/bundle.js",
// There are also additional JS chunk files if you use code splitting.
chunkFilename: "static/js/[name].chunk.js",
// This is the URL that app is served from. We use "/" in development.
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebookincubator/create-react-app/issues/253
modules: ["node_modules", paths.appNodeModules].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
"react-native": "react-native-web"
},
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson])
]
},
module: {
strictExportPresence: true,
rules: [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|jsx|mjs)$/,
enforce: "pre",
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve("eslint")
},
loader: require.resolve("eslint-loader")
}
],
include: paths.appLernaModules.concat(paths.appSrc)
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve("url-loader"),
options: {
limit: 10000,
name: "static/media/[name].[hash:8].[ext]"
}
},
// Process application JS with Babel.
// The preset includes JSX, Flow, and some ESnext features.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appLernaModules.concat(paths.appSrc),
use: [
// This loader parallelizes code compilation, it is optional but
// improves compile time on larger projects
require.resolve("thread-loader"),
{
loader: require.resolve("babel-loader"),
options: {
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
highlightCode: true
}
}
]
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
{
test: /\.js$/,
use: [
// This loader parallelizes code compilation, it is optional but
// improves compile time on larger projects
require.resolve("thread-loader"),
{
loader: require.resolve("babel-loader"),
options: {
babelrc: false,
compact: false,
presets: [
require.resolve("babel-preset-react-app/dependencies")
],
cacheDirectory: true,
highlightCode: true
}
}
]
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: [
require.resolve("style-loader"),
{
loader: require.resolve("css-loader"),
options: {
importLoaders: 1
}
},
{
loader: require.resolve("postcss-loader"),
options: postCSSLoaderOptions
}
]
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: /\.module\.css$/,
use: [
require.resolve("style-loader"),
{
loader: require.resolve("css-loader"),
options: {
importLoaders: 1,
modules: true,
localIdentName: "[path]__[name]___[local]"
}
},
{
loader: require.resolve("postcss-loader"),
options: postCSSLoaderOptions
}
]
},
// Allows you to use two kinds of imports for SVG:
// import logoUrl from './logo.svg'; gives you the URL.
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
{
test: /\.svg$/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
cacheDirectory: true
}
},
require.resolve("svgr/webpack"),
{
loader: require.resolve("file-loader"),
options: {
name: "static/media/[name].[hash:8].[ext]"
}
}
]
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve("file-loader"),
options: {
name: "static/media/[name].[hash:8].[ext]"
}
}
]
}
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
]
},
plugins: [
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In development, this will be an empty string.
new InterpolateHtmlPlugin(env.raw),
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml
}),
// Add module names to factory functions so they appear in browser profiler.
new webpack.NamedModulesPlugin(),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only):
new webpack.HotModuleReplacementPlugin(),
// Watcher doesn't work well if you mistype casing in a path so we use
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebookincubator/create-react-app/issues/240
new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart.
// See https://github.com/facebookincubator/create-react-app/issues/186
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty"
},
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
performance: {
hints: false
}
};
Running, I´m getting the following result:
$ npm start
> @myorganization/auth@3.0.0 start D:\project\packages\auth
> node scripts/start.js
[ 'D:\\project\\packages\\auth',
'D:\\project\\packages\\ux',
'D:\\project\\packages\\auth\\src' ]
Starting the development server...
Failed to compile.
../ux/src/atoms/index.js
Module build failed: Error: No ESLint configuration found.
Commenting the eslint step in webpack.config.dev, I´m getting:
$ npm start
> @myorganization/auth@3.0.0 start D:\project\packages\auth
> node scripts/start.js
[ 'D:\\project\\packages\\auth',
'D:\\project\\packages\\ux',
'D:\\project\\packages\\auth\\src' ]
Starting the development server...
Failed to compile.
../ux/src/atoms/ActivityItem/ActivityItem.js
Syntax error: D:\project\packages\ux\src\atoms\ActivityItem\ActivityItem.js: Support for the experimental syntax 'classProperties' isn't currently enabled (34:20):
32 | class ActivityItem extends Component {
33 |
> 34 | static propTypes = {
| ^
35 | showHeader: PropTypes.bool,
36 | timestamp: PropTypes.number,
37 | username: PropTypes.string,
Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
So, same problem. Not eslinting or transpiling imported code. Stuck in same place for some days and lots of work dependent on this.
Help very much appreciated to get out of this loop.
Well, after a succession of attempts and frustrations I got it working!!
The solution came from [this webpack forum issue].(https://github.com/webpack/webpack/issues/6799#issuecomment-374523938)
Basically what is happening is that, for some reason, the babel configuration in the package.json is not working, so a slight change on webpack.config.dev.js
is necessary on the babel section (haven´t evaluated webpack.config.prod.js
yet):
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
presets: [
"react-app"
]
In my case I had to delete the babel section of the package.json
also to make it work.
Of course you need also to point to new foders, like @ashtonsix posted up in the thread.
So @bradfordlemley, this sounds like something that could be changed in original CRA scripts to avoid this problem. What about this change ?
@renatonmendes , it looks like you were using an older alpha (react-scripts@2.0.0-next.9754a231) which did not have this support. (FTR, I believe you were using that older version because the newer alpha 2.0.0-next.47d2d941 recently became broken due an external dependency update, see https://github.com/facebook/create-react-app/issues/3815#issuecomment-373834505.)
A new alpha, react-scripts@2.0.0-next.b2fd8db8, was just published.
Could you give that a try?
I am not sure if this has been discussed somewhere else but nothing was mentionned in the docs. When creating a new app with create-react-app newapp
, it directly installs all the node_modules. If same node modules where already installed on the root node_modules folder of the monorepo, they still get installed locally.
Would it be possible to just create files/folders with something like create-react-app newapp --no-install
then manually install with lerna bootstrap --hoist
to mutualise duplicate modules between apps?
Besides developping in a Vagrant VM on windows, I symlink node_modules to somewhere else, so they don't pollute my host, but with create-react-app I have no control.
If I initially create the newapp/node_modules folder symlinked to somewhere else, when creating the app with create-react-app newapp
I get:
The directory newapp contains files that could conflict:
node_modules
Either try using a new directory name, or remove the files listed above.
@trompx
If same node modules where already installed on the root node_modules folder of the monorepo, they still get installed locally
By "installed locally", I'm assuming you mean in the app's node_modules.
If you're using lerna w/ yarn workspaces, this should work with #3967, which should be in an upcoming CRA 2.0 release (also requires yarn >= 1.5.0). Yarn w/ workspaces automatically hoists to the top-level node_modules. (Without #3967, react-scripts will still get hoisted, but create-react-app will fail because it can't find the hoisted react-scripts.) I believe this will work even if your top-level node_modules is symlink'd elsewhere, but not sure.
It sounds like you're using lerna w/ npm, tho. I think something likelerna bootstrap --hoist
after create-react-app
would get lerna to hoist the modules that npm installed. I don't think create-react-app --no-install
would quite work because create-react-app needs to install react-scripts first, then invokes react-scripts to create the app skeleton. Probably would be good to create a separate ticket for supporting lerna monorepos w/ npm to try to get that use case totally supported.
In either of these cases, you shouldn't hit any issue with "The directory newapp contains files that could conflict" safety check since those tools don't symlink the app's node_modules.
If you need to symlink the app's node_modules for some reason, it seems that you're working outside the standard monorepo workflow and tools, and you probably need some special features (like ignoring the safety check) to make it work and you should request those special features in a separate ticket.
Hey @bradfordlemley, thanks for the detailed answer.
By "installed locally", I'm assuming you mean in the app's node_modules.
Yes exactly.
I have all my devtools in a docker container. When working on a project, I mount the src folder inside the devtools container so I can use a bunch of tools on multiple projects, without polluting the host (in that case the Vagrant VM) with the npm/yarn/create-react-app etc. So in the devtools container, I have both yarn and npm. Some projects need yarn, some others need npm.
When you say:
It sounds like you're using lerna w/ npm
I don't really understand. Most of the time, I install my dependencies with yarn but with create-react-app, I don't have control of what is used to install the packages. I admit I'm a bit lost with lerna, which first used yarn it seems then migrated over npm5 (don't remember exactly which version made the switch).
So from what you're saying, with the 2.0 release, calling create-react-app app
will automatically hoist to the top level node_modules? Will it detects automatically that the root folder is a monorepo due, either to the presence of workspaces in the package.json or the lerna.json file, or no matter what cra will always create the app/node_modules then we'll have to manually run lerna bootstrap --hoist
?
Anyway, even if it automatically hoist to the top-level, what happens if the root package.json declares a package (installed by create-react-app) but with a different version (so other components, not cra apps, don't have to install it). In that case Lerna is supposed to install the version locally (in the app/node_modules), and I would have the same problem.
Windows has always had a bunch of problems with node modules long paths, so I ended up mounting my files in a Vagrant VM (then symlinked all node_modules folder outside of the mounted folders). I don't see another way to handle a monorepo on windows unfortunately, and am considering more and more switching to a linux distro.
@bradfordlemley I'm having some issues attempting to set this up. I'm not certain that I'm approaching this correctly. I've tried this multiple times, clearing the npm and yarn caches in between.
First, I created my root project directory, set up a package.json with workspaces: [ 'exercises/*' ]
in it. I created the exercises directory, and tried to execute npx create-react-app@next --scripts-version=2.0.0-next.66cc7a90 conduit
with the following result:
Aborting installation.
Unexpected error. Please report it as a bug:
{ Error: Cannot find module '/Users/nloding/code/talks/real-world-react/exercises/conduit/node_modules/react-scripts/package.json'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:571:15)
at Function.Module._load (internal/modules/cjs/loader.js:497:25)
at Module.require (internal/modules/cjs/loader.js:626:17)
at require (internal/modules/cjs/helpers.js:20:18)
at checkNodeVersion (/Users/nloding/.npm/_npx/13539/lib/node_modules/create-react-app/createReactApp.js:526:23)
at getPackageName.then.then.then.packageName (/Users/nloding/.npm/_npx/13539/lib/node_modules/create-react-app/createReactApp.js:331:7)
at process._tickCallback (internal/process/next_tick.js:68:7) code: 'MODULE_NOT_FOUND' }
I get the same if I leave out the scripts and just do npx create-react-app@next conduit
, and I even get that error with just npx create-react-app conduit
. If I go to a directory outside my monorepo, all three of those commands work without error. The node_modules directory does appear to be getting hoisted correctly, as I see all those packages in the monorepo/node_modules directory, including react-scripts.
I'm not using lerna, I was looking to just use yarn workspaces. What is the correct approach to adding a CRA app to a monorepo?
(edit: spelling errors)
I've also tried adding "nohoist": ["**/react-scripts", "**/react-scripts/**"]
to the root project.json, a workaround suggested in #3031, but that resulted in the same error.
Scratch that, I had the syntax in my package.json wrong. If I add nohoist
as above, it does work. It would appear almost as if the PR in that thread isn't in the react-scripts alpha. Let me know if it's better to file this as a separate issue.
@nloding #3967 fixes #3031, but it hasn't been merged. The issue is that you can't run create-react-app
inside a monorepo to create an app; however, apps already created will work, ie. react-scripts
works fine inside a monorepo. You can either create the app outside of the monorepo and copy it in, or use --nohoist like you mentioned to work-around the problem. I'll ping the maintainers to try to get #3967 merged.
@bradfordlemley Deleted my last two comments, as they both proved to be my fault, nothing related to this. However, I did find a genuine bug - I swear, a real bug this time! - and created a separate issue for it. I am not sure if it is related to this PR or not. You can view it here:
Hi. Got a question regarding running tests in a monorepo.
First issue - CRA is complaining about incompatible Jest versions. I have 23.3.0
in the root node_modules
folder (which is a dependency of 2 other apps in the monorepo), but CRA depends on 22.4.3
. I thought that Yarn will take care of it and put the correct version in node_modules
of the CRA app... Fortunately, I can skip this check using SKIP_PREFLIGHT_CHECK=true
, but it doesn't really explain if it's just skipping this check for incompatible Jest versions or if I'm disabling some other important checks as well.
Second issue - it looks like running yarn test
inside CRA app runs tests for all *.js
files in the monorepo :/ Is there any way to prevent CRA from doing it?
I'm using create-react-app
and react-scripts
v2.0.0-next.3e165448.
I thought that Yarn will take care of it and put the correct version in node_modules of the CRA app
Yarn will figure it out and the correct version of jest will be somewhere, e.g. {monoroot}/node_modules/react-scripts/node_modules/jest
, but the location depends on your monorepo. CRA's preflight check will flag issues and bail out, even though the installation is correct and will probably work. However, module resolution does get complicated in these situations and it's difficult to verify, so I think that preflight check bailing is the correct behavior. The best solution is probably to nohoist these tools in your workspace config, e.g. "nohoist": ["**/react-scripts", "**/jest"]
. That should prevent the tools from getting hoisted and allow the CRA preflight check to do its job properly.
yarn test inside CRA app runs tests for all *.js files in the monorepo
yarn test myapp mycomp
or in your app's package.json test script itself.I'm having plenty of issues with dependencies when testing and building other packages and apps in my monorepo after adding create-react-app@next
(I even tried adding whole packages/apps to nohoist rule with nohoist: [<pacakge>/**]
, but it didn't really help), so I guess I'll just give up and create this new app in a separate repo...
@szimek just making sure, you have the latest alpha release of react-scripts
also?
@nloding Yes.
We got a bit messy monorepo - we've got an SPA app (webpack 4, preact, babel 6, old postcss), Gatsby app (webpack 1, react 15, babel 6, super old postcss) and node app (webpack 3, react 15, babel 6, sass). I have no idea how it all works at the moment, because if I try to update any of the "core" dependencies (babel, postcss etc), one of the apps always breaks. Adding create-react-app
to it, which uses webpack 4, react 16 and babel 7 is just too much for it ;) Same thing happened when I tried to update Gatsby app to v2, which also uses webpack 4, react 16 and babel 7 and latest postcss - Gatsby app worked fine, but one of the other app got broken :/ It's a bit hard to update anything at the moment :)
@szimek: I've had similar issues initially but managed to work with this in the root package.json
"nohoist": [ "**/babel**", "**/eslint**", "**/jest**", "**/webpack**" ]
you may consider hoisting **/@babel**
as well for babel 7.
I vaguely remember trying nohoist: [<pacakge>/**]
but like you said it didn't help much, but the above config worked for me.
@bugzpodder Thanks! I'll try it out, though it feels really hacky and prone to break in the future. In my case I'd have to add postcss to this list as well... It's just frustrating that updating a dependency in one project, suddenly breaks another one, because I have to not only test each app, but also build each app after every update to make sure they can be deployed and if a build fails, guess what needs to be added to the nohoist
list.
BTW. I asked about it in another issue (https://github.com/yarnpkg/yarn/issues/6088), but do you know what are the possible options for nohoist
setting? What does e.g. **/babel**
do exactly? Does it prevent all dependencies which name starts with babel
in all workspaces from being hoisted? What about their dependencies - are they not hoisted as well, or would I have to add **/babel**/**
?
I think **/babel**
will cover dependencies of dependencies. ** would match aribitrarily deep directory structures, so this would match any path that contains "/babel"
I agree a lot of this is undesirable. Hopefully @babel 7 will be released this year and everyone would migrate to that. :)
With "nohoist": ["**/babel**"]
I'm getting an error while building one of my apps (Gatsby):
Error: Entry module not found: Error: Cannot resolve module 'babel' in /Users/.../repo/apps/blog
because webpack
is looking for babel-loader
in ./apps/blog/node_modules
and ./node_modules
, but it's in ./apps/blog/node_modules/gatsby/node_modules
:sob: It never ends...
I'm not really sure if these issues with dependencies in yarn workspaces are caused by some bugs in yarn, inconsistent versioning of (peer) dependencies or it's just the way dependency resolution works.
Anyway, this ticket is about create-react-app
and not the nohoist
setting, so I'll stop complaining about it ;)
Are there any plans to support Lerna? By default Lerna uses the
packages
directory to store the packages. Right now the content of that folder is not transpiled so it's not possible to use ES6 code in there. It would be nice to have the possibility to use Lerna to create a monorepo application with create-react-app.I've tried using the
src
directory with Lerna, but that conflicts with not ignoringnode_modules
directory inside thesrc
directory, so it gives a ton of lint errors when you do so.