Skip to content

feat: react-scripts lint command #1217 - #3850

Closed
maciej-ka wants to merge 1 commit into
react:nextfrom
maciej-ka:react-scripts-lint-command
Closed

feat: react-scripts lint command #1217#3850
maciej-ka wants to merge 1 commit into
react:nextfrom
maciej-ka:react-scripts-lint-command

Conversation

@maciej-ka

@maciej-kamaciej-ka commented Jan 18, 2018

Copy link
Copy Markdown
Contributor

Adds lint command to react-scripts.

Typical use will be to:

  1. add to package.json scripts:
 "scripts": {
...,
"lint": "react-scripts lint"
}

EDIT: PR provides a default configuration for ESlinter, so these are no longer needed:
2. yarn lint --init
3. yarn to install new dependencies
4. yarn lint to use

Script passes all options to eslint, so this will work yarn lint --fix. Files checked are: .js, .jsx and .mjs in src folder. This includes test files too.

@gaearongaearon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn’t work after eject.

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

That's on purpose to drive away from ejecting.
Thank you for checking. I'll try to solve this problem today.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from a9c3973 to 6fe704bCompareJanuary 18, 2018 18:35
@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

Fixed and tested. Should work after ejecting now.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from 6fe704b to 4c89a1fCompareJanuary 18, 2018 18:44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it need a separate case, and not using the same logic as above?

@maciej-kamaciej-kaJan 19, 2018

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure is node spawn needed in this case. But now I see. This way script feels no difference between being called with react-script command and after eject with node scripts/command.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for? I don't understand.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A part of eslint --init wizard is to install dependencies using npm i. Since we have yarn, this will make a small mess. This line of code is to inform, that after react-scripts lint project has to be rebuilt with rm node_modules && yarn and possibly rm package-lock.json.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this info after losing some time figuring out why all commands don't work anymore after react-scripts lint.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from 4c89a1f to 27d65f9CompareJanuary 19, 2018 00:00
@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

Lint case unified with rest of commands in bin/react-scripts.js.
Small instruction after running lint --init wizard stayed. Maybe let's remove it after eslint --init gets new option --use-yarn?

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

@gaearon should project that was built by create-react-app come with default eslinter configuration? This is a suggested approach by ESLinter team.

At the moment we don't provide such a file and users will probably need to make a copy of rules from other project or create a new eslinter config with react-scripts lint --init wizard.

@gaearon

Copy link
Copy Markdown
Contributor

I don’t think we want to add any wizard here.

By default it should use the lint config that’s already used by default by commands like npm start. Specifically, eslint-config-react-app.

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

Thanks. I'll look for a way to integrate them into react-script lint.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from 27d65f9 to 583132eCompareJanuary 20, 2018 11:10
@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

Added a default ESlint configuration, removed warning about --init.

@gaearongaearon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below; we'll also need integration tests for this.

For example you could use some existing integration test in the tasks/ folder and verify that running ./node_modules/.bin/react-scripts lint before ejecting and node scripts/lint.js after ejecting doesn't break.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After ejecting we already put eslint config into the package.json (as far as I remember).
Why is this necessary?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to know ... now ... after few days of working on it (madman laugh: iiihahahaha).

@maciej-kamaciej-kaJan 21, 2018

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was added to run linter before ejecting.
Do you know how is it possible to have same effect but without such a file?

Side note: ESlinter can be run programmicaly:

constCLIEngine=require("eslint").CLIEngine;constcli=newCLIEngine({configFile: require.resolve('../config/eslint.json'),fix: process.argv.slice(2).indexOf('--fix')>=0});constreport=cli.executeOnFiles(["src/**/*.{js,jsx,mjs}"]);CLIEngine.outputFixes(report);constformatter=cli.getFormatter();console.log(formatter(report.results));

But it still seems it needs a config file. In supported options it is possible to pass rules, but not extends. And, sadly, running above snippet after ejecting doesn't work, because eslint cannot find jsx-a11y definitions, even with this line added: plugins: ['import', 'flowtype', 'jsx-a11y', 'react']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can baseConfig argument help?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it works
baseConfig: { extends: "react-app" },

however, after ejecting linter now reports

/private/tmp/demo-15/src/App.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo-15/src/App.test.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo-15/src/index.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo-15/src/registerServiceWorker.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
✖ 4 problems (0 errors, 4 warnings)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding plugins: ['jxs-a11y'] throws `Error: Failed to load plugin jxs-a11y: Cannot find module 'eslint-plugin-jxs-a11y' (after yarn eject)

And trying these options didn't help

 cwd: '/tmp/demo-15',
rulePaths: [
path.dirname(require.resolve('eslint-plugin-jsx-a11y')) + '/rules'
],

I wonder, why having baseConfig: { extends: "react-app" } in scripts/lint.js would be better than an explicit config file in the config directory? Both of these duplicate entry in package.json.

@viankakrisnaviankakrisnaJan 23, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this line can just be

require.resolve('eslint-config-react-app')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after eject it needs to be

require.resolve(paths.appPackageJson),

though

@viankakrisnaviankakrisnaJan 23, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we can do it by playing around with eject comments 😅

// @remove-on-eject-begin/** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */// @remove-on-eject-end"use strict";constspawn=require("react-dev-utils/crossSpawn");constargs=process.argv.slice(2);// @remove-on-eject-begin/**// @remove-on-eject-endconst paths = require("../config/paths");// @remove-on-eject-begin*/// @remove-on-eject-endconstresult=spawn.sync("node",[require.resolve("eslint/bin/eslint")].concat(["src/**/*.{js,jsx,mjs}","--config",// @remove-on-eject-begin/** // @remove-on-eject-end require.resolve(paths.appPackageJson), // @remove-on-eject-begin */// @remove-on-eject-end// @remove-on-eject-beginrequire.resolve("eslint-config-react-app")// @remove-on-eject-end]).concat(args),{stdio: "inherit"});process.exit(result.status);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or just

// @remove-on-eject-begin/** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */// @remove-on-eject-end"use strict";constspawn=require("react-dev-utils/crossSpawn");constargs=process.argv.slice(2);constresult=spawn.sync("node",[require.resolve("eslint/bin/eslint")].concat(["src/**/*.{js,jsx,mjs}",// @remove-on-eject-begin"--config",require.resolve("eslint-config-react-app")// @remove-on-eject-end]).concat(args),{stdio: "inherit"});process.exit(result.status);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much! Suggestion to userequire.resolve('eslint-config-react-app') as a config path is a gold.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch 2 times, most recently from 7dc0f55 to 9998ca2CompareJanuary 23, 2018 21:09

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcoding this won't respect the changes that user made in package.json or .eslintrc post eject. IMO we should wrap this line:

// @remove-on-eject-beginconfigFile: require.resolve('eslint-config-react-app'),// @remove-on-eject-end

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes ... but then react-scripts lint after eject has few errors:

/private/tmp/demo20/src/App.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo20/src/App.test.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo20/src/index.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
/private/tmp/demo20/src/registerServiceWorker.js
1:1 warning Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
✖ 4 problems (0 errors, 4 warnings)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, do you have eslint installed globally / .eslintrc file somewhere in the parent folder? i think we need to add root: true to eslintConfig property in package.json post eject. https://eslint.org/docs/user-guide/configuring#using-configuration-files can you try adding it and see if it fix the problem?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, no change after:

 "eslintConfig": {
"root": true,
"extends": "react-app"
}

@maciej-kamaciej-kaJan 23, 2018

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also adding plugins: ['jsx-a11y'] to CLIEngine constructor options doesn't remove errors.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe running it with DEBUG=eslint:* yarn lint would help you found the problem. I cannot reproduce it locally using the same code :(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or DEBUG=eslint:config* yarn lint if you just want the log related to config

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch 5 times, most recently from a28a0f8 to 7a5ab30CompareJanuary 24, 2018 08:44
@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

E2E tests added, removed eslint config file. Huge thanks and ❤️ to @viankakrisna

@viankakrisna

viankakrisna commented Jan 24, 2018

Copy link
Copy Markdown
Contributor

happy to help! so do you find what is the cause on the issue that you have on your machine? how do we avoid ejected users have the same issue as you?

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

I haven't found the reason why this version of react-scripts lint is breaking, after eject, on my local dev. I had ESLint installed globally but it didn't help when I removed it. I hope to find some time to debug ESLint internals.

@viankakrisna

Copy link
Copy Markdown
Contributor

what's the output of DEBUG=eslint:config* yarn lint ?

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

Ha, it works now. Even when I install ESLinter globally.
Maybe it was some silly mistake from my side yesterday (like using a wrong version of react-scripts).

@sbdchd

Copy link
Copy Markdown

Might be a good idea to trigger process.exit(1); if there are errors, since the eslint CLIEngine won't do it itself.

@maciej-ka

Copy link
Copy Markdown
ContributorAuthor

That would allow chaining yarn lint && .... Let's add it. I will return process.exit(1) if there was any linting error (but not a warning). Thanks for the idea!

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch 2 times, most recently from 2529a76 to 67a774dCompareJanuary 30, 2018 21:21

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condition to trigger exit(1) could be different when a --fix flag was used.

Report object has a count of fixable errors and it is possible to count how many unfixed errors are left:

{'...': '...',errorCount: 1,fixableErrorCount: 1,}

My concern is that in react-scripts lint --fix && git push files will be changed by lint but they still need git commit.

@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from 67a774d to 7543ab4CompareJanuary 30, 2018 22:04
@maciej-ka
maciej-kaforce-pushed the react-scripts-lint-command branch from 7543ab4 to aec1ba1CompareJanuary 30, 2018 22:11
@uLan08

Copy link
Copy Markdown

Any updates on this?

@TimerTimer closed this Sep 26, 2018
@TimerTimer reopened this Sep 26, 2018
@SirBif

Copy link
Copy Markdown

I'm trying to understand what's missing to close this PR. I was checking if I could help, but I have the impression this is just a rebase away from being ready.

  • the e2e tests requested by @gaearon are there
  • there is a merge conflict (which I believe is what's causing appveyor CI to fail)

Did I get that right @maciej-ka ?

@RoseyRosey mentioned this pull request Oct 5, 2018
@gaearongaearon closed this Nov 1, 2018
@kfei

kfei commented Jan 8, 2019

Copy link
Copy Markdown

Is this PR rejected?

@locklockBot locked and limited conversation to collaborators Jan 13, 2019
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@maciej-ka@gaearon@viankakrisna@sbdchd@uLan08@SirBif@kfei@Timer@facebook-github-bot