Enigmatic-Smile / serverless-plugin-optimize

⛔️ DEPRECATED ⛔️ Bundle with Browserify, transpile and minify with Babel automatically to your NodeJS runtime compatible JavaScript
https://www.npmjs.com/package/serverless-plugin-optimize
MIT License
130 stars 53 forks source link

Access static files (templates) #32

Closed hlegendre closed 7 years ago

hlegendre commented 7 years ago

Hi,

I am trying to deploy a serverless function that requires access to liquid templates. I managed to include the static files in the bundle through the "includePath" config parameters but I am unable to get a path to them.

This is because the node process calling the handler is not in the same folder as the handler itself. Hence I cannot find a path to the handler (that I can then prefix to the path of my templates) to fs.readFile them... I tried using __dirname, but Browserify changes it while bundling to the path at the time of compilation...

Would you have any idea of how to make it work, please ?

PS: I explored the https://github.com/JohnPostlethwait/stringify way but I cannot define additional transforms to browserify in serverless-plugin-optimize, can I ?

BR,

Hugues

goncaloneves commented 7 years ago

@hlegendre did you try relative paths?

hlegendre commented 7 years ago

@goncaloneves yes. That's what I tried first. But the node process is launched from /var/task whereas the handler.js file is in a deep folder _optimize/XXX/. Therefore any relative path is relative to /var/task and not the handler.js containing folder... And I don't know beforehand this folder.

goncaloneves commented 7 years ago

You need to have the optimize prefix at the lowest level same of your source.

I am still not visualizing your project structure but if you follow SLS recommendation it should work fine.

About Browserify transforms is a no.

Right now I dont have time for features in my hands, if you have the will and find a solution for your problem I welcome you to do a PR. 😎

hlegendre commented 7 years ago

I don't think the structure of my project has an impact since your plugin optimizes everything (except the textual templates I include as well) into a single js file. The output is therefore something along

/_optimize/xxx/handler.js
/_optimize/xxx/templateFolder/*.liquid

where xxx is the name of the function.

I did not want to rely on opening the liquid files through /var/task/_optimize/xxx/templateFolder/yyy.liquid because I need to specify the name of the function in the routine opening them and this would not allow me to use templates with several function (I would not know which xxx to chose).

I was hoping there would be a way to get the path to handler.js directly from the lambda function but process.cwd() is /var/task and __dirname gets replaced by Browserify by the local path at the time of bundling.

I guess there is no apparent way to do it. I'll probably try something dirty like exploring the /var/task folder which should contain only on subFolder, named as my function...

Regarding the PR, I do not know much about Browserify so I am not sure I would be able to help but I'll have a look.

Thanks anyway.

goncaloneves commented 7 years ago

You said you tried using relative paths, I recommend you try again.

In your structure is easy to call any template file from within your lambda just using ./templateFolder/file.liquid. Why do you need full path? Using relative paths in relation to your handler file should be enough.

Then add the same liquid file with includePaths and it will be included creating the same folder structure you have before bundling.

If this is not enough and only solved by full path then you need to hack lambda runtime path + optimize prefix + your file path.

hlegendre commented 7 years ago

Since everything is "optimized" by your plugin, I get a single handler.js file which is then deployed to /var/task/_optimize/${functionName}/handler.js

Any additional folders I chose to copy using the includePaths options gets copied to /var/task/_optimize/${functionName}/ as well. But the handler.js file is "required" (or launched) by AWS Lambda from the /var/task/ folder. Therefore any fs.readFile with a relative path looks for the file from this folder and not from the handler.js folder.

I would not have problems with require directives since node handles this well (path is relative to the script file having the call and not the CWD). I have problems with fs.readFile.

I managed to make it work by using path.resolve(process.env.LAMBDA_TASK_ROOT, '_optimize', process.env.AWS_LAMBDA_FUNCTION_NAME, p) to get the full path when I am on AWS Lambda.

goncaloneves commented 7 years ago

Hugues that's perfect. 3 issues opened about this and you brought the solution. 👍

I will add this information to the readme file.

hlegendre commented 7 years ago

you're welcome !

ro-savage commented 6 years ago

For anyone looking at this, remember that if you are using subfolders the asset will get deployed to them and that needs to be taken into account.

E.g.

  myLambda:
    handler: mySubFolder/myLambda.handler
    optimize:
      includePaths: ['mySubFolder/myFile.json']
path.resolve(process.env.LAMBDA_TASK_ROOT, '_optimize', process.env.AWS_LAMBDA_FUNCTION_NAME, 'mySubFolder/myFile.json')
GoChartingAdmin commented 6 years ago

Do we include the below line in serverless.yml?

path.resolve(process.env.LAMBDA_TASK_ROOT, '_optimize', process.env.AWS_LAMBDA_FUNCTION_NAME, 'mySubFolder/myFile.json')

And what if my function depends on multiple json files?

ro-savage commented 6 years ago

@GoChartingAdmin, that is the line you include when importing it into the serverless function.

e.g.

const path = require('path')
const myJson = require(path.resolve(process.env.LAMBDA_TASK_ROOT, '_optimize', process.env.AWS_LAMBDA_FUNCTION_NAME, 'mySubFolder/myFile.json'))