Im very new to Node and is possible its just my lack of knowledge, in that case Im sorry, I opened the issue https://github.com/nodejs/node/issues/18267 thinking it was a node bug but the issue https://github.com/grpc/grpc/issues/13049 is telling: "The __dirname variable is explicitly documented as referring to the full path of the directory containing the current module file."
There is a comment of me after this block with a script to reproduce the project.
Below the detail steps to reproduce the problem:
__dirname => "/"
var binding_path = binary.find(path.resolve(path.join(__dirname, './package.json'))); /* node_modules/bcrypt/bcrypt.js [line:0005] */
/* INNER path.join(__dirname, './package.json') RETURNS '/package.json' */
/*
resolvedPath => ""
path => "/package.json"
resolvedPath => ""
resolvedAbsolute => false
resolvedPath = path + '/' + resolvedPath; /* <node_internals>/path.js [line:1174] */
resolvedPath => "/package.json/"
path => "/package.json"
resolvedPath => "/package.json/"
resolvedAbsolute = path.charCodeAt(0) === 47/*/*/; /* <node_internals>/path.js [line:1175] */
resolvedAbsolute => true
resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); /* <node_internals>/path.js [line:1182] */
resolvedPath => "package.json"
"/package.json" <= return '/' + resolvedPath; /* <node_internals>/path.js [line:1186] */
/* node_modules/bcrypt/node_modules/node-pre-gyp/lib/pre-binding.js [ {function=binary.find} line:0015] /
/ binary.find execute against "/package.json" and throw error: "package.json does not exist at /package.json"
/* the problem looks happens because of lack of calling "process.cwd()" inside [ {function=path.resolve} line:1174] on the flow */
Can you provide exact steps or script to reproduce this?
Also mention nodejs and npm versions.
Thanks for the attention.
Here what you asked:
node --version => v8.2.1
npm --version => 5.6.0
mkdir -p base
cd base
mkdir ts
npm init -y
npm install typescript --save-dev
npm install webpack --save-dev
npm install webpack -g
npm install webpack
npm install webpack-node-externals
npm install awesome-typescript-loader --save-dev
npm install file-loader
npm install ignore-loader
npm install ts-loader
npm install bcrypt @types/bcrypt
npm install jshint
npm install aws-sdk
/* aws-sdk above to stop compiler error */
tsc --init
***
echo '' > ./package.json
cat <<EOT>> ./package.json
{
"name": "stp003-Node",
"version": "1.0.0",
"description": "learn",
"private": "true",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"awesome-typescript-loader": "^3.4.1",
"typescript": "^2.6.2",
"webpack": "^3.10.0"
},
"dependencies": {
"@types/bcrypt": "^1.0.0",
"aws-sdk": "^2.185.0",
"bcrypt": "^1.0.3",
"file-loader": "^1.1.6",
"ignore-loader": "^0.1.2",
"jshint": "^2.9.5",
"ts-loader": "^3.3.0",
"webpack-node-externals": "^1.6.0"
}
}
EOT
***
echo '' > ./tsconfig.json
cat <<EOT>> ./tsconfig.json
{
"compilerOptions": {
/* Specify ECMAScript target version:
'ES3' (default), 'ES5', 'ES2015',
'ES2016', 'ES2017', or 'ESNEXT'. */
"target": "ESNEXT",
/* Specify module code generation:
'none', 'commonjs', 'amd', 'system',
'umd', 'es2015', or 'ESNext'. */
"module": "ESNext",
/* Enable all strict type-checking options. */
"strict": true,
/* Generates corresponding '.map' file. */
"sourceMap": true
}
}
EOT
***
echo '' > webpack.config.js
cat <<EOT>> webpack.config.js
module.exports = {
devtool: "inline-source-map",
entry: "./ts/index.ts",
target: "node",
output: {
filename: "./index.js"
},
resolve: {
extensions: ["*", ".js", ".ts", ".tsx", ".json"]
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: "awesome-typescript-loader", /* alternative ts-loader */
},
{
test: /\.(css|cs|htm|html)?$/,
loader: "ignore-loader"
},
{
test: /npm-cli\.js?$/,
loader: "ignore-loader"
}
]
},
node: {
ajv: "empty",
bcrypt: "empty",
child_process: "empty",
fs: "empty",
fsevents: "empty",
net: "empty",
npm: "empty"
}
};
EOT
***
mkdir -p ./ts/{M,V,C,T}
echo '' > ./index.js
echo '' > ./ts/T/dataUtil.ts
cat <<EOT>> ./ts/T/dataUtil.ts
export class DataUtil {
printIt(toPrint: string): void {
console.log(toPrint);
}
}
EOT
***
echo '' > ./ts/T/cryptUtil.ts
cat <<EOT>> ./ts/T/cryptUtil.ts
import * as bcrypt from 'bcrypt';
export class cryptUtil {
private _rounds: number = 10; //0xf49f6cd693d04c7ebe6928429a24f2ce;
public get rounds(): number {
return this._rounds;
}
public set rounds(rounds: number) {
this._rounds = rounds;
}
public getSalt(): string {
return bcrypt.genSaltSync(this.rounds);
}
public getSaltAsynchronous(
callback: ((err: Error, salt: string) => void)
): void {
bcrypt.genSalt(this.rounds, callback);
}
public BCryptHashGet(passw: string): string {
return this.BCryptHashGet(passw);
}
public BCryptHashGetAsynchronous(
passw: string,
callback: ((err: Error, hash: string) => void)
): void {
this.getSaltAsynchronous((err: Error, salt: string) => {
bcrypt.hash(this.rounds,passw,callback);
});
}
public BCryptHashCompare(passw: string, hash: string): boolean {
return bcrypt.compareSync(passw, hash);
}
public BCryptHashCompareAsynchronous(
passw: string,
hash: string,
callback: ((err: Error, isMatch: boolean) => void)
): void {
bcrypt.compare(passw, hash, callback);
}
}
EOT
***
echo '' > ./ts/M/animal.ts
cat <<EOT>> ./ts/M/animal.ts
export class Animal {
_name: string;
set name(parmName: string) {
this._name = parmName;
}
get name(){
return this._name;
}
}
EOT
***
echo '' > ./ts/M/person.ts
cat <<EOT>> ./ts/M/person.ts
import { Animal } from "./animal";
import { DataUtil } from "./../T/dataUtil";
import { cryptUtil } from "./../T/cryptUtil";
export class Person {
_crypt: cryptUtil;
_animal: Animal;
_datautil: DataUtil;
constructor() {
this._animal = new Animal();
this._datautil = new DataUtil();
this._crypt = new cryptUtil();
}
_name: string = "";
set name(parmName: string) {
this._name = parmName;
}
get name() {
return this._name;
}
echoname() {
console.log("Plaintext:" + this.name);
}
echonamecrypt() {
console.log("Crypto:" + this._crypt.BCryptHashGet(name));
}
}
EOT
***
echo '' > ./ts/index.ts
cat <<EOT>> ./ts/index.ts
import { Person } from "./M/person";
class index {
main() {
let p = new Person();
p.name = "nameperson";
p.echoname();
//p.echonamecrypt();
}
}
let idx = new index();
idx.main();
EOT
***
THEN
npm run build
node ./index.js
/home/myuser/myprojects/base/index.js:32779
throw new Error("package.json does not exist at " + package_json_path);
^
Error: package.json does not exist at /package.json
at Object.exports.find (/home/myuser/myprojects/base/index.js:32779:15)
at Object.<anonymous> (/home/myuser/myprojects/base/index.js:66705:27)
at Object.<anonymous> (/home/myuser/myprojects/base/index.js:66906:30)
at __webpack_require__ (/home/myuser/myprojects/base/index.js:20:30)
at Object.<anonymous> (/home/myuser/myprojects/base/index.js:66658:65)
at __webpack_require__ (/home/myuser/myprojects/base/index.js:20:30)
at Object.__webpack_require__.name.parmName._name (/home/myuser/myprojects/base/index.js:66594:71)
at __webpack_require__ (/home/myuser/myprojects/base/index.js:20:30)
at Object.<anonymous> (/home/myuser/myprojects/base/index.js:66573:68)
at __webpack_require__ (/home/myuser/myprojects/base/index.js:20:30)
I have this problem
node v9.3.0
npm 5.6.0
It appears you are using Webpack. Are you trying to use bcrypt in the frontend? It won't work there. bcrypt is a native module for nodejs.
Im not using it in frontend, i havent frontend its a code to learn, im learning typescript/nodejs and my webpack.config.js has target: "node".
Updated node and npm.
node --version => v8.9.4
npm --version => 5.6.0
I just want build a serverside bundle like it :
There is a bundler comparison here:
https://stackshare.io/stackups/webpack-vs-grunt-vs-backpack-vs-gulp
@Mark086 I understand your use-case. However, bundling your code will break native modules like this one.
_As a workaround, you can exclude some dependencies using the IgnorePlugin_
NodeJS native modules contains DLLs and glue code and the module initialization code loads them into the NodeJS process. For this we need the full path to the native module. We use a library called bindings to find the correct path to the native DLL.
Webpack while bundling changes those expectations (namely, the initialization code and package.json are located in the directory)
I'll take a look at the module loading code and see if it can be fixed.
Thanks a lot for the attention, i will freeze this part of my exercise and will keep learning others, and thanks for try fix it too.
I'm getting this error as well. I'm using Webpack to bundle my server side code though.
@nukeop, As I wrote above, we need the package.json to locate the native counterpart to this extension.
So _any_ bundler will break this functionality.
If you are using webpack, ignore this module using IgnorePlugin or Externals. I recommend the later.
Yep, you are 100% correct. I made the comment above so that I'll be able to find this thread the next day and share my solution to this problem for anyone visiting it in the future.
Here's the simplest solution if you want to bundle your server side code using webpack and use native modules:
target: 'node'externals: [nodeExternals()]This solves the problem. If you find that there are modules that this solution excludes that should be bundled, add them to the whitelist of nodeExternals. For example lodash requires this.
Hi @agathver, ignoring bcrypt (or all node_modules) was not a solution when you need to bundle your backend code. So it was a showstoper for me too.
I switched to https://github.com/dcodeIO/bcrypt.js#readme to solve the bundle problem.
Hi everyone, my use case involve an offline installation with an RPM package, so bundling node_modules was a no-go. Using webpack did the trick (I had to exclude tweak it a lot, like in https://github.com/ZenSoftware/bundled-nest/blob/master/webpack.config.js for my Nest application), but it works, with the exception of bcrypt. So I did like @florian-kittel, I switch to a pure JS implementation, to avoid deployment nightmare.
If you have a recipe that can bundle bcrypt without hassle, I'll be glad to read it :)
@Glandos If your deployment is an RPM, just copy the node_modules folder verbatim. You should not bundle NodeJS applications using something like webpack is an invitation to trouble. Not just bcrypt, bundling is not compatible with any module that uses native code, like pg or mongodb
In your CI or build machine, perform a clean install using npm ci and then copy the resulting node_modules together with the code. I use this method to run code using bcrypt and other native modules in production where our standard deployment is with RPM for a fleet of VMs.
[compil@centos7-nodejs]$ du -sh node_modules/
472M node_modules/
I always appreciate advice, but this is not applicable to me. I have 200 hundreds servers, some of them behind a small聽DSL line. Transferring half of a gigabyte of data for just 8MiB webpacked script is a complete waste of resource.
Of course, under XZ (used with RPM packaging), this falls under 30MiB. But the compression takes a very long time, much longer than a 20s webpack call.
By the way, I tried ncc (https://github.com/vercel/ncc) with great success: it detects the pattern of node-pre-gyp and does the compilation before bundling. Of course, in the end, you have a binary that must be compatible with the Node.js installation on your target node, but it is completely self-contained.
Most helpful comment
Yep, you are 100% correct. I made the comment above so that I'll be able to find this thread the next day and share my solution to this problem for anyone visiting it in the future.
Here's the simplest solution if you want to bundle your server side code using webpack and use native modules:
target: 'node'externals: [nodeExternals()]This solves the problem. If you find that there are modules that this solution excludes that should be bundled, add them to the whitelist of nodeExternals. For example lodash requires this.