Register partials in express-handlebars

76 Views Asked by At

I'm trying to register my partials into my app. I cannot figure it out how to do so. No matter what answer I get from other stack questions, it just don't work for me...

I set the express handlebars

import { engine } from 'express-handlebars';

//I use modules so without this(don't know what it does) doesn't work
const __filename = new URL(import.meta.url).pathname;
const __dirname = path.dirname(__filename);

app.set('view engine', 'hbs');
app.set('views', './views');
app.engine('hbs', engine({
    extname: '.hbs',
    partialsDir: path.join(__dirname, 'views', 'partials')
}));

I have the following dir format: enter image description here

I create my layout format and import the body and header:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{title}}</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
    {{> header }}

    {{{body}}}

</body>
</html>

Than, in the partials folder I create the header :

<header>
    <p>Wellcome back back</p>
</header>

After all this, my app doesn't find the partials name header:

Error: The partial header could not be found
    at Object.invokePartial (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\runtime.js:332:11)
    at Object.invokePartialWrapper [as invokePartial] (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\runtime.js:84:39)
    at Object.eval [as main] (eval at createFunctionContext (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\compiler\javascript-compiler.js:262:23), <anonymous>:13:28)
    at main (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\runtime.js:208:32)
    at ret (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\runtime.js:212:12)
    at ret (C:\Users\sasda\Desktop\websockets\node_modules\handlebars\dist\cjs\handlebars\compiler\compiler.js:519:21)
    at ExpressHandlebars._renderTemplate (C:\Users\sasda\Desktop\websockets\node_modules\express-handlebars\dist\express-handlebars.js:244:16)
    at ExpressHandlebars.<anonymous> (C:\Users\sasda\Desktop\websockets\node_modules\express-handlebars\dist\express-handlebars.js:156:31)
    at Generator.next (<anonymous>)
    at fulfilled (C:\Users\sasda\Desktop\websockets\node_modules\express-handlebars\dist\express-handlebars.js:10:58)
2

There are 2 best solutions below

0
daniel sas On

I used modules to import in JS files:

{
  "name": "websockets",
  "version": "1.0.0",
  "description": "",
  "module": "true",
  "type": "module",
  "main": "server.js",
  "scripts": {
    "dev": "nodemon server.js"
  },

So far, I tried to use path with imports module. It gave me errors like the following:

file:///C:/Users/sasda/Desktop/websockets/app.js:23
app.use(expres.static(path.join(__dirname, 'public')));
                                ^

ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'C:\Users\sasda\Desktop\websockets\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

I tried luckily to just write hardcode the path with ./views/partials, or whatever I needed to import in my app.js. Later on I found the following helpers.

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

I don't understand why it works, but finally I am able to use partials and views without hardcode the paths:

import { create } from 'express-handlebars';
import { fileURLToPath } from 'url';
import { dirname } from 'path';



const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

/**
 *  Serve and set the handlebars engine
*/
app.use(expres.static(path.join(__dirname, 'public')));

const hbs = create({
    extname:        '.hbs',
    partialsDir:    path.join(__dirname, 'views', 'partials'),
    layoutsDir:     path.join(__dirname, 'views', 'layouts')
});
app.engine('hbs', hbs.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, 'views'));

My folder structure is remaining unchanged: enter image description here

0
Bornoflightning On

Don't think you need to set the views twice, I have it once and it works fine. Try setting your engine and the handlebars like this. Try switching the order that you are running app.engine and app.set: enter image description here