都2024年了,Express依旧是我写node项目的常见选择。它的灵活性和强大的中间件系统使其能够轻松处理模板引擎、静态文件以及复杂的代理需求。本文将详细介绍如何在 Express.js 中处理模板引擎、静态文件,以及如何根据请求的 host 返回不同的前端项目。我们还将展示如何通过 JSON 配置文件动态代理多个前端项目,从而使应用更加灵活和易于维护。
模板引擎
模板引擎允许你使用动态内容生成 HTML 页面。Express.js 支持多种模板引擎,如 Pug (以前叫 Jade)、EJS、Handlebars 等。
使用 Pug 作为模板引擎的基本步骤
-
安装模板引擎
npm install pug -
设置模板引擎 在你的 Express 应用中,配置模板引擎:
const express = require('express'); const app = express(); app.set('view engine', 'pug'); app.set('views', './views'); // 设置模板文件夹 -
创建模板文件 在
views文件夹中创建一个 Pug 模板文件,例如index.pug:doctype html html head title= title body h1= message -
渲染模板 在路由中使用
res.render渲染模板文件:app.get('/', (req, res) => { res.render('index', { title: 'Hey', message: 'Hello there!' }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
使用 EJS 作为模板引擎的基本步骤
-
安装模板引擎
npm install ejs -
设置模板引擎 在你的 Express 应用中,配置模板引擎:
const express = require('express'); const app = express(); app.set('view engine', 'ejs'); app.set('views', './views'); // 设置模板文件夹 -
创建模板文件 在
views文件夹中创建一个 EJS 模板文件,例如index.ejs:<!DOCTYPE html> <html> <head> <title><%= title %></title> </head> <body> <h1><%= message %></h1> </body> </html> -
渲染模板 在路由中使用
res.render渲染模板文件:app.get('/', (req, res) => { res.render('index', { title: 'Hey', message: 'Hello there!' }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
静态文件
静态文件包括 HTML 文件、CSS 样式表、JavaScript 文件、图片等。这些文件通常存放在一个公开的目录中,供客户端直接访问。
处理静态文件的基本步骤
-
创建静态文件夹 创建一个文件夹来存放你的静态文件,例如
public文件夹。 -
放置静态文件 在
public文件夹中放置你的静态文件,例如public/style.css、public/script.js和public/image.png等。 -
配置 Express 服务静态文件 使用 Express 的
express.static中间件来服务静态文件:const express = require('express'); const app = express(); app.use(express.static('public')); // 配置静态文件目录 app.get('/', (req, res) => { res.send('Hello World!'); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });现在,客户端可以直接访问
public文件夹中的静态文件。例如:http://localhost:3000/style.csshttp://localhost:3000/script.jshttp://localhost:3000/image.png
代理多个前端项目
有时你可能需要根据请求的 host 返回不同目录中的前端文件。可以通过自定义中间件和路由来实现这一功能。
示例代码
-
安装必要的包
npm install express -
项目结构 假设你的项目结构如下:
project-root/ ├── app.js ├── public1/ │ ├── index.html │ └── ... └── public2/ ├── index.html └── ... -
配置 Express 应用
const express = require('express'); const path = require('path'); const app = express(); // 中间件:根据请求的 host 动态选择静态文件目录 app.use((req, res, next) => { const host = req.hostname; if (host === 'example1.com') { express.static(path.join(__dirname, 'public1'))(req, res, next); } else if (host === 'example2.com') { express.static(path.join(__dirname, 'public2'))(req, res, next); } else { res.status(404).send('Not Found'); } }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
详细说明
-
安装 express 确保你已经安装了 Express 包。
-
项目结构 你的项目根目录下有两个文件夹
public1和public2,分别存放两个不同的前端项目。 -
配置中间件 通过使用自定义的中间件,根据请求的 host 动态选择要服务的静态文件目录。
req.hostname获取请求的 host。- 根据
host的不同,使用express.static动态设置静态文件目录。
-
启动服务器 运行
app.js,服务器将根据请求的 host 返回不同的前端文件。
示例运行
假设你在本地运行服务器,并且通过 hosts 文件配置了 example1.com 和 example2.com 指向本地:
- 当访问
http://example1.com:3000时,将返回public1目录中的文件。 - 当访问
http://example2.com:3000时,将返回public2目录中的文件。
注意!!!
Host 配置 在实际应用中,你可能需要在 DNS 或 hosts 文件中配置这些 host 名称指向你的服务器 IP 地址。比如win你就需要改一下c盘的host文件
性能优化 如果有大量的静态文件请求,考虑使用反向代理服务器(如 Nginx)来代理这些静态文件请求,提升性能。
通过这种方式,你可以在同一个 Express 服务器上代理多个前端项目,灵活地根据请求的 host 返回不同的内容
思考,这种写死的很不灵活是不是还可以再拓展一下呢?
当然可以!我们可以通过配置文件来定义各个前端项目的目录和路由模式,从而实现更灵活和可维护的代理。下面将介绍如何通过 JSON 文件或字典来配置多前端项目代理。
JSON 配置文件
首先,我们创建一个 JSON 配置文件,定义各个前端项目的 host 和路径:
config.json
{
"projects": [
{
"host": "example1.com",
"path": "./public1"
},
{
"host": "example2.com",
"path": "./public2"
},
{
"host": "127.0.0.1",
"route": "/public3",
"path": "./public3"
},
{
"host": "127.0.0.1",
"route": "/public4",
"path": "./public4"
}
]
}
配置 Express 应用
接下来,我们修改 Express 应用的代码,使其能够读取配置文件并根据配置动态代理多个前端项目。
app.js
const express = require("express");
const path = require("path");
const fs = require("fs");
const app = express();
const port = 3000;
// 封装日志打印函数
function logProxySetup(proxyUrl, projectPath) {
console.log(`Proxy setup: ${proxyUrl} -> ${projectPath}`);
}
// 读取配置文件
const config = JSON.parse(fs.readFileSync("./config.json", "utf-8"));
// 动态配置中间件
config.projects.forEach((project) => {
if (project.host && project.route) {
// 配置特定 host 和路由的静态文件目录
app.use(project.route, (req, res, next) => {
console.log(`Received request for ${req.hostname}${req.url}`);
if (req.hostname === project.host || req.hostname === "localhost") {
console.log(
`Serving static files from ${project.path} for route ${project.route}`
);
express.static(path.join(__dirname, project.path))(req, res, next);
} else {
next();
}
});
let proxyUrl = `http://${project.host}${port === 80 ? "" : ":" + port}${
project.route
}`;
logProxySetup(proxyUrl, project.path);
} else if (project.host) {
// 配置特定 host 的静态文件目录
app.use((req, res, next) => {
console.log(`Received request for ${req.hostname}${req.url}`);
if (req.hostname === project.host || req.hostname === "localhost") {
console.log(
`Serving static files from ${project.path} for host ${project.host}`
);
express.static(path.join(__dirname, project.path))(req, res, next);
} else {
next();
}
});
let proxyUrl = `http://${project.host}`;
logProxySetup(proxyUrl, project.path);
} else if (project.route) {
// 配置特定路由的静态文件目录
app.use(project.route, (req, res, next) => {
console.log(`Received request for ${req.hostname}${req.url}`);
if (req.hostname === "localhost") {
console.log(
`Serving static files from ${project.path} for route ${project.route}`
);
express.static(path.join(__dirname, project.path))(req, res, next);
} else {
next();
}
});
let proxyUrl = `http://localhost:${port}${project.route}`;
if (port === 80) {
proxyUrl = `http://localhost${project.route}`;
}
logProxySetup(proxyUrl, project.path);
}
});
// 启动服务器
app.listen(port, () => {
let serverUrl = `http://localhost:${port}`;
if (port === 80) {
serverUrl = "http://localhost";
}
console.log(`Server is running on ${serverUrl}`);
});
详细说明
-
读取配置文件
- 使用
fs.readFileSync读取config.json文件,并解析为 JSON 对象。
- 使用
-
动态配置中间件
- 遍历配置文件中的
projects数组。 - 根据每个项目的配置,动态设置中间件。
- 如果配置了
host和route,则需要同时匹配hostname和path。 - 如果只配置了
host,则只需要匹配hostname。 - 如果只配置了
route,则只需要匹配路径前缀。
- 遍历配置文件中的
-
启动服务器
- 运行
app.js,服务器将根据配置文件动态代理多个前端项目。
- 运行
示例运行
假设你在本地运行服务器,并且通过 hosts 文件配置了 example1.com 和 example2.com 指向本地:
- 当访问
http://example1.com:3000时,将返回public1目录中的文件。 - 当访问
http://example2.com:3000时,将返回public2目录中的文件。 - 当访问
http://127.0.0.1:3000/public3时,将返回public3目录中的文件。 - 当访问
http://127.0.0.1:3000/public4时,将返回public4目录中的文件。
通过这种方式,你可以通过配置文件灵活地代理多个前端项目,支持根据 host 和路由模式返回不同的内容。
总结
本文详细介绍了在 Express.js 中处理模板引擎、静态文件以及多前端项目代理的方法。我们首先探讨了如何使用 Pug 和 EJS 作为模板引擎,并展示了它们的安装、配置和使用方法。接着,我们介绍了如何配置和服务静态文件,使客户端能够直接访问这些文件。最后,我们展示了如何根据请求的 host 返回不同的前端项目,并通过 JSON 配置文件实现动态代理多个前端项目。这些技术和方法为开发者提供了灵活的工具,帮助他们更高效地构建和管理复杂的 Express.js 应用。通过这些实践,开发者可以在同一个服务器上代理多个前端项目,提升应用的可维护性和扩展性。