Jehjoa
Jehjoa

Reputation: 561

Webpack not recognizing Node's process module

After not touching Javascript for over a decade I had an idea for an app that will work best when implemented as a NodeJS app. I read up on the modern JS ecosystem and like most people I'm thoroughly confused, haha.

Seems like the combination of NodeJS, TypeScript and Webpack is a good way to go, but I'm having issues even getting a simple Hello World working.

The one TypeScript file I wrote, ./src/run_task.ts:

// #!/usr/bin/env node
/**
 * @file Main application file. Users start the app by running `node dist/run_task.js`
 * @author Gerard Leenhouts
 */

import * as process from "process";

function main(): number {
    console.log(process);
    console.log(`Got ${process.argv.length} arguments.`);
    return 42;
}

main();

When I execute tsc manually (tsc -p server.tsconfig.json) it works fine, but when I execute webpack it seems to create it's own definition of the process module in the resulting .js file. Here's a part of it:

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        runTimeout(drainQueue);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) { return [] }

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };

My package.json:

{
  "name": "startpage",
  "version": "1.0.0",
  "description": "Self hosted web app to function as a web browser startpage",
  "main": "run_task.js",
  "scripts": {
    "build": "webpack",
    "start": "node dist/run_task.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Gerard Leenhouts",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^9.4.6",
    "ts-loader": "^3.5.0",
    "typescript": "^2.7.2",
    "webpack": "^3.11.0"
  }
}

My webpack.config.js:

const path = require('path');

module.exports = [
    {
        // devtool: 'inline-source-map',
        entry: './src/run_task.ts',
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    use: [
                        {
                            loader: 'ts-loader',
                            options: { configFile: 'server.tsconfig.json' }
                        }
                    ],
                    exclude: /node_modules/
                }
            ]
        },
        resolve: {
            extensions: [ '.ts', '.tsx', '.js' ]
        },
        output: {
            filename: 'run_task.js',
            path: path.resolve(__dirname, 'dist')
        }
    }
];

My server.tsconfig.json:

{
    "compilerOptions": {
        // "sourceMap": true,
        "outDir": "./dist/",
        "strict": true,
        "noImplicitAny": true,
        "target": "es6",
        "module": "commonjs",
        "moduleResolution": "node",
        "esModuleInterop": true,
        "baseUrl": "./",
        "paths": { "*": ["node_modules/*", "src/types/*"] },
        "removeComments": true
    },
    "include": [ "./src/**/*" ]
}

I've been going through the Webpack and TypeScript documentation for hours now, and can't seem to figure it out. It's quite possible I'm overlooking something simple but I can't see the forest for the trees anymore. Obviously it has something to do with module resolution but everything seems fine in the config files, as far as I can tell. Any help is appreciated, thanks in advance!

Upvotes: 1

Views: 3820

Answers (2)

Vipul Nema
Vipul Nema

Reputation: 21

Webpack's by default compile build for target "web". So To resolve your issue just use target value "node".

{ target: "node" }

Because client side code can also contain some Node js" global variable like "process.env". so webpack poly-fill those variable in web target build.

More more advanced case and control. "node" property can also be used directly. https://v4.webpack.js.org/configuration/node/

Upvotes: 0

Daniel Conde Marin
Daniel Conde Marin

Reputation: 7742

it seems to create it's own definition of the process module in the resulting .js file

In your webpack.config.js you need to set the target to node. Just add target: 'node' at the same level as output. This will compile for usage in a Node.js-like environment (uses Node.js require to load chunks and not touch any built in modules like process, fs, etc). Docs here: https://webpack.js.org/concepts/targets/

Upvotes: 4

Related Questions