Closed appdev44 closed 4 years ago
Curious about this as well. Any advice on how to get the built output a copy of the binary?
@appdev44 @atrauzzi I'd the same issue. First, you need to copy the file into the output directory and then build a relative path in the runtime instead of hardcoding an absolute one during a build process. I've extracted this to the npm package since non of the existing solutions had that feature. You can use that code: https://github.com/smt116/node-native-ext-loader, create your own implementation using it as the starting point or create a pull request to some existing solutions. You might be also interested in the https://github.com/ushu/node-addon-loader as it was used as the inspiration for node-native-ext-loader
.
I have the same pb when i'm building this native addon in an other directory. It is the same with native-ext-loader
and node-addon-loader
My situation:
Webpack builds to
./dist
And we create an asar package with webpack. Then in our application we have
./electron.exe ./application/package.asar/dist
A reference to what was once ./node_module/somemodule/module.node can not be found in the packaged app because ./dist will not exist and it should have been ./application/package.asar/dist/
Any idea how to fix this?
I had a similar problem, I have a build machine that build my addon then webpack packs everything. However, since the .node file wasn't actually bundled I couldn't run the packed script anywhere else.
I ended up writing my own loader, I don't know if it can be made generic, but it does solves my problem at least and I hope it can help others.
const fs = require("fs");
const path = require("path");
module.exports = function nodeLoader() {
const filename = path.basename(this.resourcePath);
const src = fs.readFileSync(this.resourcePath, {encoding: "binary"});
return `
const nodeFilename = ${JSON.stringify(filename)};
const src = ${JSON.stringify(src)};
require("fs").writeFileSync(nodeFilename, src, "binary");
try {
global.process.dlopen(
module,
nodeFilename
);
} catch(e) {
throw new Error('node-loader: Cannot open ' + nodeFilename + ': ' + e);
}
`;
};
It will bundle the .node file as a string in the packed script and then can be used to load it.
Since global.process.dlopen
expects a filename, I had to write the data to a file in cwd
before loading it
The following solution worked for me:
const CopyPlugin = require('copy-webpack-plugin')
module.exports = {
plugins: [
new CopyPlugin([{
from: 'node_modules/scrypt/build/Release/scrypt.node',
to: 'build/Release'
}])
],
externals: './build/Release/scrypt'
}
externals
preserves the original require()
/etc. argument, instead of the absolute path that node-loader
emitsresolve.extensions
doesn't by default include .node
, so I'd either need to add it, or use resolve.alias
, and then worry about the path that the addon would be copied to ... copy-webpack-plugin
seemed obviouser.Somebody can create minimum reproducible test repo?
This demo: https://github.com/joshuan/test-node-loader node-loader generate absolute path to keytar.node (as example) native module.
I had a similar problem, I have a build machine that build my addon then webpack packs everything. However, since the .node file wasn't actually bundled I couldn't run the packed script anywhere else.
I ended up writing my own loader, I don't know if it can be made generic, but it does solves my problem at least and I hope it can help others.
const fs = require("fs"); const path = require("path"); module.exports = function nodeLoader() { const filename = path.basename(this.resourcePath); const src = fs.readFileSync(this.resourcePath, {encoding: "binary"}); return ` const nodeFilename = ${JSON.stringify(filename)}; const src = ${JSON.stringify(src)}; require("fs").writeFileSync(nodeFilename, src, "binary"); try { global.process.dlopen( module, nodeFilename ); } catch(e) { throw new Error('node-loader: Cannot open ' + nodeFilename + ': ' + e); } `; };
It will bundle the .node file as a string in the packed script and then can be used to load it. Since
global.process.dlopen
expects a filename, I had to write the data to a file incwd
before loading it
thanks, this solution partially works for me. On windows 10, if I install for the current user, it works. If I install for all users, it not works.
Is this still an open bug? I'm having a similar issue with keytar
where absolute paths are packaged into the application and then the app fails when distributed to other machines
I used https://github.com/toyobayashi/native-addon-loader and it solved all my issues.
Just for the record, I've been trying to get nodegit to work with Electron and create-react-app and native-addon-loader was the only one that worked, having also tried the options from this comment.
@Livven I'm having a problem with this library. Webpack bundles my application into the following structure:
- .webpack
- service
- src
handler.js
addon.node
But in handler.js
I have module.exports = require("./addon.node");
. But this path is not valid. If I manually move addon.node
to src
, it works.
Do you know how can I make handler.js
reference the correct path?
If anyone encounters this "node-loader" issue while working with Electron, target: 'electron-renderer'
and the following syntax can resolve it.
const addon = require('electron').remote.require('./addon/dist/addon.node');
The link below contains more detail. https://stackoverflow.com/questions/50547649/using-node-js-addons-in-electrons-renderer-with-webpack
If an error message, "Require is not defined", is found, nodeIntegration: true
needs to put in the main js file. This link has more detail.
https://stackoverflow.com/questions/55233839/require-is-not-defined-when-adding-electron-renderer-to-webpack
Fixed in the next branch, ETA is today, anyway you faced with this problem again, please open a new issue with minimum reproducible test repo and we will fix it :+1:
I have a webpack(3.5.6) project using node-loader(0.6.0), which I use to build a package for a nw.js application. I am trying to include a custom node package (Created with nw-gyp) in my build. But for some reason all files apart from the ".node" files are copied into my build folder, and in the generated java script file, it has an absolute path reference eg function(module) {try {global.process.dlopen(module, "c:\src\locale_modules\helloworld.node")
thanks, alex