如何提升部署在Heroku平台上的Node.js应用渲染速度?
部署Heroku后渲染缓慢的问题排查与解决
当前代码的核心问题
你在服务器启动时异步拉取Firestore数据,但服务器不会等待数据加载完成就开始接收请求。如果请求来得比数据加载快,前端拿到的是空数组,后续还要等数据加载完成才能渲染,这会让用户感觉页面加载极慢。另外,你直接把DocumentSnapshot对象存进数组,EJS渲染时每次调用.data()都会产生额外开销,也是拖慢速度的原因。
针对性修复步骤
1. 确保数据加载完成后再启动服务
把getNews改成异步函数,等数据拉取完成后再让服务器监听端口,避免请求进来时数据还没准备好:
var allnewsarr = []; async function getNews() { console.log('running'); try { const snaps = await fs.collection('news').orderBy("timestap",'desc').get(); // 直接提取文档数据存成纯对象,减少EJS渲染时的开销 allnewsarr = snaps.map(doc => ({ ...doc.data(), id: doc.id // 如果需要文档ID可带上 })); console.log(allnewsarr.length, "are the articles"); } catch (error) { console.log(error.message); // 失败后5秒重试,避免无限循环 setTimeout(getNews, 5000); } } // 等待数据加载完成再启动服务 (async () => { await getNews(); server.listen(port, () => { console.log(`The new logs ${port}`); }); })();
2. 优化Firestore数据拉取与处理
- 只拉取需要的字段:如果news文档字段较多,用
.select('title', 'content', 'timestap')指定要获取的字段,减少数据传输量。 - 匹配地域:Heroku服务器默认在美东,若你的Firestore数据库在其他区域,跨地域访问会有延迟,把Firestore地域改成和Heroku服务器相近的区域(比如美东)。
3. 优化EJS渲染速度
- 开启视图缓存:生产环境下启用EJS缓存,避免重复编译模板:
if (process.env.NODE_ENV === 'production') { app.set('view cache', true); } - 提前处理数据逻辑:不要在EJS模板里做复杂计算,所有数据处理都在服务器端完成后再传给模板。
4. 解决Heroku冷启动问题
如果应用长时间无请求,Heroku会休眠实例,再次请求时需要重启并重新拉取数据,导致首次加载极慢:
- 用Heroku Scheduler定时发送请求到应用,保持实例活跃。
- 升级到Heroku付费实例,避免自动休眠。
5. 数据量大时用分页加载
若news数据量很大,一次性拉取所有数据会耗时很久,改成分页加载:
- 服务器端接收页码参数,用Firestore的
limit()和startAfter()实现分页,每次只返回10-20条数据。 - 前端滚动到底部时再请求下一页数据,减少单次页面加载的数据量。
内容的提问来源于stack exchange,提问作者Elton
相关产品推荐
相关产品推荐

