简体   繁体   中英

express-handlebars isn't finding my layouts or partials

I have the following Express 4 view engine setup:

var handlebars = require('express-handlebars').create({
  layoutsDir: path.join(__dirname, "views/layouts"),
  partialsDir: path.join(__dirname, "views/partials"),
  defaultLayout: 'layout',
  extname: 'hbs'
});

app.engine('handlebars', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));

I have the following file structure:

/views
    error.hbs
    index.hbs
    /partials
        menu.hbs
    /layouts
        layout.hbs

And finally in my route: res.render('index');

And visiting my site, it loads only my index.hbs template. It does not use my layout.hbs . I don't get any errors or anything. It just doesn't use the layout even though layout is set as my default layout in the handlebars config.

Next I tried to change my code to this:

res.render('index', {layout: 'layout'});

Now I get the error:

Error: ENOENT: no such file or directory, open '/.../views/layout.hbs'

So it's like it's not finding my layoutsDir ... What am I missing here?

Next I changed it to this:

res.render('index', {layout: 'layouts/layout'});

Okay so that worked. My layout is now loaded. But then I added in a partial to my layout:

{{> menu }}

Now I get: /.../views/index.hbs: The partial menu could not be found

So what is going on here? How come Handlebars isn't recognizing my layoutsDir or partialsDir ? It's just not seeing them at all or something. And how come defaultLayout wasn't being used? I had to specify the layout.

According to the API documentation for express-handlebars if you are changing the file extension from the default .handlebars then when you set the view engine, all occurrences of handlebars should be replaced with the new extension you wish to use.

So your express setup will need to be updated to:

app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));

Note: the documentation uses a period before the extension eg .hbs but it seems to work without this.

Full code:

var path = require('path');
var express = require('express');
var app = express();
var http = require('http').Server(app);

var handlebars = require('express-handlebars').create({
  layoutsDir: path.join(__dirname, "views/layouts"),
  partialsDir: path.join(__dirname, "views/partials"),
  defaultLayout: 'layout',
  extname: 'hbs'
});

app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));

app.get('/', function(req, res){
  res.render('index');
});


http.listen(3000, function(){
  console.log("Server running");
});

In the new handlebars in your use partials you dont have to include its directory in server.js

  • The partials are included in "express-handlebars"
  • The first line in view engine setup is responsible for the above

Take note of these.

    const hbs = require('hbs');
    const expressHbs = require('express-handlebars');

//view engine setup
     app.engine('.hbs', expressHbs({ defaultLayout: 'layout', extname: '.hbs' }));
     app.set('view engine', 'hbs');
     app.set('views', path.join(__dirname, '../views'));
     app.use(express.static(path.join(__dirname, '../public')));

Try to use wildcard on your Dependencies to make sure you match the latest version

"dependencies": {  
    "express": "*",
    "express-handlebars": "^3.0.0",
    "hbs": "*"
  },

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM