Skip to content

Instantly share code, notes, and snippets.

@tylergaw
Last active January 26, 2017 20:09
Show Gist options
  • Select an option

  • Save tylergaw/84c85da9c844d325b3ec99d8d329eaff to your computer and use it in GitHub Desktop.

Select an option

Save tylergaw/84c85da9c844d325b3ec99d8d329eaff to your computer and use it in GitHub Desktop.

Node Dependency Conflict using Create React App and Groundwork.JS

(update: While this could still be an issue that effects other packages, Groundwork.JS is fixed as of 1.5.1. https://github.com/thegroundwork/groundwork.js/pull/55 Darren fixed it by moving the dependencies to proper spots)

I'm not sure if this is an issue with Create React App, or with Groundwork.JS, or just a "this is how the world works". Whatever the reason, the results are trouble.

The main issue; because npm has a flat(er) directory structure as of version 3.x, dependencies can be overwritten by subdependencies. This can cause breakage if a dependency relies on a certain version and cannot find it. Which I'll show an example of here.

Setup

If you're following along and want to see this like I am here are my relevant versions of software.

node:

node -v
v6.9.1

npm

npm -v
3.10.8

create-react-app

create-react-app --version
1.0.2

What we'll see

After a bit of install dancing–which is going to be common–we'll see the react app unable to be started or built due to an error with eslint configuration in the eslint-config-react-app.

Create the project

We'll follow the standard steps for creating a new app via create-react-app.

create-react-app dep-stomping

Once it finished, move to the directory; cd dep-stomping. Because we know eslint is the troubled package, let's take a look at what version is installed now.

npm ls eslint
[email protected] /Users/tyler/Desktop/dep-stomping
└─┬ [email protected]
  └── [email protected]

3.x.x is the version react scripts depends on. And notice we're using the version of it installed under react-scripts. Confirm the application is ready to go by running; npm start. If everything is good, you should see the standard app running on port 3000

Groundwork.JS

Stop your app server with ctrl-c and install Groundwork.JS and make sure it's saved to package.json:

npm install --save groundwork.js

After Groundwork.JS install is complete, let's check eslint again:

npm ls eslint
[email protected] /Users/tyler/Desktop/dep-stomping
└─┬ [email protected]
  └── [email protected]

Perfect. We're still on the 3.x series and still using the react-scripts dependency. Again, let's ensure the app is runnable with npm start.

If the app is still running as expected, we're good to go.

Create the problem state

This issue appears to occur because of the order dependencies and subdependencies are installed. Let's get the project into a state that will be common for any new contributor or ourself if we switch to a different machine or wipe out this project directory. We'll do so by removing the node_modules directory and clearing npm caches. Stop the app server and run:

rm -rf node_modules

and then

npm cache clean

Just to make sure we're in a blank state run; npm ls. This should produce a number of errors:

[email protected] /Users/tyler/Desktop/dep-stomping
├── UNMET DEPENDENCY [email protected]
├── UNMET DEPENDENCY [email protected]
└── UNMET DEPENDENCY [email protected]

npm ERR! missing: [email protected], required by [email protected]
npm ERR! missing: [email protected], required by [email protected]
npm ERR! missing: [email protected], required by [email protected]

These errors are expected becuase we have dependencies in package.json, but haven't installed any of them. Now, install the dependencies with:

npm install

Once install completes, you may already see signs of the issue in a new stack of warnings from npm:

npm WARN [email protected] requires a peer of babel-eslint@^7.0.0 but none was installed.
npm WARN [email protected] requires a peer of eslint@^3.8.1 but none was installed.
npm WARN [email protected] requires a peer of eslint-plugin-react@^6.4.1 but none was installed.
npm WARN [email protected] requires a peer of eslint@>=2.0.0 but none was installed.
npm WARN [email protected] requires a peer of eslint@^2.10.2 || 3.x but none was installed.
npm WARN [email protected] requires a peer of [email protected] - 3.x but none was installed.

Now let's check on eslint

npm ls eslint
[email protected] /Users/tyler/Desktop/dep-stomping
└─┬ [email protected]
  └── [email protected]

Notice we're now using version 1.10.3 which is a dependency of groundwork.js. This is the problem. Confirm this is the problem by running npm start:

Failed to compile.

Error in ./src/index.js
Module build failed: Error: react-app:
	Configuration for rule "array-callback-return" is invalid:
	Value "warn" is the wrong type.

Referenced from: /Users/tyler/Desktop/dep-stomping/node_modules/react-scripts/.eslintrc
    at Array.forEach (native)
    at Array.reduceRight (native)
 @ multi main

Why is eslint having trouble though?

In eslint version 1.10.3 error levels for each rule were specified as an integer; 0, 1, or 2. 1.10.3 config docs

I'm not sure the exact version that changed this, but at least as far back as 3.0.0 error levels can now be specified as an integer or a string off, warn, or error. 3.0.0 config docs

The error we see above from the react app is due to the first eslint rule specified in eslint-config-react-app

'array-callback-return': 'warn',

Because the app is using the Groundwork.JS specified version of eslint, 1.10.3, eslint is expecting an integer and rightly throws an error when it sees the string "warn".

A sub-optimal work around

Before finding a proper fix, there is a way to get your app up and running. We'll do a bit of dependency install juggling. First, stop the app if it's still running; ctrl-c.

Remove node_modules and clean caches:

rm -rf node_modules && npm cache clean

Go to package.json and delete the groundwork.js dependency. Then install dependencies with; npm install.

Again, take a look at which verison of eslint we're using:

npm ls eslint
[email protected] /Users/tyler/Desktop/dep-stomping
└─┬ [email protected]
  └── [email protected]

and to double-check things are back, start the app with npm start. Note; if your app depends on groundwork.js it may throw errors whn it can't find it in this step. As long as you don't see the previous eslint error, you should be OK. Now we can install groundwork.js;

npm install groundwork.js

and for good measure check on eslint:

npm ls eslint
[email protected] /Users/tyler/Desktop/dep-stomping
└─┬ [email protected]
  └─

We're back to using the eslint version we need and have Groundwork.JS install. Once again, start the app with npm start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment