EJS include file relative to project root

后端 未结 2 384
北海茫月
北海茫月 2021-01-02 03:43

I am using Express and EJS to build a site and I have a directory structure somthing like:

+--www/
  |
  +--partials/
  | |
  | +--header.ejs
  | +--(a bun         


        
相关标签:
2条回答
  • 2021-01-02 04:14

    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:

    1. Get the root from the initial file (where express is instantiated)
    2. Put that into a variable
    3. 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

    1. __directory
    2. path.dirname(require.main.filename);
    3. 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:

    1. Creating a middleware to pass variables in response.locals
    2. 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();
    });
    
    1. 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 %>
    
    0 讨论(0)
  • 2021-01-02 04:24

    Looks like this is not supported by EJS however i found a workaround for this problem. In the above setup the pain point is for all partial files you need to mention the relative paths and if you refactor code that becomes more pain. So rather mentioning the relative path at every include i declare a variable rootPath once, and there i give the path to reach home. So that at every include i can simply mention the relative path just like path from root.

    For example in guide/index.ejs i mention the following in top of the ejs file

    <% var rootPath = '../'; %>

    and and code in ejs file looks like below

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

    Your HTML code

    <%- include(rootPath + 'partials/footer'); %>

    So in case i refactor index.ejs to some other folder all i need to do is change the value of rootPath

    0 讨论(0)
提交回复
热议问题