So this seems easy but has been tricky. Obviously Serverless bundles with webpack and then uploads to S3 before deploying with Cloud Formation.
The issue here is that webpack has some isues with the node __dirname, as you can read about over here: https://github.com/webpack/webpack/issues/1599
Basically that means you need to add the following to your webpack config prior to even thinking about using __dirname to grab your absolute path (just after target: node,
):
// assume target: 'node', is here
node: {
__dirname: false,
},:
So. Great. My question is:
For a Serverless project — which has multiple functions — based on the standard starter kit, what is the root directory of a given function within the base repo?
I added the above code to my webpack config, and __dirname is now working again, however I still have not been able to find the file that is packed in the repo.
Where the repo looks like this:
repo-root
——— src
——— ——— someFunction
——— ——— ——— some-sub-directory
——— ——— ——— ——— targetfile.json
What do I append to '__dirname' in order to hit targetfile.json?
Short answer:
AWS Lambda functions handler.js build / spawned by a Serverless Framework will be placed at the path: /var/task/src/hander.js
The default runtime directory for Lambda (at least Node8.10) is: /var/task
Long Answer: This was about webpack including JSON files. I was really asking the wrong question to achieve my desired result. What I really wanted to know was:
In your repo that /src directory (probably — if you are using the default Serverless project structure) contains your handler.js file and is the reference point (first directory to be copied in from your serverless project) from your Repo — nothing above that src directory is copied in.
That said trying assuming that your local file / folder structure looks like this:
repo-root
——— src
——— ——— someFunction
——— ——— ——— some-sub-directory
It is important to remember that the serverless AWS Lambda file structure will look like this (by default):
——— src
——— ——— handler.js
——— node_modules
Notice there is nothing else there (by default) beyond your handler.js file.
No subdirectories no nothing. This is because webpack has not been told to include the JSON file (which takes some work).
The first thing that is required is to include / require / reference your json file from within your code base. This lets webpack know that you will need it later:
let file = require('./some-sub-directory/targetfile.json');
If you don't properly require the JSON file it won't make a difference what location you point to it won't be there. Another more 'Hacky' option would be to just rename your JSON file to .js and then include via the same process.
Just including the JSON file (in my case) did not trigger webpack to actually include the file in the bundler. I also needed to add the webpack file-loader: https://www.npmjs.com/package/file-loader
And then add the following to my webpack config — under rules (it would be slightly different for webpack 4):
{
// type: 'javascript/auto', // this would be for webpack 4
test: /\.json$/,
use: [
{
loader: 'file-loader',
options: {
name: "./src/mypackedfiles/[name].[ext]"
}
}
]
}
More details can be found over here: https://github.com/webpack/webpack/issues/6586#issuecomment-379448638
Keep in mind that just including the file DOES NOT parse the values that are enclosed in that file — it only tells webpack to include it so that you can then read it locally from the Lambda using fs
or some other method.
The key here (if you were trying to get a json file included / accessible to a Serverless AWS Lambda function like I was) is to realize that this is really more of a question of webpack than it is of Lambda pathing.
For that reason the best way to trouble shoot / find your file is just to build your function and then un-zip the file it creates to see if your json has been properly included.
Once it has been included — THEN you can use the above mentioned settings with __dirname to track down and actually utilize that file.
Based on the above webpack configuration your directory structure (within your zip) would look like this:
——— src
——— ——— mypackedfiles
——— ——— ——— targetfile.json
——— ——— someFunction
——— ——— ——— some-sub-directory
——— node_modules
So with that in mind your reference to the json file added by webpack would now look like this:
let filelocation = __dirname + '/mypackedfiles/targetfile.json'
You could now access filelocation from fs
or whatever parser you want as it is properly included in your serverless lambda.
Note for Multiple Functions within one Repo: With this method the json file will be copied into EVERY function that is spawned by your repo. This may or may not be a good thing for you but it works fine for me since my JSON files are not overly huge.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With