-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
browserify not working for node apps #696
Comments
@doapp-ryanp I'm still a little unclear on how you intend to use your browserify-ed code inside of AWS Lambda. Lambda requires the function to export a top level CommonJS module. That being said, browserify-ing the SDK for use in Node.js is currently not supported, because we rely on the Would you be able to explain a use case a little more? I'm curious about why uploading an archive of Node.js modules is not working well for you. |
@AdityaManohar I have broswerfied code that is working just fine in lambda. You can export top level CommonJS method. The bummer is the only node module I have not gotten to work so far is aws-sdk. If your curious on how I'm doing this, take a look at the JAWS code I wrote. I wan't to be able to bundle up aws-sdk so I'm not restricted to the version that is included in lambda (2.1.35 is already backlevel). Because its not browserify compatible, I have to As for the use case for bundling - first some background: I'd like to start out by saying I love lambda+api gateway. It is a game changer. With that said the cold start lag times make it un-useable as a production webservice/api layer. I define cold start as: 1st call after initial creation (brand new lambda, or contaner that has been provisioned due to load) OR 1st call after being frozen from inactivity (currently ~5mins). I know this is a extremely difficult problem to solve at scale (and the problem is worse in Java lambdas currently). I (and co-workers/friends) have had discussions with lambda and api gateway engineers and I know they are working on improving the cold start issues. I'm aware this issue is not the forum to address the problem - but you must understand the background in order to understand my use case. With this in mind, the nature of the product (containers launching + grabbing code, containers being unfrozen etc) it is of paramount importance that the following conditions are optimized as much as possible to cut down on cold start times:
So my use case is to leverage build/bundle tooling like browserify/systemjs + uglifyier/minifier. I want lambda+api gateway to be a successful production grade product. With AWS's track record I think it will become just this. Cutting every ms of lag time off that can be done with a reasonable amount of work, will go a long way in making it successful. IMO most lambda code that uses the aws-sdk will only be using a fraction of its codbase - supporting a popular tool like browserify to remove the un-used code is a reasonable request. I know its more work, but with AWS's investment in lambda, maybe now is the time to invest more resources in the aws-sdk to separate it into sdk for browser and sdk for node. My hunch is this will not only make it easier for tools like browserify/systemjs to work, but it will also allow for some optimizations that will improve its efficiency in lambda. Sorry this was so long winded, hard to convey this problem and use case concisely |
@doapp-ryanp Thanks for the explanation! This definitely helps understand your use case better. I did some investigation and I was able to reproduce the problem with a rather trivial use case: // log.js
var log = function() {
console.log(process.memoryUsage());
};
module.exports = log; // source.js
var log = require('./log');
log(); Browserify-ing the source file still throws the same error $> browserify source.js --dg --no-builtins --no-commondir > bundle.js module.js:338
throw err;
^
Error: Cannot find module '_process'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at s (/Users/aditm/dev/code/bundle.js:1:176)
at /Users/aditm/dev/code/bundle.js:1:367
at Object._process (/Users/aditm/dev/code/bundle.js:16:14)
at s (/Users/aditm/dev/code/bundle.js:1:316)
at /Users/aditm/dev/code/bundle.js:1:367
at Object../log (/Users/aditm/dev/code/bundle.js:2:11) It also looks like we only depend on the Hope this helps! |
Nope it does not work. In my continued digging, turns out there is a way to insert global vars, which gets around the However this exposes another problem. api_loader.js does Not quite sure why I asked in that issue a week or so ago for some clarification. What am I missing here? Here is my browserify code:
Here is output from lambda (as expected __dirname is replaced during browserify):
|
The I hope this helps clarify things! |
thanks that helps clarify how What needs to be done for browserify to correctly include metadata.json (and other json) files in |
The problem here is that, due to the way the SDK is loaded (you just Is size on disk correlated to cold start time? It's worth noting that although there's a bit of data on disk, that data is not actually loaded until a service is constructed, so it does not impact |
@doapp-ryanp also, if this really is an issue going forward, you might want to consider relying on the system-wide install of aws-sdk in Lambda, since that's always present and never requires an install-- and is kept fairly up-to-date. It might be worth elaborating why this is a blocker for you; the Lambda team would certainly be interested in knowing. |
@lsegal thanks for the clear explanation.
This does indeed seem to be the case. Ignoring runtime all together, larger the file the longer it takes to get into the container that Lambda creates. Leads to slower initial provision and provisioning of said container when scaling out. I know we are only talking about 500k here zipped for the aws-sdk, but since most npm mods work with browserify we figured it was a reasonable optimization step to run to shave every ms off of lambda start times that we could.
Relying on the system-wide install of the aws-sdk, and the single nodejs version currently supported in lambda is a blocker because:
I created this forum post back in May on this subject. Have not been given a clear direction on how Lambda team is going to handle these issues. |
I can't respond to any of these with authority (you might want to ping your forum thread and get an official response from the current SDK maintainers), but from experience I can say that: Security: if there was some kind of security patch going out with the SDK it's extremely likely that this release would be synchronized with Lambda's update of their version. AWS takes security patches very seriously, you're unlikely to see a significant delay when it comes to this stuff. Backwards compatibility: The SDK follows Semantic Versioning. Going from 2.1 to 2.2 is not an incompatible update; only 2.x to 3.x. Lambda would NOT upgrade their SDKs from 2.x to 3.x if it involved breaking changes; that would break all of their existing users. I know from experience that AWS takes backwards compatibility very seriously, and so does this SDK. For the rest you might want to get an official answer. Hope that helps! |
Thanks for the prompt response. Re: backwards compat: As it stands today, lambda only supports ONE version of aws-sdk and one version of Node.js. My point was more that this architecture decision in a node runtime is significantly flawed. I will indeed continue to try to take it up with them, however it is also in your best interest for them to support multiple because as it stands now you will never be able to release a v3. This same logic applies for node.js runtime. It will cripple the ability for the product to move forward at the speed the node ecosystem requires. Just for completeness sake, I am aware I can bundle my own (non browserified) version of aws-sdk and I can even bundle my own version of node/io.js. Both will increase the bloat (discussed before) and bundling the runtime as it stands today is a hack and has a CGI style interface (wont go into that discussion here). |
Node.js 4.3 is now available in Lambda so you can leverage ES6 features in your Lambda functions, and Lambda does update its default version of the aws-sdk on a regular basis. While this does not resolve SDK's incompatibility with |
If you still would like to bundle the latest version of the SDK to use in Lambda and not use the default version of the SDK pre-installed in Lambda, you can zip your directory that contains both the code for your Lambda function and a If file size is a concern, there are folders and files you can delete from |
@doapp-ryanp Here's an example of a quick and dirty module: // handler.js
var S3 = require('aws-sdk/clients/s3');
var handler = function() {
var s3 = new S3();
s3.headObject({
Bucket: 'BUCKET',
Key: 'KEY'
}, function(err, data) {
console.log(err, data);
});
};
module.exports = handler; Running Let me know if this helps with your development! I'll update again once this feature is in master. |
@chrisradek this is awesome!! This is a big step forward for NodeJS based Lambda's. Thank you for not forgetting about this issue. What version release of the SDK do you anticipate this making it into? @ac360 @flomotlik @eahefnawy heads up ^ |
The PR was just merged and released as part of |
sweet. appreciate you getting it in a release so quick. I'll roll this into one of my projects here soon (week or 2) and report back. |
@chrisradek sorry it took so long for me to get to this, but I have just tested the It is producing super small code sizes. This functionality will now allow me to stay up to date with the most recent Great work!! ps - this issue can be closed IMO |
@doapp-ryanp |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread. |
Trying to browserify my node code for use in lambda to help combat the cold start issues (which also raises the ceiling on the hard 50MB zipped limit).
Is browserfying for node not supported? Ultamately I'd like to just use the
--node
browserify option, but its not working.Ex: (I wont be hard coding creds, this is just for ease of reproduce.)
If I run
browserify bundletests.js > bundled.js
then runnode bundle.js
I getXMLHttpRequest is not defined
which is expected since I'm not running in the browser.So I run
browserify bundletests.js --dg --no-builtins --no-commondir > bundled.js
to not use the builtins and I getAny ideas?
The text was updated successfully, but these errors were encountered: