Bundling and tree-shaking node_modules into a single file - node.js

I'm trying to create an AWS Lambda Node 8 Application. I realise you shouldn't try to do npm install on Lambda, and instead upload a zip containing your scripts and the node_modules folder. However, the zip is over 7MB and contains a lot of dead-code that I'm not expecting to be run (for instance, node_modules\node-sass\src contains a load of c++ files which I don't think is called through node?).
I know that 7MB isn't "large" but this is just a sample application to test the waters to use Lambda and I want to nail down the concepts :). Also, to avoid confusion: the application is to compile sass on the fly, so I am trying to deploy libsass/nodesass. I know it's usually a build-time only tool!
I've tried using backpack to bundle my scripts, since it claims to create a single main.js file. It does create a file with a lot of external code, which looks like code from node_modules, but it doesn't work when run in a clean folder.
Error: Cannot find module 'fs-extra'
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.module.exports.exports.__esModule (C:\Dev\fsdf\sass-compiler\main.js:3192:18)
at __webpack_require__ (C:\Dev\fsdf\sass-compiler\main.js:21:30)
at Object.<anonymous> (C:\Dev\fsdf\sass-compiler\main.js:7837:16)
at __webpack_require__ (C:\Dev\fsdf\sass-compiler\main.js:21:30)
at Object.module.exports.Object.defineProperty.value (C:\Dev\fsdf\sass-compiler\main.js:7820:18)
at __webpack_require__ (C:\Dev\fsdf\sass-compiler\main.js:21:30)
The only way I can make it work is to use zip up the entire node_modules folder and the main.js file. However, this produces an 8MB zip since main.js is considerably bigger than my 3KB source code!
Have I missed something, or is simply impossible to avoid zipping up node_modules? My theory is that it should be possible since Webpack doesn't need node_modules in the browser.

Related

Cannot find module app.js?

I am starting node app.js in the server directory, and I get the following:
module.js:544
throw err;
^
Error: Cannot find module 'server/server/app.js'
at Function.Module._resolveFilename (module.js:542:15)
at Function.Module._load (module.js:472:25)
at Function.Module.runMain (module.js:682:10)
at startup (bootstrap_node.js:191:16)
at bootstrap_node.js:613:3
[nodemon] app crashed - waiting for file changes before starting...
How to fix this? It was working before, and now it's looking for a weird path /server/server instead of just /server.
I just reinstalled node to a more up-to-date version, from 5. to latest stable.
Most likely you try to load your module like so:
require('server/server/app.js')
Node.js then tries to find it somewhere below node_modules. But I suppose, the file is not a dependency but part of your own code. Normally, you would then require it like so (consider the point at the beginning):
require('./server/server/app.js')
This makes Node.js look for the file beginning at the current directory ('.').
This would work in an environment with the following folder structure:
/myfiles/main.js <-- this file contains the `require` statement
/myfiles/server/
/myfiles/server/server/
/myfiles/server/server/app.js <-- this file is being `require`d
I encountered with this issue because I deleted build folder and then try to build the project.
Solution - in my case
I run the tsc --watch that compiled all .ts files to .js
maybe you want to access file app.js,
require('./server/server/app.js')
// to be like this
require('server/server/app.js')
use can using this package
npm i app-module-path

ElasticBeanstalk nodejs.log can't find module 'hogan.js'

I have a simple node.js app that is using "hogan": "^1.0.2" (from packages.json under "dependencies").
It has been failing to deploy, and looking in the logs, I am seeing (multiple times):
Error: Cannot find module 'hogan.js'
at Function.Module._resolveFilename (module.js:325:15)
at Function.Module._load (module.js:276:25)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
I'm fairly new to node.js on EB, and have just been following http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_express.html with a pre-existing Express app.
Assuming EB runs npm install for me (is that a safe assumption?), what might the issue be?
I was using "hogan": "^1.0.2" instead of "hogan.js": "^3.0.2", which worked locally but not on EB.
hogan is just an unofficial alias someone made to hogan.js.
I do not get hogan.js errors any more after making the switch.
For what it's worth, I also had an issue similar to this and determined that it was due to file case issues. In the node EB container, the OS is case-sensitive, and because I was ignoring file case changes in git, it didn't update the file casing in the repository.
You should run git config core.ignorecase false if this is the issue.
You might also change "hogan": "^3.0.2" to "hogan": "*" because EB does run npm install for you. If EB can't find the specific version with "^", it might not install the package as you did locally. Also you might check your file structure before you do eb create or eb deploy. You might include something unnecessary if you are using the command line. I suggest that you create an application.zip file with files you need, such as package.json, app.js and index.html and upload it through GUI. Don't ever pack up node_modules in your .zip file, that's troublesome.

How to load node modules in beaker notebook?

I'm using beaker notebook and would like to use some external node modules - yet because beaker doesn't change the system path to the directory of the currently active file, my attempts to include stream-filter are met with the error:
Error: Cannot find module 'stream-filter'
Error: Cannot find module 'stream-filter'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:286:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at eval (eval at processCode (/opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/app.js:45:23), :5:14)
at processCode (/opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/app.js:45:18)
at /opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/app.js:32:28
at callbacks (/opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/node_modules/express/lib/router/index.js:164:37)
at param (/opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/node_modules/express/lib/router/index.js:138:11)
at pass (/opt/homebrew-cask/Caskroom/beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/node_modules/express/lib/router/index.js:145:5)
I'm wondering how to solve this problem. I tried process.chdir('/Users/akivalipshitz/Developer/Computational_Linguistics') to no avail, even though stream-filter is installed in node_modules in the same directory.
So how do people use node modules
The context where the node code is eval'd is in your case
/opt/homebrew-cask/Caskroom//beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/app.js
So require() looks for a module in the node_modules folder there and then recursively up along the parent folders (see docs).
One solution (if you're only working on one project or use this module frequently across all your projects) would be to install your module there:
cd /opt/homebrew-cask/Caskroom//beaker/1.4.2-1-ge55c059/Beaker.app/Contents/Resources/dist/config/plugins/eval/node/app/
npm install stream-filter
Another (ugly) approach could be to build a long relative path in your require(). In your case something like:
require('../../../../../../../../../../../../Users/akivalipshitz/Developer/Computational_Linguistics');
Both cases it would mean that your code is not portable to another beaker instance. However, at least until a better solution is proposed this could get you along prototyping.
as of this writing, the current version of Beaker allows you to import npm modules right from the GUI. Just click notebook -> Language Manager -> Javascript, then type the module names into Loaded Libraries. Beaker autocompletes from the npm registry.
This works both in the electron client and the cloud hosted version.

Sudo node server return error, OsX

There is the case:
mac:~ username$: sudo node server
module.js:340
throw err;
^
Error: Cannot find module '/Users/username/server'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
So here is 2 questions:
How to specify modules folder in node.js(node on my machine is taking place on /usr/local/bin/node); may be u could give me a advice how I may organise my project files.
How could I prevent this type of errors in future? What could I read about it?
I think you don't get what exactly Node will do with your command.
With this command, Node is trying to load a script file (in your current folder) with no extension named server.
It looks like this file doesn't exist in your current directory.
Let's take a simple example: you have a file named app.js in your current folder which contains a simple output in the console.
// In the app.js file
console.log("Output in the console by NodeJS");
Now, run the command node app.js. You should have the output in your console.
Talking about organisation, it depends of your workflow and projects. You could find lot of informations about this by reading the source code of popular projects on Github.

"Error: Cannot find module 'less'" Node.js module loading preference/order/cache?

Here's the situation… So I've created a Node.js module that acts as an interface to some Node.js template engines, Shift.js. That is included inside another Node.js module, Design.io (it's specified Design.io's package.json dependencies block). Design.io watches files for changes.
Then you build an app and require('design.io'). You also install, say, Less and Stylus into your project.
This way, when you save a .less or .styl file, a chain of methods are called:
require("design.io") gets notified of the filesystem event. Design.io then calls
require('shift').render(string, extension, callback). Shift.js then calls
require(moduleFor(extension)) # require("less"). The string is compiled.
In my app (current working directory) I have installed less and stylus:
npm install less stylus
The problem I'm having is, in step 3 which is called from within the Shift.js module, I get errors like this:
Error: Cannot find module 'less'
at Function._resolveFilename (module.js:334:11)
at Function._load (module.js:279:25)
at Module.require (module.js:357:17)
at require (module.js:368:17)
at Less.engine (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift/less.js:6:14)
at Less.render (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift/less.js:18:21)
at /Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift.js:69:23
at /Users/viatropos/Documents/git/plugins/design.io/node_modules/async/lib/async.js:118:13
at Object.forEachSeries (/Users/viatropos/Documents/git/plugins/design.io/node_modules/async/lib/async.js:134:9)
at Object.render (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift.js:78:31)
My question is, why is this happening? I thought that you could dynamically require libraries from a module as long as they were installed somewhere… What am I missing?
The goal would be that libraries like Shift.js wouldn't have to define every single dependency in package.json… For an "interface to the template engines" library, that would require too many dependencies that the app would probably never be using.
Thanks for the help, hope that was somewhat clear.
When you npm install foo, the foo module gets installed in a directory named node_modules in the current working directory.
When you install this shift library, it only looks for modules to require within its own node_modules directory, or in one of the global directories require.resolve() searches.
And that's the simple solution to your problem:
npm install -g less
And then the library is globally visible to all Node.js code on your computer, rather than only being visible to code in the current working directory.
Alternatively, if you only want shift to see it, then do something like this:
npm install shift
cd node_modules/shift
npm install less

Resources