# 使用 Express.js
使用 Express 时,热服务器模块重载可能不会在 SSR 之后工作。
这是因为 Express 有自己的路由栈,所以仅重载缓存并不足以让 Express 内部的路由重新加载。
### 在 Express 中添加全局回调
对于 Express 和 Next.js 的热模块重载,需要设置一个全局回调来清除 Express 的路由缓存。
这允许在不重启服务器的情况下识别路由更新。
```javascript title="server/express.js"
import express from 'express';
import next from 'next';
const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();
global.clearRoutes = () => {
server._router.stack = server._router.stack.filter((k) => !(k && k.route && k.route.path));
};
app.prepare().then(() => {
const server = express();
server.all('*', (req, res) => {
const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
const { pathname, query } = parsedUrl;
handle(req, res, parsedUrl);
});
server.listen(port, () => {
console.log(`> Ready on http://${hostname}:${port}`);
});
});
```
### 在重新验证期间触发回调
在 `_document.js` 中添加一个全局回调,在重新验证期间清除 Express 路由缓存,允许在不重启服务器的情况下提供更新后的路由。
```jsx title="pages/_document.js"
class MyDocument extends Document {
static async getInitialProps(ctx) {
if (ctx?.pathname && !ctx?.pathname?.endsWith('_error')) {
await revalidate().then((shouldUpdate) => {
if (shouldUpdate) {
global.clearRoutes();
}
});
}
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
```