Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node cant find package.json file #573

Closed
Mark086 opened this issue Jan 20, 2018 · 15 comments
Closed

Node cant find package.json file #573

Mark086 opened this issue Jan 20, 2018 · 15 comments

Comments

@Mark086
Copy link

Mark086 commented Jan 20, 2018

Im very new to Node and is possible its just my lack of knowledge, in that case Im sorry, I opened the issue nodejs/node#18267 thinking it was a node bug but the issue grpc/grpc#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' */

/* <node_internals>/path.js [ {function=path.resolve} line:1174] */
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 */

@recrsn
Copy link
Collaborator

recrsn commented Jan 22, 2018

Can you provide exact steps or script to reproduce this?
Also mention nodejs and npm versions.

@Mark086
Copy link
Author

Mark086 commented Jan 22, 2018

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

tsc
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)

@oasis1992
Copy link

I have this problem
node v9.3.0
npm 5.6.0

@recrsn
Copy link
Collaborator

recrsn commented Jan 24, 2018

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.

@Mark086
Copy link
Author

Mark086 commented Jan 24, 2018

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 :

https://hashnode.com/post/is-there-any-reason-to-bundle-server-side-code-with-webpack-cja6i7ygs05a5xpwuitg0fu7r

There is a bundler comparison here:
https://stackshare.io/stackups/webpack-vs-grunt-vs-backpack-vs-gulp

@recrsn
Copy link
Collaborator

recrsn commented Jan 25, 2018

@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.

@Mark086
Copy link
Author

Mark086 commented Jan 25, 2018

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.

@Mark086 Mark086 closed this as completed Jan 25, 2018
@nukeop
Copy link

nukeop commented Apr 3, 2018

I'm getting this error as well. I'm using Webpack to bundle my server side code though.

@recrsn
Copy link
Collaborator

recrsn commented Apr 4, 2018

@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.

@nukeop
Copy link

nukeop commented Apr 4, 2018

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:

  • Install webpack-node-externals
  • In your webpack config, add the following entries:
    • 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.

@florian-kittel
Copy link

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.

@Glandos
Copy link

Glandos commented Feb 2, 2021

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 :)

@recrsn
Copy link
Collaborator

recrsn commented Feb 2, 2021

@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.

@Glandos
Copy link

Glandos commented Feb 2, 2021

[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.

@Glandos
Copy link

Glandos commented Feb 3, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants