Gatsby: Custom ESLint rules

Created on 13 Oct 2017  Â·  8Comments  Â·  Source: gatsbyjs/gatsby

Environment

Product | Version
--- | ---
Gatsby version | 1.9.55
NodeJS | 8.5.0
macOS | 10.11.6

The problem

Context

Hi folks,

I got a generic ESLint configuration for ReactJS based projects that I'm using on a Gatsby-based project.

ESLint has no clue about Gatsby's webpack existence and fires some false-positives because of three main issues:

  • No extension resolving (e.g. .jsx) causing import/no-unresolved errors
  • No alias resolving (e.g. /helpers/) causing import/no-unresolved errors
  • Loading gatsby-plugin-... version of plugins (e.g. styled-components), but importing original-plugin in the project causing no-extraneous-dependencies errors

gatsby-node.js

const path = require("path");
const pathRoot = (...args) => path.resolve(__dirname, ...args);

exports.modifyWebpackConfig = ({ config, stage }) => {

  config.merge({
    resolve: {
      extensions  : [".js", ".jsx"],
      alias       : {
        config  : pathRoot("config"),
        helpers : pathRoot("src", "helpers"),
        shared  : pathRoot("src", "shared")
      }
    }
  });

  return config;

};

Ugly fix

We can fix the third issue by declaring core-modules like that (not so clean & difficult to maintain):

"import/core-modules": [
      "react",
      "prop-types",
      "react-helmet",
      "styled-components"
    ],

The two other rules are temporary (?) disabled...

--> Is there any clean solution (other than this) ?


Related to

gatsbyjs/gatsby#463
gatsbyjs/gatsby#1990
gatsbyjs/gatsby#362

stale?

Most helpful comment

There are few things I think we can do to mitigate this. I think the first important step is to release an eslint-config-gatsby that sets up all the relevant globals, "core" module, and the like

All 8 comments

There are few things I think we can do to mitigate this. I think the first important step is to release an eslint-config-gatsby that sets up all the relevant globals, "core" module, and the like

@jquense That's a great idea for the import/core-modules part.

But I still don't see any good solution for the disabled rules.

the other's are easy enough to handle with a config i thinl, though i don't quite understand these concerns:

No alias resolving (e.g. /helpers/) causing import/no-unresolved errors
Loading gatsby-plugin-... version of plugins (e.g. styled-components), but importing original-> > plugin in the project causing no-extraneous-dependencies errors

what is /helpers/ and why doesn't importing gatsby-plugins directly work? everything should be listed in the site package.json (and resolvable)

About gatsby plugins

If I'm right, plugins which have a gatsby version (such as styled-components and react-helmet) should be listed as gatsby-plugin-foo-bar and not foo-bar in the package.json.

For instance, take the official example of Styled Component: it's only using gatsby-plugin-styled-components and not styled-components.

package.json

  "dependencies": {
    "gatsby": "latest",
    "gatsby-plugin-styled-components": "latest",
  },

In a component, you still import the original plugin, and not the gatsby version:

MyComponent.jsx

import styled from "styled-components";

This package is loaded from the gatsby plugin itself which has a styled-components dependency...

... Firing the import/no-extraneous-dependencies ESLing rule:

ESLint

  1:1  error  'styled-components' should be listed in the project's dependencies. Run 'npm i -S styled-components' to add it  import/no-extraneous-dependencies

I can see two solutions for that:
1) Add the original package dependency in the Gatsby project?
2) Add a import/core-modules ESLint rule for theses packages?

About Webpack resolving

File extensions

Fixed by the following ESLint rule:

"import/extensions" : ["error", { "jsx": "never" } ]

Aliases

We have several directories in the /src/ which are shared across the project (e.g. /helpers/), but not shared in other projects (that's why they aren't in a package).

In order to use them from any file while avoiding the /../../../helpers/foo.js, we have set a webpack helpers/... alias. In a non-Gatsby React project, ESLint can understand these aliases and resolve them. In a Gatsby project, ESLint isn't aware of the webpack config and isn't able to resolve as a result.

A temporary solution is to disable this ESLint rule, but it's an open door for real unresolved errors:

"import/no-unresolved" : "off",

@jquense Is that more understandable? :)

So i think some of the problem here is that we've chosen a small convenience at the expense of defeating tools and best practices. Frankly I think that Gatsby should not provide these modules without you installing them. Take the styled-components, the correct way to structure that plugin is to have styled-components be a peerDependency of the plugin (like the emotion-plugin), not a direct dependent, if styled-components really only needs one instance of it, otherwise i'd say we shouldn't automagically let you import the plugins dependency. Ditto for packages like React, prop-types, etc. There is just too much issue with this and no good way of letting all the tooling know about, instead the starter should just install these dependencies directly, and then you can treat them like any other dep.

Yeah… with starters and us giving the npm install instructions in packages — people shouldn't have too much trouble getting the right packages installed.

Perhaps make this switch for v2?

For what it is worth, I created this for linting my own projects: https://www.npmjs.com/package/eslint-config-gatsby-standard

Old issues will be closed after 30 days of inactivity. This issue has been quiet for 20 days and is being marked as stale. Reply here or add the label "not stale" to keep this issue open!

Was this page helpful?
0 / 5 - 0 ratings