如何实现Express根端点返回并渲染README.md文件?
解决Express渲染README.md为GitHub风格页面的问题
为什么你的代码报错?
require('../README.md') 会让Node.js把MD文件当作JS模块解析,但MD的语法(比如开头的#)不是合法的JS语法,所以直接抛出语法错误。Node.js默认只支持JS、JSON等模块类型,不能直接require MD文件。
实现步骤
1. 安装必要依赖
需要用marked解析Markdown为HTML,highlight.js实现代码高亮:
npm install marked highlight.js
2. 编写Express路由代码
用Node.js内置的fs模块读取README.md内容,再用marked转换为HTML,最后返回带GitHub风格样式的页面:
const express = require('express'); const fs = require('fs'); const path = require('path'); const marked = require('marked'); const hljs = require('highlight.js'); const app = express(); // 配置marked,启用代码高亮,匹配GitHub风格语法 marked.setOptions({ highlight: function(code, lang) { const language = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language }).value; }, breaks: true, // 支持换行 gfm: true // 支持GitHub Flavored Markdown }); app.get('/', (req, res) => { // 确定README.md的绝对路径 const readmePath = path.join(__dirname, '../README.md'); try { // 同步读取文件内容 const readmeContent = fs.readFileSync(readmePath, 'utf8'); // 将Markdown转换为HTML const htmlContent = marked(readmeContent); // 构造完整HTML页面,内嵌GitHub风格样式 const fullHtml = ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>README</title> <style> body { max-width: 800px; margin: 2rem auto; padding: 0 1rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; line-height: 1.5; } h1, h2, h3, h4, h5, h6 { margin-top: 2rem; margin-bottom: 1rem; font-weight: 600; } pre { background-color: #f6f8fa; border-radius: 6px; padding: 1rem; overflow-x: auto; } code { background-color: #f6f8fa; padding: 0.2rem 0.4rem; border-radius: 3px; } blockquote { border-left: 4px solid #dfe2e5; padding-left: 1rem; color: #6a737d; margin: 0; } /* 代码高亮样式(模拟GitHub) */ .hljs { color: #24292e; background: #f6f8fa; } .hljs-doctag, .hljs-keyword, .hljs-meta .hljs-keyword, .hljs-template-tag, .hljs-template-variable, .hljs-type, .hljs-variable.language_ { color: #d73a49; } .hljs-title, .hljs-title.class_, .hljs-title.class_.inherited__, .hljs-title.function_ { color: #6f42c1; } .hljs-attr, .hljs-attribute, .hljs-literal, .hljs-meta, .hljs-number, .hljs-operator, .hljs-selector-attr, .hljs-selector-class, .hljs-selector-id, .hljs-variable { color: #005cc5; } .hljs-meta .hljs-string, .hljs-regexp, .hljs-string { color: #032f62; } .hljs-built_in, .hljs-symbol { color: #e36209; } .hljs-code, .hljs-comment, .hljs-formula { color: #6a737d; } .hljs-name, .hljs-quote, .hljs-selector-pseudo, .hljs-selector-tag { color: #22863a; } .hljs-subst { color: #24292e; } .hljs-section { color: #005cc5; font-weight: 700; } .hljs-bullet { color: #735c0f; } .hljs-emphasis { color: #24292e; font-style: italic; } .hljs-strong { color: #24292e; font-weight: 700; } .hljs-addition { color: #22863a; background-color: #f0fff4; } .hljs-deletion { color: #b31d28; background-color: #ffeef0; } </style> </head> <body> ${htmlContent} </body> </html> `; res.send(fullHtml); } catch (err) { res.status(500).send('无法加载README.md文件'); } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`服务器运行在 http://localhost:${PORT}`); });
代码说明
fs.readFileSync:同步读取README.md内容,也可以用异步的fs.promises.readFile配合async/await,避免阻塞服务器事件循环:app.get('/', async (req, res) => { const readmePath = path.join(__dirname, '../README.md'); try { const readmeContent = await fs.promises.readFile(readmePath, 'utf8'); const htmlContent = marked(readmeContent); // 构造fullHtml... res.send(fullHtml); } catch (err) { res.status(500).send('无法加载README.md文件'); } });marked.setOptions:配置解析规则,启用代码高亮和GFM语法,让渲染效果更贴近GitHub。- 内嵌样式:模拟GitHub的页面布局和代码高亮样式,无需依赖外部资源。
- 错误处理:捕获文件读取失败的情况,返回友好的错误提示。
内容的提问来源于stack exchange,提问作者swamptiger24
相关产品推荐
相关产品推荐

