0

Update #2 after some more research

Looking into the build logs some more, it looks like Cypress gets installed via a postinstall hook that downloads a binary that Heroku doesn't pick up in the build process for some reason unless config is set to NPM_CONFIG_PRODUCTION=false. Comparing the failed build log with the successful build log, this postinstall hook doesn't run:

> cypress@6.0.0 postinstall /tmp/build_0453cc7d/frontend/node_modules/cypress

Why this and potentially other devDependencies don't get installed prior to npm run build doesn't appear to be documented and runs contrary to Heroku's documentation that devDependencies are installed by default.

Update #1 with more build info

Here's a gist that shows the failing build log and the succeeding build log (after configuring Heroku not to prune devDependencies using heroku config:set NPM_CONFIG_PRODUCTION=false).

https://gist.github.com/ddehart/9e0ca72a3f20f104e05d70eed6de6c64

The pruning appears to be initiated after the build process installed Cypress, so it's not clear why setting NPM_CONFIG_PRODUCTION=false prompted the Cypress installation, despite Heroku's documentation that says:

By default, Heroku will install all dependencies listed in package.json under dependencies and devDependencies.

Original question

I'm getting this npm run build error when deploying to Heroku:

Failed to load plugin 'cypress' declared in 'package.json': Cannot find module 'eslint-plugin-cypress'

Here's my package.json for reference:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.6",
    "@testing-library/react": "^11.2.2",
    "@testing-library/user-event": "^12.2.2",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "^4.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "cypress:open": "cypress open",
    "cypress:run": "cypress run"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "plugin:cypress/recommended"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@testing-library/cypress": "^7.0.2",
    "cypress": "^6.0.0",
    "eslint-plugin-cypress": "^2.11.2"
  }
}

The project was initiated using Create React App. npm run build succeeds without any issues locally, so I first thought maybe Heroku was pruning devDependencies, but looking back at other build logs that succeeded show that pruning happens after a successful build.

If it helps, here's my package.json from the last successful build.

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "react-scripts": "3.4.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "cypress:open": "cypress open"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "plugin:cypress/recommended"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "cypress": "^5.4.0",
    "eslint-plugin-cypress": "^2.11.2"
  }
}

I think the build is complaining about this, although that hasn't changed at all from the last successful build.

  "eslintConfig": {
    "extends": [
      "react-app",
      "plugin:cypress/recommended"
    ]
  },

Removing that plugin declaration of course ruins Cypress in my IDE. Is there any way to work around the build error or troubleshoot on the Heroku instance itself?

Derek
  • 827
  • 11
  • 23
  • 1
    Does this answer your question? [Heroku can't find ts-node](https://stackoverflow.com/questions/57543386/heroku-cant-find-ts-node) – ChrisGPT was on strike Nov 28 '20 at 22:44
  • @Chris it's related, but there must be something about the internals of the Heroku build process I don't understand. `devDependency` pruning happens after the build process (which fails). For whatever it's worth, setting `NPM_CONFIG_PRODUCTION=false` prompted npm to install Cypress, which cleared the error. I'd love to understand why, though, as keeping this configuration seems suboptimal. – Derek Nov 28 '20 at 23:34
  • "`devDependency` pruning happens after the build process (which fails)"—your question doesn't show this. Please [edit] it and add more context for your build error, so we can see the full stack trace. – ChrisGPT was on strike Nov 28 '20 at 23:36
  • @Chris I just added additional info. Thanks for your help – Derek Nov 28 '20 at 23:49
  • It looks like the issue was more with my `eslintConfig` than it was with `devDependencies`. I still don't completely understand what changed since previous builds succeeded, but at least I avoided the config @Chris recommended against in his answer. – Derek Nov 29 '20 at 02:39

1 Answers1

2

Rather than setting NPM_CONFIG_PRODUCTION=false, I ended up moving the Cypress eslintConfig into its own .eslintrc.json file within the cypress directory. Since Heroku only seems to be getting hung up on the Cypress plugin referenced in the main package.json, removing that configuration altogether fixed the Heroku build issue without affecting my IDE and without having to rely on the non-standard NPM_CONFIG_PRODUCTION setting.

Per Cypress's documentation, the .eslintrc.json file just needs this for the recommended rules:

{
  "extends": [
    "plugin:cypress/recommended"
  ]
}
Derek
  • 827
  • 11
  • 23