dubmojo
dubmojo

Reputation: 6838

Why does bundling Node.js backend api with Webpack fails with "TypeError: i is not a function"?

I'm trying to create a docker container to house my front (React) and backend (express REST service) but my efforts to bundle the backend with Webpack are failing to execute claiming that "i is not a function". I should be clear that this is not running in Docker yet. I'm just trying to execute it in my dev environment manually first.

I simply webpack, then try running the bundled js directly (e.g. node ./dist/server.bundle.js). Here's my webpack.config.js:

{
    "name": "test-backend",
    "version": "1.0.0",
    "description": "Test Backend",
    "scripts": {
        "start": "nodemon ./server.js",
        "build": "webpack",
        "debug": "node --inspect ./server.js",
        "debug-brk": "node --inspect-brk ./server.js"
    },
    "dependencies": {
        "body-parser": "1.19.0",
        "cors": "2.8.5",
        "express": "4.17.1",
        "express-jwt": "5.3.3",
        "ioredis": "4.17.3",
        "jsonwebtoken": "8.5.1",
        "ldapjs": "2.0.0",
        "ldapjs-client": "0.1.1",
        "lodash": "4.17.19",
        "node-cache": "5.1.0",
        "redis": "3.0.2",
        "rootpath": "0.1.2",
        "superagent": "5.2.2",
        "uuid": "8.2.0"
    },
    "devDependencies": {
        "nodemon": "2.0.4",
        "webpack": "^4.43.0",
        "webpack-cli": "^3.3.12",
        "webpack-node-externals": "^2.5.2"
    }
}

The error line/position points to what looks like an import for "crypto", and others, in my bundled backend js:

TypeError: i is not a function
    at Object.<anonymous> (/var/test/test-services/images/test-unified/backend/dist/server.bundle.js:333:90327)
    at n (/var/test/test-services/images/test-unified/backend/dist/server.bundle.js:1:110)
...

...var r=i("crypto"),a=i("fs"),o=i("util"),s=i("path"),...

I feel like the webpacking failed to include necessary node modules. It's most likely that I'm missing something from my webpack.config.js:

const path = require('path');

module.exports = {
  entry: './server.js',
  mode: 'production',
  target: 'node',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'server.bundle.js'
  }
};

There are some examples and tutorials on bundling server side js, but they're examples and just include simple server.js code without Express and other modules.

Any tips are greatly appreciate. Thank you.

Upvotes: 1

Views: 709

Answers (1)

dubmojo
dubmojo

Reputation: 6838

I'll close this question by sharing my webpack.config.js change:

const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: './server.js',
  mode: 'production',
  target: 'node',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'server.bundle.js'
  },
  externals: [nodeExternals()]
};

Using webpack-node-externals will basically expect that node_modules be locally relative and not try to bundle them in. Your source will be, but not the external modules. I can live with that.

To answer jonsharpe's Q as to why bundle a Node.js app was primarily for simplicity of my docker container and in a way security by packing and optimizing my application. I have a bunch of various components, services and controllers in the app and it's all one file now.

I found this guide after the fact that mentions the issue with require and external nodes. She also used webpack-node-externals: https://jasminexie.github.io/using-webpack-for-node-backend/

Upvotes: 1

Related Questions