mde / ejs

Embedded JavaScript templates -- http://ejs.co
Apache License 2.0
7.7k stars 841 forks source link

Can ejs.renderFile use 'layouts' #681

Closed webdpro closed 1 year ago

webdpro commented 2 years ago

This is a question on EJS and the renderFile.

Currently, with the regular ejs.render we use a 'layout' file, then our 'template' of the page is injected into the body of that layout file. However, with renderFile, it seems to only take the 'single' file with passed arguments to render that file.

The question is, can you actually use the 'layout' file, or is the idea to use a single 'file' vs the 'layout'?

Just to add to this question and maybe get some thoughts on this. Basically, what we are looking to do is pass the rendering to a 'worker' thread. The main reason for this is to prevent 'blocking' during the page request. As it stands right now, many of our pages pass over an object returned from the DB where we then loop over the results. While this does work, we noticed it blocks the EL.

We then used the async await functions of ejs however it was kind of a mixed bag where the blocking did seem to go away, however, if you had a heavy loop it still would block the EL (not surprising)

This moved us into the direction of using a worker_thread to process the page using a worker pool.

The general flow of this process is to

1) Pass our data to the worker 2) Inside the worker we call the EJS renderFile 3) Pass the HTML back from the worker 4) Route returns the HTML as a res.send(html)

We have this partially working, in regards to returning the main content are (minus the layout, hence the first part of the question)

Doing it this way allows the blocking to be a non-issue and with our internal testing we can have a 'long' running loop inside the template that does not impact the EL and other users.

The second part to this question is, any downside to doing this with workers? And if layouts are not supported with the renderFile, would just constructing it as 'partials' be the best option, so we would have

1) Template file 2) Inside template file use 'includes' for {header} mainPageData {footer} ?

For more clarity on the app, it currently is deployed in containers and we don't see any resource starvation and the EL blocks are small, like 30 MS, however under load that is still not ideal, so off loading that so it does not impact other users is the goal here.

Anyhow, maybe we missed something and this is the totally wrong approach but wanted to see if anyone else experienced things like this and worked around it etc.

KalanaPerera commented 1 year ago

Did you able to find any solution? experiencing same

webdpro commented 1 year ago

We did.

Basically what we did is

1) Create a Worker Pool and the main Worker. 2) We create the Worker as a module that accepts 3 parameters Type, Template, and Data 3) The module then awaits the ejs.renderFile, passing both the 'template' and 'data' data being the data we wish to pass, e.g DB respons etc. and the template being the actual EJS template file (view).

As an example, our route looks like this

wt.run( { type:"page", template:"path/to/view/index.ejs", data:{ //data object },

}).then(data=>{
res.send(data);

});

So, here we have our module wt, we pass over the parameters and wait for it to finish processing the file, and because the WT returns the rendered file we simply wait for that and send the data once completed.

If you use 'includes' in your template, you will need to 'await' them so, for example

Typically, you would do something like

<%-include('../../../partials/header');%>

This will not work with render file, so you will need to 'await' those partials like

<%-await include('../../../partials/header');%>

On Sun, Feb 5, 2023 at 4:50 AM Kalana Perera @.***> wrote:

Did you able to find any solution? experiencing same

— Reply to this email directly, view it on GitHub https://github.com/mde/ejs/issues/681#issuecomment-1417749724, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJT5SO22OI3HFEL2BDLYF3WV6OZPANCNFSM5ZCHWYEA . You are receiving this because you authored the thread.Message ID: @.***>

mde commented 1 year ago

Thanks for circling back to respond on this. This is a great solution. Closing this issue.