question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: 'configurator' field in package.json

See original GitHub issue

tl;dr

Add a field to package.json that tells ESLint, Flow, other tools, where to look for configs. Useful for zero-conf opinionated packages like create-react-app and standard.

  // ESLint will look for react-scripts/config/.eslintrc
  // Flow will look for react-scripts/config/.flowconfig
  "configurator": "react-scripts"

As a community, we’ve mostly solved the problem of nested, extendable configuration. ESLint does this really well, Babel also does this.

However, I think that this project gaining 4k stars in 4 days proves that there is a market for non-configurable opinionated tools hiding dependencies from the user. I’d like to give props to standard for being one of the first tools demonstrating this is a viable model (it doesn’t matter whether I agree with its choices).

The problem I‘m starting to see is that many amazing tools, like ESLint and Flow, don’t currently play very well with this approach out of the box.

Problem

ESLint

ESLint is very flexible but if you want IDE integration, you need to tell it where your config is. This is why our otherwise zeroconf package.json now has to look like this:

{
  "name": "my-app",
  "version": "0.0.1",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.1.0"
  },
  "dependencies": {
    "react": "^15.2.1",
    "react-dom": "^15.2.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "./node_modules/react-scripts/config/eslint.js" // 😁
  }
}

Yes, one extra field is not a high price, but it is already a bit frustrating that we have to hardcode ESLint there. We would like to treat it as an implementation detail, to the extent that it is reasonable. (e.g. eslint-ignore comments are fine, but putting paths to configs into user’s package.json is annoying)

Also, it doesn’t even solve the problem completely because ESLint will look for plugins relative to the project root, so any transitive plugin dependencies won’t be discovered with npm 2 (or in some cases, admittedly not likely with our tool, with npm 3). You can find the discussion about this in eslint/eslint#3458.

Flow

Flow poses a similar problem for us, although in a more unfortunate way. We can’t even tell Flow to look at a different config. When you run flow init, it creates .flowconfig in the project root, and that’s it. This is reasonable if the user plans to change it (which seems necessary for lib integrations), but we can’t even influence the default generated config in any way. And unfortunately, for a number of reasons, the default generated config won’t work for create-react-app.

If you want Flow to work, you need to replace the config generated by flow init with this one:

[libs]
./node_modules/fbjs/flow/lib

[options]
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable

module.name_mapper='^\(.*\)\.css$' -> 'react-scripts/config/flow/css'
module.name_mapper='^\(.*\)\.\(jpg\|png\|gif\|eot\|svg\|ttf\|woff\|woff2\|mp4\|webm\)$' -> 'react-scripts/config/flow/file'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe

And we don’t want to do this automatically because:

  • Many people don’t currently use Flow.
  • Our philosophy is to not generate a ton of configs in the user folder.
  • We want the config to be compatible with the current version of react-scripts, so if we generate Flow config before the person actually starts using Flow, by the time they start using it, their checks might fail because something changed on our side.

Solution?

I don’t know if there is a nice solution to this, but here is my proposal. This is how I want package.json to look:

{
  "name": "my-app",
  "version": "0.0.1",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.1.0"
  },
  "dependencies": {
    "react": "^15.2.1",
    "react-dom": "^15.2.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "eject": "react-scripts eject"
  },
  "configurator": "react-scripts" // 😀
}

ESLint would then use react-scripts/config as the base directory for its regular config/plugin search mechanism. So it would look for .eslintrc, package.json, etc, in that directory, and resolve plugin modules relative to it. Since ESLint wants to stay configurable, it will also look for overrides in the current folder (and use its regular override mechanism), but this would just add configurator as a first-class citizen for providing configuration.

Similarly, Flow would look into that project when running flow init, and if it finds .flowconfig in react-scripts/config, it would use that instead of its default config. This gives us a way to own the default configuration even if the user is on their own. In the future, Flow could support merging ${configurator}/config/.flowconfig with local .flowconfig—similar to how ESLint would work if it implemented this feature.

This would benefit an ecosystem by fostering development of opinionated presets of preconfigured tools. If you’re a tool, honor configurator in package.json and try reading configuration from ${configurator}/config in addition to your normal lookup paths. If you’re a preset author, you can fork react-scripts or any other configurator, make some changes to it, and keep it simple to adopt your preset: just swapping configurator is all end users need to do.

What do you think? Am I missing something?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:36
  • Comments:20 (12 by maintainers)

github_iconTop GitHub Comments

6reactions
gaearoncommented, Jul 26, 2016

The downside with https://github.com/facebookincubator/create-react-app/issues/215#issuecomment-235278535 is that every IDE/plugin would need to implement this. So, for each of N tools (ESLint, Flow), there would be M plugins (Atom, Sublime), and NxM integrations that would need to do it this way (ESLint for Atom, ESLint for Sublime, Flow for Atom, …).

Whereas if we do this on the tool level as suggested in https://github.com/facebookincubator/create-react-app/issues/215#issue-167602431, we only need the N tools to integrate this. IDEs already call the tools with no arguments and rely on the tools to know how to discover configuration.

6reactions
vjeuxcommented, Jul 26, 2016

There’s already a thousand ways that all those tools can figure out where to find the configuration, it’s really unclear to me that adding yet another one is the right solution. Also, adding a hardcoded path to the config that the tools can read means that anybody can also read it and it’s not a blackbox anymore.

Proposal instead:

Have the IDEs read package.json and if there’s a script called eslint, then use it instead of the global eslint.

Then, we would add an opaque script that calls eslint with --config=opaquepath/eslintrc

Read more comments on GitHub >

github_iconTop Results From Across the Web

package.json - npm Docs
Description. This document is all you need to know about what's required in your package.json file. It must be actual JSON, not just...
Read more >
Manifest fields | Yarn - Package Manager
List of all the supported fields for a Yarn project manifest (package.json files)
Read more >
What's what? - Package.json cheatsheet! - Arek Nawo
A complete rundown of all various package.json fields. How to setup Node.js package.json file? What means what? Dependencies, files, configs ...
Read more >
package.json | pnpm
package.json. The manifest file of a package. It contains all the package's metadata, including dependencies, title, author, et cetera.
Read more >
Specifics of npm's package.json handling - manpages.ubuntu!
If you plan to publish your package, the most important things in your package.json are the name and version fields as they will...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found