create-react-app eslint issue due to higher level folder containing another app with node_modules in it - node.js

I have a git repository which has 2 projects in it, a loopback app (named app), and a react app created with create-react-app (named client).
And the directory structure is as follows;
├─┬app
│ ├──node_modules
│ ├─┬client
├─node_modules
the loopback project (app) uses eslint, has eslint in devDependencies, client does not have eslint in package.json.
Client app is created with create-react-app, so when I run react-scripts, it finds eslint in the upper directory, and complains about its version, if I delete the app\node_modules everything works fine.
So how does react-scripts find the eslint in upper directory, is there a way of telling it not to check any other node_modules folder, it should only check in the current folder.
react-scripts tells me that I can put SKIP_PREFLIGHT_CHECK=true in my .env file, is it safe to do this, does it run the eslint 3.x on the upper level folder, or does it run the required 5.6.0 version installed in client\node_modules folder?
I will setup a deployment toolchain for this project so I need make sure that it works fine all the time.
EDIT:
The config entry in my client\package.json
"eslintConfig": {
"extends": "react-app",
"root": true
},
EDIT2:
Steps to reproduce problems:
my node version is: 8.11.3
npx loopback-cli app (accept default options when prompted)
cd app
npm i
npx create-react-app client
cd client
npm i
npm run start (you should see the errors after this)
EDIT3:
I ended up ejecting react-scripts.

Try creating a .eslintrc file in your client folder, include the following content:
.eslintrc
{
"extends": "react-app"
}
Alternatively, this should work according to the docs:
{
"root": true
}
By default, ESLint will look for configuration files in all parent folders up to the root directory. This can be useful if you want all of your projects to follow a certain convention, but can sometimes lead to unexpected results. To limit ESLint to a specific project, place "root": true inside the eslintConfig field of the package.json file or in the .eslintrc.* file at your project’s root level. ESLint will stop looking in parent folders once it finds a configuration with "root": true.

Related

Build library files into build folder with yarn workspaces and typescript

I created a yarn workspace alongside typescript as such.
I have three folders with their own package.json
/api
/client
/lib
The point is to share code from lib between API and client. In an API file for example I can do
import {User, UserAccount} from '#myproject/lib'
There are problems with this.
I need to build lib each time I change something
/api's build files point to C:/myproject/lib/build/index.js
Since I would like to deploy the project to heroku by just pushing what's in /api/build, this will fail because it can't find the files in /lib/build. Maybe I can push both build folders up to heroku, but what I was hoping for was some magic that compiled all /lib/src files into /api/build. My /client is running in expo which I assume uses something like webpack or I don't know what, and it seems to do this. Do I need to use webpack to acheive this or can I do it with yarn workspaces and typescript?
In tsconfig.json of client and api packages you need two configs, if you don't already have them:
In "compilerOptions" make sure you have "composite": true
Add "references": [{ "path": "relativePathTo/lib" }]
When you run tsc, run it with the --build (-b) flag, like this: tsc -b. This will build the active package and any package in references. More on TypeScript Project References.
This fixes your problem in development. Depending on your project configuration, you may need to do more things to put it through the CI.

run eslint in multi repository project

let's say, I have following project structure:
back/package.json
back/lib/Content/*.js
front/package.json
slices/budget/back/package.json
slices/budget/back/lib/Content/*.js
slices/budget/front/package.json
slices/accounting/back/package.json
slices/accounting/back/lib/Content/*.js
slices/accounting/front/package.json
how do I?
cd back && eslint ./lib/**/*.js ../slices/**/lib/Content/*.js
specifically, I want to
install eslint one time as devDependencies
somewhere in /back of root module
config eslint one time somewhere in /back/package.json:eslint key of root module
add eslint config in /back/package.json of root module just one time
eslint entire tree of modules
not in each slice seperatly
run from ci cd
so I need a way to run from /back
and later - maybe someway to respect eslint config hierarchy
not change project directory structure at all
what I receive
cd back && npm run lint
> back#1.0.0 lint
> eslint ../
Oops! Something went wrong! :(
ESLint: 8.23.1
ESLint couldn't find a configuration file
reason: https://eslint.org/docs/latest/user-guide/configuring/configuration-files#using-configuration-files
You can use the --ignore-path option to specify a file with patterns that should be ignored. The file should contain one pattern per line. For example, to ignore all files in the node_modules directory, you could create a .eslintignore file with the following contents:
node_modules
You can also use the --ignore-pattern option to specify a pattern that should be ignored. For example, to ignore all files in the node_modules directory, you could run:
eslint . --ignore-pattern node_modules
The error is probably because you haven't specified the eslint config file explicitly. To run eslint on all the modules, starting from the parent folder, run: eslint ../ -c .eslintrc.js (or whatever .eslintrc file you use in back). It seems like eslint is confused if it does not have the config file in the same directory it is running from hence you need to manually specify the path to it.
The correct way of solving this issue would be creating sharable config file with configuration you have in back right now:
module.exports = {
rules: {
semi: [2, "always"]
}
};
Then you publish it to public or private npm with a name #your-project/eslint-config and use it in .eslintrc.json that is the same in all your projects:
{
"extends": [
"#your-project/eslint-config"
]
}
This way gives you ability to configure CI in a simple and independent way if you have lots of repositories: just run eslint lib/*.js.
If you have all the repositories in one computer and want to lint all of them using one command, you can use one of my tools:
redfork, install eslint and redfork globally and run:
redfork 'eslint lib/*.js'
But maybe you need to have some changes in project structure.
runny, if you don't want to make changes in project structure, just add configuration file .runny.json:
{
"command": "eslint lib/*.js",
"directories": [
"~/one",
"~/two",
"~/three"
]
}
It will run the same command for any directory you need.
I had a similar issue and the following has solved my problem.
I guess you haven't specified the eslint config file explicitly.
To run eslint on all the modules
run: eslint ../ -c .eslintrc.js
It seems like eslint is confused if it does not have the config file in the same directory it is running from, so you need to manually specify the path to it.
no real answer, except to create .eslintignore, .eslintrc, package.json at project root

Electron builder not copying my dist/node_modules directory in the right place

I've got one node application which I'm already launching with Electron. Now, I want to package it with electron-builder, but I'm dealing with such an strange behaviour. Usually, when I build my application, a dist folder gets generated, containing all the transpiled javascript files and also the package.json. Then, I have to run npm i --production again there to set up my production dependencies. So what I want electron-builder to do is to copy exactly the dist directory as it is once everything is installed:
electron-builder build --linux AppImage
This is my package.json related config:
"main": "dist/app.js",
"build": {
"appId": "my.app",
"files": [
"dist/**/*"
]
},
I guess that with this configuration I'm telling it to copy the dist directory and its contents. The AppImage file gets built and if I unzip it, I can see a resources dir gets created inside, containing one app.asar file. If I extract the asar content, I can see node_modules gets placed at the same level than dist, and not inside of it!! So I have:
AppImage
-- resources
---- app.asar
------ node_modules
------ dist (everything except node_modules)
When I launch the application it obviously complains of not finding the node_modules. The docs say there's some default files pattern which can take precedence of what user has defined...
I also have tried:
"files": {
"from": "dist",
"to": "dist",
"filter": ["**/*"]
}
And seems not being able to find the package.json file.
Somebody asked this similar question years ago, with no answer. Any help please?
Finally I found the way to do it, I had to tweak the configuration with a property that I found in the docs: includeSubNodeModules, which defaults to false and seems to include the node_modules subfolders in the output. Also I had to explicitly omit the root node_modules folder since I don't want it in the output.
"build": {
"appId": "myApplication",
"files": [
"dist/**/*",
"!node_modules"
],
"includeSubNodeModules": true
},

Why "npm run lint" is pointing to .eslintrc in parent folder not current?

cd ~me/olc/componment1/src
there's a .eslintrc.
npm install
node_modules now contains eslint-config-airbnb-base as our .eslintrc extends from airbnb-base.
npm run lint
it failed, saying "was referenced from the config file ~me/olc/.eslintrc".
So how come it's not using the .eslintrc from current folder, but from ../../.eslintrc ?
How to fix this pls ?
By default, ESLint will look for configuration files in all parent folders up to the root directory.
ESLint will stop looking in parent folders once it finds a configuration with "root": true.
https://eslint.org/docs/user-guide/configuring/configuration-files#cascading-and-hierarchy
BTW why ppl are giving negative points instead of helping ? any reason my question is not clear enough ?

Get version number from package.json in React Redux (create-react-app)

OP EDIT: If anyone else comes across this: the app was created using create-react-app, which limits importing to within the src folder. However if you upgrade react-scripts to v1.0.11 it does let you access package.json.
I'm trying to get the version number from package.json in my app.
I've already tried these suggestions, but none of them have worked as I can't access package.json from outside the src folder (might be due to React, I'm new to this). Moving package.json into src then means I can't run npm install, npm version minor, and npm run build from my root folder. I've tried using process.env.npm_package_version but that results in undefined.
I'm using Jenkins, and I haven't set it up to push the commits up yet, but the only idea I have is to get the version from the tags in GitLab, but I have no idea how to do that, and it would add unnecessary dependency to the repo, so I would really like to find an alternative.
EDIT:
My file structure is like:
--> RootAppFolder
|--> build
|--> node_modules
|--> public
|--> src
|--> Components
|--> Root.js
|
|--> package.json
So to access package.json from Root.js I have to do import packageJson from './../../package.json' and then I get the following error:
./src/components/Root.js
Module not found: You attempted to import
./../../package.json 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/.
Solving this without importing and exposing package.json to the create-react-app
Requires: version 1.1.0+ of create-react-app
.env
REACT_APP_VERSION=$npm_package_version
REACT_APP_NAME=$npm_package_name
index.js
console.log(`${process.env.REACT_APP_NAME} ${process.env.REACT_APP_VERSION}`)
Note: the version (and many other npm config params) can be accessed
Note 2: changes to the .env file will be picked only after you restart the development server
From your edit I would suggest to try:
import packageJson from '/package.json';
You could also try to create a symlink:
# From the project root.
cd src; ln -s ../package.json package.alias.json
List contents of src directory and you'll see the symlink.
ls
#=> package.alias.json -> ../package.json
Adding the .alias helps reduce the "magic" for others and your future self when looking at this. Plus, it'll help text editors keep them apart. You'll thank me later. Just make sure you update your JS code to import from ./package.alias.json instead of ./package.json.
Also, please take a look at this question:
The create-react-app imports restriction outside of src directory
Try this.
// in package.json
"version": "1.0.0"
// in index.js
import packageJson from '../package.json';
console.log(packageJson.version); // "1.0.0"
I don't think getting version by 'import' or 'require' package is correct.
You can add a script in you package.json
"start": "REACT_APP_VERSION=$npm_package_version react-app-script start",
You can get it by "process.env.REACT_APP_VERSION" in any js files.
It also works in build scripts, like this:
"build": "REACT_APP_VERSION=$npm_package_version react-app-script build",
import package.json
Generally speaking, importing package.json is not good. Reasons: security & bundle size concerns
Yes, latest webpack (default config) + ES6 import does tree-shaking (i.e. only includes the "version" value instead of the whole package.json) for both import packageJson from '../package.json' and import { version } from '../package.json'. But it is not guaranteed if you use CommonJS (require()), or have altered your webpack config, or use another bundler/transpiler. It's weird to rely on bundler's tree-shaking to hide your sensitive data. If you insist on importing package.json but do not want the whole package.json exposed, you may want to add some post-build checks to ensure other values in package.json are removed.
However the security concern here remains theoretical for open source projects whose package.json is public after all. If both security and bundle size are not problems, or, the non-guaranteed tree-shaking is good enough for you, then go ahead)
.env
The .env method, if it works, then it's good, but if you don't use create-react-app, you might need to install dotenv and do some additional configurations. There's also one small concern: it is not recommended to commit the .env file (here and here), but if you do the .env method, it looks like you will have to commit the file as it likely becomes essential for your program to work.
Best practice (arguably)
(this is not primarily for create-react-app, but you still can either use react-app-rewired or eject cra in order to configure webpack in cra)
If you use webpack, then with DefinePlugin:
plugins: [
new webpack.DefinePlugin({
'process.env.VERSION': JSON.stringify(
process.env.npm_package_version,
),
}),
]
You can now use console.log(process.env.VERSION) in your front-end program (development or production).
(You could simply use VERSION instead of process.env.VERSION, but it usually requires additional configuration to satisfy linters: add globals: {VERSION: 'readonly'} in .eslintrc (doc); add declare var VERSION: string; in .d.ts file for TypeScript)
Although it's "npm_package_version", it works with yarn too. Here's a list of npm's exposed environment variables.
Other bundlers may have similar plugins, for example, #rollup/plugin-replace.
Open your package.json file and change this line
Problem Is:
// in package.json
"scripts": {
"dev": "REACT_APP_VERSION=local REACT_APP_VERSION_NUMBER=$npm_package_version react-scripts start",
...
}
Solution is
// in package.json
"scripts": {
"dev": "react-scripts start",
...
}

Resources