Error: ENOENT: no such file or directory in express-handlebars

Viewed 13181

I am using express-handlebars to load dynamic content in NodeJS

inside app.js

const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const pp = require("./util/path.js");
const adminRoutes = require("./routes/admin");
const shopRoutes = require("./routes/shop");
const expressHbs = require("express-handlebars");
const app = express();

app.engine("hbs",expressHbs());
app.set("view engine", "hbs");
app.set("views", "views");

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "public")));

app.use("/admin", adminRoutes.routes);
app.use(shopRoutes);

app.use((req, res, next) => {
  res.status(404).render("404", { pageTitle: "Page Not Found" });
});
app.listen(3001, "localhost", () => console.log("Listening on 3001 PORT"));

When expressHbs() function has no param it shows the following error

Error: ENOENT: no such file or directory, open 'C:\dev\nodejs\maximi_course\views\layouts\main.handlebars'

And when i pass an option object to it:

app.engine(
  "hbs",
  expressHbs({
    extname: "hbs",
    layoutsDir: path.join(__dirname, "views")
  })
);

It shows:

Error: ENOENT: no such file or directory, open 'C:\dev\nodejs\maximi_course\views\main.hbs'

I've searched for a solution but i got no result , Actually i am following a tutorial and i have done the same as teacher did but i got an error.

Lastly thing that i have tried is adding defaultLayout property and it works and load the default but when i change the url to another page it always load the same page which i set as default

Here is project folder and all its contents

Directory

10 Answers

I had the same problem and fixed it by using the following method:

app.engine(
  "hbs",
  expressHbs({
    extname: "hbs",
    defaultLayout: false,
    layoutsDir: "views/layouts/"
  })
);

express-handlebars.js@4.0.1 defines the following configuration options

function ExpressHandlebars(config) {
    // Config properties with defaults.
    utils.assign(this, {
        handlebars     : Handlebars,
        extname        : '.handlebars',
        layoutsDir     : undefined, // Default layouts directory is relative to `express settings.view` + `layouts/`
        partialsDir    : undefined, // Default partials directory is relative to `express settings.view` + `partials/`
        defaultLayout  : 'main',
        helpers        : undefined,
        compilerOptions: undefined,
    }, config);

If you do not use a default layout you can just set defaultLayout: false like below

app.engine(
  "hbs",
  expressHbs({
    extname: "hbs",
    defaultLayout: false
  })
);

Need to set defaultLayout as false, else "express-handlebars" will search for main.handlebars.

app.engine("hbs", expressHbs({ defaultLayout: false }));
app.set("view engine", "hbs");
app.set("views", "views");

Actually it's a bit annoying problem with express-handlebars but got it solved as following:

  • I had to create a standalone file which's not one of Routes and assign its name to defaultLayout
  • I had to set the path to views/layouts/
  • I had to to define extname to the extension i had defined
app.engine(
  "hbs",
  expressHbs({
    extname: "hbs",
    defaultLayout: "main-layout",
    layoutsDir: "views/layouts/"
  })
);

Node.js/Expressjs

Q. Error: ENOENT: no such file or directory, open 'S:\globle_express\views\layouts\main.handlebars'

Answer.

enter image description here

Rename your layout folder and do layouts

The folder structure of Expressjs should be like this

Making defaultLayout to false will solve this problem. My code worked fine with me.

    app.engine('hbs',hbs(
  {
    extname:'hbs', 
    defaultLayout:false,
    layoutDir:__dirname+'/views/layout/', 
    partialsDir:__dirname+'/views/partials/'
  }
  ))

Better to keep folder name as layouts and file name inside is layout.hbs without 's'.

After renaming the folder, my previous code worked with me perfectly.

app.engine('hbs',hbs(
  {
    extname:'hbs', 
    defaultLayout:'layout',
    layoutDir:__dirname+'/views/layouts/', 
    partialsDir:__dirname+'/views/partials/'
  }
  ))

There is no need of creating a layouts folder with a file within it.create 'views' folder and add the file. For instance 'form.handlebars' then do the following according to your code

    app.get('/' (req,res)=> {
      res.render("contact", {
      layout: false,
      name: req.body.name,
      quote: req.body.quote
      });
    })

Include this in your app.js

app.locals.layout = false;
 app.engine(
  'hbs',
  hbs.express4({
    defaultLayout: false,
    partialsDir: __dirname + '/views/partials'
  })
);

For express 4

You can simple add this:

app.engine('handlebars', exphbs.engine());
app.set('view engine', 'handlebars')

It worked in my case. Thanks:)

Related