Search code examples
reactjsherokuwebpackdeployment

Heroku deployment of a React app with webpack says cannot find webpack dependency but it runs ok on local


I am trying to deploy a simple react app, built with webpack, on Heroku but I am getting this error: [![enter image description here][1]][1]

While on local it runs without any problem. When running the command heroku logs --tail --app myApp I get these logs, where in the end it still says Build succeeded + error webpack not found:

2021-09-23T16:43:10.842485+00:00 app[web.1]: sh: 1: webpack: not found
2021-09-23T16:43:10.847661+00:00 app[web.1]: npm ERR! code ELIFECYCLE
2021-09-23T16:43:10.847852+00:00 app[web.1]: npm ERR! syscall spawn
2021-09-23T16:43:10.847936+00:00 app[web.1]: npm ERR! file sh
2021-09-23T16:43:10.848030+00:00 app[web.1]: npm ERR! errno ENOENT
2021-09-23T16:43:10.852550+00:00 app[web.1]: npm ERR! assessment@1.0.0 start: `webpack serve --config ./webpack.config.js --mode development`
2021-09-23T16:43:10.852592+00:00 app[web.1]: npm ERR! spawn ENOENT
2021-09-23T16:43:10.852656+00:00 app[web.1]: npm ERR!
2021-09-23T16:43:10.852708+00:00 app[web.1]: npm ERR! Failed at the assessment@1.0.0 start script.
2021-09-23T16:43:10.852755+00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
2021-09-23T16:43:10.855613+00:00 app[web.1]:
2021-09-23T16:43:10.855700+00:00 app[web.1]: npm ERR! A complete log of this run can be found in:
2021-09-23T16:43:10.855749+00:00 app[web.1]: npm ERR!     /app/.npm/_logs/2021-09-23T16_43_10_853Z-debug.log
2021-09-23T16:43:10.969506+00:00 heroku[web.1]: Process exited with status 1
2021-09-23T16:43:11.000000+00:00 app[api]: Build succeeded
2021-09-23T16:43:11.025930+00:00 heroku[web.1]: State changed from starting to crashed
2021-09-23T16:43:11.099764+00:00 heroku[web.1]: State changed from crashed to starting
2021-09-23T16:43:12.966234+00:00 heroku[web.1]: Starting process with command `npm start`
2021-09-23T16:43:13.949091+00:00 app[web.1]:
2021-09-23T16:43:13.949101+00:00 app[web.1]: > assessment@1.0.0 start /app
2021-09-23T16:43:13.949102+00:00 app[web.1]: > webpack serve --config ./webpack.config.js --mode development
2021-09-23T16:43:13.949102+00:00 app[web.1]:
2021-09-23T16:43:13.953260+00:00 app[web.1]: sh: 1: webpack: not found
2021-09-23T16:43:13.956297+00:00 app[web.1]: npm ERR! code ELIFECYCLE
2021-09-23T16:43:13.956485+00:00 app[web.1]: npm ERR! syscall spawn
2021-09-23T16:43:13.956570+00:00 app[web.1]: npm ERR! file sh
2021-09-23T16:43:13.956655+00:00 app[web.1]: npm ERR! errno ENOENT
2021-09-23T16:43:13.959694+00:00 app[web.1]: npm ERR! assessment@1.0.0 start: `webpack serve --config ./webpack.config.js --mode development`
2021-09-23T16:43:13.959750+00:00 app[web.1]: npm ERR! spawn ENOENT
2021-09-23T16:43:13.959805+00:00 app[web.1]: npm ERR!
2021-09-23T16:43:13.959848+00:00 app[web.1]: npm ERR! Failed at the assessment@1.0.0 start script.
2021-09-23T16:43:13.959888+00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

It seems that somehow it cannot find the webpack dependency.

This is my webpack:

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: path.resolve(__dirname, './src/index.js'),
  module: {
    rules: [
      // React loader
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      // css loader
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      // Images loader
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
      // SVG loader
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'svg-url-loader',
            options: {
              limit: 10000,
            },
          },
        ],
      },
    ]
  },
  resolve: {
    extensions: ['*', '.js', '.jsx'],
  },
  output: {
    path: path.resolve(__dirname, './build'),
    filename: 'bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Founders Lair Assessment',
      filename: 'index.html',
      template: path.resolve(__dirname, './src/public/index.html'),
      inject: 'body'
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    contentBase: path.resolve(__dirname, './build'),
    port: 3000,
    hot: true
  },
};

This is my package.json:

"scripts": {
        "start": "webpack serve --config ./webpack.config.js --mode development",
        "predeploy": "npm run build",
        "deploy": "gh-pages -d build",
        "build": "webpack --mode production",
        "heroku-prebuild": "npm install --dev"
    },
    "keywords": [],
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.12.10",
        "@babel/preset-env": "^7.12.11",
        "@babel/preset-react": "^7.12.10",
        "antd": "^4.9.4",
        "axios": "^0.21.0",
        "babel-loader": "^8.2.2",
        "css-loader": "^5.0.1",
        "file-loader": "^6.2.0",
        "gh-pages": "^3.1.0",
        "html-webpack-plugin": "^5.0.0-beta.1",
        "lodash": "^4.17.10",
        "react": "^17.0.1",
        "react-dom": "^17.0.1",
        "react-hot-loader": "^4.13.0",
        "style-loader": "^2.0.0",
        "svg-url-loader": "^7.1.1",
        "webpack": "^5.11.0",
        "webpack-cli": "^4.2.0",
        "webpack-dev-server": "^3.11.0"
    },
    "dependencies": {
        "dotenv": "^8.2.0"
    }

Any idea how to fix this issue? [1]: https://i.sstatic.net/khbm0.png


Solution

  • The problem is that the heroku container does not know how to serve your project by default. You need to install a local server so that your files can be requested. As such, you need to do the following:

    1. add express as a dependency. your package.json file should have express under "dependencies", like so: "express": "^4.18.1" (don't forget the comma at the end, if needed)

    2. you will then need a server.js file with the following content:

      const express = require('express') const path = require('path');

      const app = express() const port = process.env.PORT || 3000

      app.use(express.static(path.join(__dirname, 'build')));

    3. the start script in package.json should be "node server.js"

    4. now deploy all this to heroku and it should work

    PS: or if you don't like this approach (although imo it is the cleanest), then you probably need to add webpack as a dependency (and not devDependency) and it will probably work but it's not recommended to use dev configs in production.