Project structure with lerna and multiple react instances - javascript

I have a problem with project structure with lerna. Below is my project tree:
- project
-- node_modules //lerna root
-- lib //server
--- node_modules
--- package.json
--- tsconfig.json
-- app //web
--- node_modules
--- package.json
--- tsconfig.json
-- packages //lerna
--- ui-components
---- node_modules
---- package.json
---- tsconfig.json
-- package.json //lerna root
Right now in ui-components package.json I have installed react/react-dom deps, but this deps are installed in lerna root node_modules. Because of that when I use this package inside app (web) my compiler throw me this error:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app <-- THIS
This error is because I have two react instances, first is in lerna root node_modules and second is in app node_modules ...
What I do, I add peerDependecies to package.json in ui-components:
"peerDependencies": {
"react": "17.0.2",
"react-dom": "17.0.2"
}
And it work... for a while, to using yarn in ui-components and app.
And now I have a problem? Can someone tell me how can i fix this problem? Maybe I should change the structure of the whole project?
Thanks for any help!

Related

SCSS not working within a REACT app specifically

I'm pretty sure its my folders filepath for my compile Sass script, but I've been at this one a few hours now, so I'm hoping you can help... (maybe there's a setup setting IDK about?...
Two similar projects - 1 Vanilla, 1 React.
1. On both I have node, NPM and node-sass installed; via: npm i --save-dev node-sass
2. I've got livesass compiler going. On vanilla it works as expected. On the React project live-sass-compiler keeps on crashing (it is working long enough for me to test it though) and when i run in the terminal: npm run compile:sass the terminal turns into a node, never compiles, and also seems to get stuck in this state.
Please help!
NOW FOR THE DIFFERENCES:
==========Filepaths==========
(Filepath is indicated by "./", multiple files indicated by array syntax.
Vanilla (root):
index.html (stylesheet href="./STYLES/SCSS/index.css")
index.js
./STYLES/ [index.css, index.css.map, index.scss]
package.json (script: "compile:sass": "node-sass STYLES/SCSS/index.scss STYLES/output.css -w")
Works great!
REACT (root):
./public/index.html (stylesheet href="../src/STYLES/CSS/index.css")
./src/index.js
.src/STYLES/ [index.scss, (desired css output)]
package.json (script: "compile:sass": "node-sass src/STYLES/index.scss src/STYLES/CSS/index.css -w")
in both of them, inside the node-modules folder, I have installed:
"devDependencies": {"node-sass": "^7.0.1"}
Hey, I figured it out! - I got rid of live-sass-compiler (it's depreciated). - I also removed the "script: "compile:sass": "node-s..."" as it's no longer required. Compilation will happen natively every time you save the file.
TO USE WITH REACT:
Terminal:
npm install -D sass
sass —watch scss:css
1. add an .env file to the root. Inside type: “SASS_PATH=src/STYLES/SCSS”
(this allowed relative paths to be ignored on previous versions. I haven't gotten this to work but everything else seems to work. It may be depreciated... IDK.)
2. include the filepath import to the JS page you’d like the CSS to live under:
(example (for APP-WIDE Changes): index.js: import './STYLES/index.scss’ //imports to the app component
3. to import another file from index.scss:
Within the index.scss file:
#use './SCSS/_unorganized.scss'; // ("#import" will soon be depreciated, instead use #use)
Hope this saves someone else some time!

How to organize npm scripts and several webpack configs?

I have several dashboards in project and I decided to make separate scripts in package.json for each(in development it's not very useful to build all dashboards when you work only with one. It takes more time).
First I found that via script is possible to launch concrete webpack config.So it will look like:
"scripts": {
"dash1": "export NODE_ENV=development && webpack --config=webpack.dash1.config.js -d --watch --display-error-details export name=employee ",
"dash2": "export NODE_ENV=production && webpack --config=webpack.dash2.config.js --progress",
"dash3": "export NODE_ENV=development && webpack --config=webpack.dash3.config.js -d --watch --display-error-details",
}
In this case I will need to have 3 separate webpack config-files, where I'll specify proper entry files. But Is it possible somehow to pass the parameter in npm script and to check it in webpack config? Maybe it's possible to perform conditional check for entries according to trnasmitted from npm-script param?
Webpack config files are just javascript - so anything goes. In your case you could
use environment variables
https://webpack.js.org/guides/environment-variables/
NODE_ENV=development DASHBOARD=dash1 webpack --config=webpack.config.js
(p.s. you do not need export blah &&)
use a base config and a configuration for each dashboard which extends this configuration
config
├── base.config.js
├── dash1.config.js // extends base.config.js
└── dash2.config.js
and use a tool like https://github.com/survivejs/webpack-merge to help with merging the base configuration.

What is the right way to create separate npm modules and use them locally

I created a React Native component which lives in a different folder with its own package.json file, and I want to use it in another project
MyComponent is located in Workspace/MyComponent and as a few dependencies in package.json
"dependencies": {
"react-navigation": "^1.0.0-beta.11"
},
"peerDependencies": {
"react": "16.0.0-alpha.12",
"react-native": "0.45.1"
},
"devDependencies": {
"react": "16.0.0-alpha.12",
"react-native": "0.45.1"
}
I am currently in the development of MyComponent so I have run npm install in the repo, there is a node_modules folder.
My have linked MyComponent with MyApp which is located in Workspace/MyApp, using npm link
Although, when I run MyApp and try to use MyComponent, it complains about duplicated declaration, because react is in both MyComponent and MyApp, and they are linked.
If I remove the node_modules folder from MyComponent, react-navigation complains about react not defined.
In the ReactJS world, webpack for example allow to set the root with the preferred node_modules folder which is great.
module.exports = {
...
resolve: {
root: path.resolve(__dirname, 'node_modules'),
}
...
}
I wish to do something similar so I don't have duplicated modules and can debug MyComponent in MyApp locally without reinstalling MyComponent for every single change. What is the best approach for me to achieve this?
Thanks
I found a solution to my question, and it's called whackage
https://github.com/FormidableLabs/whackage
If this is something that will eventually be put in its own repo and then will be installed like any other component, I would probably just build it in the node_modules directory of the parent project. That would prevent you from having to run npm install for every little change.
You can also declare a dependency on a local file and then npm will install it in node_modules
"dependencies": {
"my-component": "file:app/components/my-component",
}
So I have a component that I've built within my project that is referenced in my package.json file. When I run npm install this component is installed in the node_modules folder. That could help with the duplicate library declarations but it wouldn't solve the repeated use of npm install
Update: I just learned that npm 5 doesn't copy the files over to the node_modules folder. It now creates a symlink (basically, a virtual directory that points to the real one) to the code in your project.
This means you will not have to run npm install each time you change your code so it will likely be the best solution for you.

Using webpack and babel with files from parent project directory

I have a project set up like this and I'm trying to require file-a.js from file-b.js.
project-name/
node_modules/
src/
file-a.js
tools/
tool-name/
node_modules/
src/
file-b.js
webpack.config.js
package.json
package.json
My webpack 1.13.0 configuration was working until I added babel-loader 6.2.4 with babel-preset-es2015 6.6.0. Then I started getting error messages.
ERROR in /home/dan/dev/dan/project-name/src/file-a.js
Module build failed: Error: Couldn't find preset "es2015" relative to directory "/home/dan/dev/dan/project-name/src"
Now I have a hunch that this is happening because it's looking for babel-preset-es2015 in the upper package.json. I can make this error go away by installing it at that level, but then I get a similar message about the babel module not being there.
I've tried all sorts of things, symlinked the upper src directory into the inner project, used resolve.root and resolve.alias to try and manually resolve the folder without the nested path. Used context to set the project root as the outer folder, but it still picked up the wrong node_modules.
How can I force webpack to use the correct node_modules folder?
By default webpack looks in ./node_modules, ../node_modules, and ../../node_modules.
To force it to only use a specific directory, you can set an absolute path for the module modulesDirectories property in the resolve section:
module.exports = {
// ...
resolve: {
modulesDirectories: [path.join(__dirname, 'node_modules')]
}
}
More details on moduleDirectories in webpack's documentation

How do I exclude the "require('react')" from my Browserified bundle?

I'm using Browserify to bundle a ReactJS application.
All my components include a require("react") at the top. This causes Browserify to include the ReactJS source in my bundle. But I'd like to exclude it.
How do I do that? Is this the right thing to do?
#NickTomlin gave this answer, but then deleted it.
You can use external:
browserify --external react src.js > dest.js
An example using the api:
var bundler = browserify('src.js');
bundler.external('react');
bundler.bundle();
This is a viable option. external requires another script to provide the module in a compatible way. You can produce such a script like this:
browserify -r react > react.js
env NODE_ENV=production browserify -r react | uglifyjs -m > react.min.js
And in HTML:
<script src="react.js"></script>
<script src="dest.js"></script>
dest.js is your code except react. react.js is just react and its dependencies.
Need more things external? Just add them in addition to react.
browserify -x react -x react-bootstrap src.js > dest.js
browserify -r react -r react-bootstrap > vendor.js
You could also do something like this in package.json
"browser": {"react": "./react-fake.js"}
// ./react-fake.js
try {
module.exports = require('react');
} catch(e){
module.exports = window.React;
}
And compile with -x react. This allows you to accept a -r react build, and fallback to a global React.
Sounds like you want to use browserify-shim.
In your package.json
"browserify-shim": {
"react": "global:React"
},
"browserify": {
"transform": [ "browserify-shim" ]
},
"dependencies": {
"browserify-shim": "~3.2.0"
}
(untested). This section has more information.
I also wanted to do this, and found a possible solution.
From the browserify -h help:
--ignore, -i Replace a file with an empty stub. Files can be globs.
Just use the ignore feature.
browserify -i react -i react-dom ...
I also added react and react-dom as peer dependencies, cause in my case, the package can be imported in other packages builds.
You can also use the externals section in the webpack.config.js file. eg:-
externals: {
// require('jquery') is loaded externally and avaliable as jQuery
"jquery": "jQuery"
}
See https://webpack.github.io/docs/library-and-externals.html

Categories