This is a very good question, it's one I had myself until very recently.
Really there appears to be no direct & central way to get the web root... it's just not something the node nor the express developers thought was valuable it seems.
However there are a few tools made available that can help but won't directly solve the problem.
GENERAL APPROACH:
- Get the root from the initial file (where express is instantiated)
- Put that into a variable
- Get that variable out to your templates
METHOD ONE - globals
The first work around I found is passable.
It utilizes the ability to set a variable to the global scope.
It's not ideal but if you want to see more click HERE.
IMPORTANT:
All of the below require that in the main file of your express app (the one that instantiates the express app) you set a variable to the current working directory.
The three ways I know of are
- __directory
- path.dirname(require.main.filename);
- path.resolve();
I believe there is an advantage to the second method but I don't remember what it is currently... also I'm not sure it works in the latest (14.x) version of node... I started changing over to 3 once I started using 14.5...
METHOD TWO - passing variables
The second workaround I think is the worst... it will work but may become untenable if you have anything less than a simple setup.
This method is to pass the variables through your routes.
this would look like:
router.get('/', (request, response) =>
{
response.render('PATH TO TEMPLATE', {dataItem1: 'DATA STUFF TO PASS', dataItem2: 'MORE STUFF'});
});
METHOD THREE
This is definitely the method I prefer.
It makes it easier, simpler, and more clean.
There are really two methods here but they are very similar.
This method is utilizing either app.locals OR response.locals.
When I say app I mean the instance of express, (whatever you called it).
So this is as simple as:
- Creating a middleware to pass variables in response.locals
- Setting variables directly on app.locals
Examples:
const appDir = path.dirname(require.main.filename);
app.use((request, response, next) =>
{
response.locals.someVar = 'value of someVar';
response.locals.appDir = appDir;
return next();
});
app.locals.appDir = path.dirname(require.main.filename);//const path = require('path');
In both cases the values are simply available in EJS templates.
So using them would look like:
<%= appDir %>