Introduction
Building web applications require a robust set of tools to handle the backend logic, templating for dynamically generating HTML, and a strong typed language for safe development practices. The combination of Express, Handlebars, and TypeScript offers a powerful stack for developers to build scalable and maintainable applications. In this tutorial, you will learn how to integrate Handlebars as a templating engine into an Express application that uses TypeScript.
Prerequisites
- Basic knowledge of Node.js and Express
- Familiarity with TypeScript
- Node.js and npm installed
- Visual Studio Code or your preferred IDE
Setting Up Your Project
First, create a new directory for your project and initialize a new npm package:
mkdir express-ts-handlebars
cd express-ts-handlebars
npm init -y
Install the necessary dependencies:
npm install express express-handlebars @types/express @types/express-handlebars typescript ts-node nodemon
Set up TypeScript in your project by creating a tsconfig.json file:
tsc --init
Edit your tsconfig.json to include the following options:
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
}
}
Integrating Handlebars with Express
To use Handlebars as your templating engine with Express, set it up in your entry file, typically this is index.ts:
import express from 'express';
import exphbs from 'express-handlebars';
const app = express();
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
app.get('/', (req, res) => {
res.render('home');
});
app.listen(3000, () => {
console.log('The web server has started on port 3000');
});
Then, create a views directory with a ‘home.handlebars’ file as a basic template:
<h1>Welcome to Express + Handlebars + TypeScript</h1>
Creating a Router and Controller
For more structure, you should create separate routers and controllers. Here’s a simple controller example:
export const homeController = (req, res) => {
res.render('home', { layout: 'main', pageTitle: 'Home Page' });
};
And a router to match:
import { Router } from 'express';
import { homeController } from './controllers/homeController';
const router = Router();
router.get('/', homeController);
export default router;
Configuring the Layouts and Partials
In your views directory, create a ‘layouts’ directory with a main.layout.handlebars file:
<html>
<head>
<title>{{pageTitle}}</title>
</head>
<body>
{{{body}}}
</body>
</html>
Create partials for reusable components. For example, create a header.partial.handlebars file:
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
</header>
TypeScript Typings
Handle request and response objects safely by extending the Express types:
import { Request, Response } from 'express';
interface TypedRequest<T> extends Request {
body: T;
}
interface TypedResponse extends Response {
locals: {
user?: MyUserType;
};
}
Complete Project Structure
Here’s how your project folder could look like:
express-ts-handlebars/
├─ src/
│ ├─ controllers/
│ │ └─ homeController.ts
│ ├─ routes/
│ │ └─ homeRoute.ts
│ ├─ types/
│ │ └─ custom.d.ts
│ └─ index.ts
├─ views/
│ ├─ layouts/
│ │ └─ main.layout.handlebars
│ ├─ partials/
│ │ └─ header.partial.handlebars
│ └─ home.handlebars
├─ package.json
└─ tsconfig.json
Running the Application
Create a ‘start’ script in your package.json to compile and run your app:
"scripts": {
"start": "tsc && node ./dist/index.js",
"dev": "nodemon ./src/index.ts"
}
To start your application, run:
npm run start
Or for development with automatic reloading:
npm run dev
Conclusion
In this tutorial, you’ve learned how to integrate Handlebars as your templating engine into an Express application using TypeScript. Managing views is simplified, TypeScript brings strong typing to your app for better code integrity, and Express provides a lightweight framework to manage the web server and routing. With these tools, you can build efficient and effective web applications.