The quick fix jumps over the lazy problem

When react-scripts build is called in a directory that also contains a .eslintrc.js file, React will automatically attempt to lint the code as part of the build. The problem (as we see it), is that our (and probably your?) linting packages are in the devDependencies section of package.json - which, when building in your CI environment with NODE_ENV=production, are not installed. This of course causes the linting, and therefore the entire build, to fail.

As we lint during development and check linting for each PR, there’s no reason for us to lint during build. To tell React to skip this auto-linting, you need to set an environment variable before the react-scripts build command runs.

DISABLE_ESLINT_PLUGIN=true react-scripts build

That’s all.

A little more context

We’ve been slowly building out a set of admin tools for our editorial team. (Our first tool was one to manage Collections.) We began this repo with the intent of having each tool be its own React application, which gave us the following basic structure:

.
├── .eslintrc.js
├── .gitignore
├── README.md
└── collections/
    ├── index.tsx
    └── package.json

Because package.json was not in the same folder as .eslintrc.js, we didn’t encounter the auto-linting issue. However, as we are now building a second tool for our editors, we re-assessed this project structure. Wouldn’t it be easier to have a single application that shared UI components, build/deploy scripts, and infrastructre? Yes. Yes it would. So, we reconfigured the project files:

.
├── .eslintrc.js
├── .gitignore
├── package.json
├── README.md
└── src/
    ├── _shared/
    │   ├── assets
    │   ├── components
    │   └── pages
    ├── index.tsx
    ├── collections/
    │   ├── components
    │   └── pages
    └── prospects/
        ├── components
        └── pages

(Notice how package.json is now in the same directory as .eslintrc.js.)

All seemed well and good until we opened a PR, at which point the docker_build step failed with the following:

Failed to compile.

Failed to load plugin 'prettier' declared in '.eslintrc.js': Cannot find module 'eslint-plugin-prettier'

Knowing the fix now, the above is easy to understand. However, nowhere could I find documentation that clearly states that if react-scripts build sees a .eslintrc.js file in the same directory, it will attempt to lint during build.

After some mostly fruitless research (read: searching Stack Overflow), we eventually did the obvious thing and removed .eslintrc.js. Voila! The build succeeded! However, we do want our .eslintrc.js file for local development and PR checks, so while we weren’t exactly done, we had discovered what was triggering the “new” lint-during-build behavior.

From there we re-visited our Stack Overflow tabs, remembering seeing something about disabling linting, re-added .eslintrc.js, and added the DISABLE_ESLINT_PLUGIN=true environment variable. Local dev and PR linting? Check. No linting during build? Check.

This was a silly problem to run in to, and was semi-tough to figure out as it wasn’t obvious why React was trying to lint during build all of the sudden. (Additionally, some changes had been made to .eslintrc.js and package.json in the original PR, so we also had to consider those changes as culprits.)

Hopefully this explanation and fix helps y’all.

P.S. I did find that the DISABLE_ESLINT_PLUGIN option is documented, but it still doesn’t make clear that the mere presence of a .eslintrc.js file will trigger linting.

Until next time, take care of each other, and I’ll see you on the internet.

~ jonathan, backend team


Tagged with: #react, #linting, #ci