Import packages in serverless functions

Hi Valentin:

Slightly simplified, your function handler currently looks like this:

const nodemailer = require('nodemailer');

exports.main = ({ }, sendResponse) => {
 sendResponse({
 statusCode: 200,
 body: { message: 'nodemailer contains: ' + Object.keys(nodemailer) },
 });
};

Trying to GET this lambda results in “Error: Cannot find module ‘nodemailer’”, as you observed.

This error can be resolved via webpack using a procedure as follows.

First, split this file into two files:

File 1

exports.main = ({ }, sendResponse) => {

// We'll paste the bundled webpack output right here.

};

File #2

const nodemailer = require('nodemailer');

sendResponse({
 statusCode: 200,
 body: { message: 'nodemailer contains: ' + Object.keys(nodemailer) },
});

Second, we set up “File #2” as a Node app (“File #2” is called “sendMail.js” in the following screenshot). Starting off like so:

The “package.json” file looks as follows in my case:

{
 "name": "webpack_test",
 "version": "1.0.0",
 "description": "test webpack on HS Serverless",
 "main": "sendMail.js",
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1"
 },
 "author": "v",
 "license": "ISC",
 "dependencies": {
 "nodemailer": "^6.4.8"
 }
}

While I set up “webpack.config.js” as follows:

const path = require('path');

module.exports = {
 entry: './sendMail.js',
 output: {
 filename: 'bundle.js',
 path: path.resolve(__dirname, "webpack_output"),
 },
 node: {
 child_process: 'empty',
 fs: 'empty',
 dns: 'empty',
 net: 'empty',
 tls: 'empty'
 }
};

Installing dependencies (in particular, “nodemail”) via

$ npm install --save

Third, we run webpack on this app:

$ webpack --config webpack.config.js

Webpack has now compiled the node app into a flat file “bundle.js” (as per my config file), which contains close to 1 Million characters of gibberish (i.e. compiled javascript, including all nested dependencies of the app):

Fourth and finally, we take this ENTIRE output and paste it into “File 1” (where I had placed the comment):

Now when I route a GET request to the function handler in “File 1”, I get a successfull response:

Yippieh! I hope these steps are helpful for implementing webpack with HubSpot Serverless.

NOTE:

Please note that I added

node: {
 child_process: 'empty',
 fs: 'empty',
 dns: 'empty',
 net: 'empty',
 tls: 'empty'
 }

to the webpack configuration file after seeing some rather gruesome access errors. I implemented this fix as per Modules "net" and "tls" not found when running webpack under sheets API directory · Issue #1732 · googleapis/google-api-nodejs-client · GitHub , but I haven’t checked whether I actually broke the functionality of nodemail.js this way. So this solution might need some more work, but I hope it illustrates the general approach.

Thanks to HubSpotters Mike (@mgallant23) and Derek (@dgervais), whose internal resources on this topic I have relied on in preparing this solution.

Valentin, feel free to get in touch with any further questions on this topic.