Using webpack with NodeJs native modules
Asked Answered
N

1

13

I have an Node.js app that has few native module which are created via node-gyp. These modules do not end up in "node_modules" and are being required via standard "require" from Node...

My webpack config is based on this article If I run the app "unpackaged" - everything works fine... But after I run "webpack -p --progress" and try to run it, I get following:

X:\myapp>node main-backend.bundle.js env=production port=80 ssl_port=443
[Error: Cannot open X:\myapp\lib\modules\my-module\build\Release\mymodule.node: Error: The specified module could not be found.

I made sure all the loaders are npm installed. From the error, I can tell that the path is correct (relative to server.native.js) but obviously not to app.js...However, this "just works" when using regular node.js and I am not sure if this is even the crux of the issue...

I would appreciate any help!

Here is abridged layout of my app

myapp/
    app.js
    node_modules/
    lib/
      modules/
        my-module/
           src/
             one.cc
             one.h
           lib/
             server.native.js
           bindings.gyp
           build/
             Release/
               mymodule.node

server.native.js is very simple, calling native module

try {
    module.exports = require('../build/Release/mymodule.node');
    console.log('native module loaded...');
} catch (err) {
    console.log(err);
}

And here is my webpack.config.js

var webpack = require("webpack");
var path = require("path");
var fs = require("fs");

var nodeModules = {};
fs.readdirSync("node_modules")
  .filter(function(x) {
    return [".bin"].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = "commonjs " + mod;
  });


module.exports = [
  {
    name: "server-side",
    context: __dirname,
    entry: {
      "main-backend": "./app.js"
    },
    target: "node",
    output: {
      path: __dirname,
      filename: "[name].bundle.js",
      chunkFilename: "[id].bundle.js"
    },
    module: {
      loaders: [
        { test: /\.json$/,   loader: "json-loader" },
        { test: /\.jade$/,   loader: "jade-loader" },
        { test: /\.node$/,   loader: "node-loader" }
      ]
    },
    externals: [nodeModules],
    resolve: {
      extensions: [ "", ".js", ".node"]
    },
    plugins: [
      new webpack.IgnorePlugin(/\.(css|less)$/)
      new webpack.BannerPlugin("require(\"source-map-support\").install();", { raw: true, entryOnly: false })
    ],
    node: {
      __dirname: true,
      __filename: true
    },
    devtool: "sourcemap",
    profile: true
  }
];
Nimocks answered 28/9, 2015 at 21:33 Comment(1)
You have externals: [nodeModules], instead of externals: nodeModules, as per the articleAmah
S
2

For the past two years, I was wondering how to use native modules along webpack@4 and webpack@5. It's quite sad to say that but after hundreds of hours spend on the idea of integrating native modules into a bundle I get a conclusion about how much impossible it is.

My recommendation is to put every module that is using .node or other kinds of native modules into nodeExternals - webpack will just skip them and if you'll want to run your bundle you need to have modules installed. Using webpack for native projects aren't a good solution and I would simplify recommend going through without it.

Steiner answered 12/1, 2022 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.