
可通过检查 HTTP 请求头中的 Accept 字段值判断:若包含 text/html(如浏览器地址栏直接访问),则为查看源码;若为 */* 或其他非 HTML 类型,则为脚本正常加载。此方法适用于服务端(如 Node.js、Nginx、Service Worker 代理)实现差异化响应。
可通过检查 http 请求头中的 `accept` 字段值判断:若包含 `text/html`(如浏览器地址栏直接访问),则为查看源码;若为 `*/*` 或其他非 html 类型,则为脚本正常加载。此方法适用于服务端(如 node.js、nginx、service worker 代理)实现差异化响应。
在 Web 开发中,有时需要对同一份 .js 文件提供双重用途:既作为可执行脚本被 <script> 标签或 ES 模块导入,又能在用户直接在浏览器地址栏输入路径(如 https://example.com/script.js)时,自动渲染为带语法高亮的 HTML 页面(例如配合 Service Worker 实现离线代码浏览)。关键前提在于——服务端或拦截层必须能可靠识别请求意图。
核心原理在于浏览器发起请求时,Accept 请求头会因上下文不同而显著变化:
✅ 浏览器直接打开 JS 文件(查看源码):
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,...
→ 明确声明接受 HTML 类型,表明用户意图是“渲染为页面”。⚠️ 作为 <script> 加载或通过 import 导入:
Accept: */*(或 application/javascript, text/javascript 等)
→ 不包含 text/html,表明资源应被解析执行,而非展示。
因此,检测逻辑简洁而可靠:
// 示例:Express.js 中间件(服务端)
app.get('/scripts/:file(*)', (req, res) => {
const accept = req.get('Accept') || '';
if (accept.includes('text/html')) {
// 用户直接打开:返回语法高亮 HTML 页面
const jsContent = fs.readFileSync(`./scripts/${req.params.file}`, 'utf8');
const highlightedHtml = highlightJsToHtml(jsContent); // 使用 highlight.js 等库
res.type('text/html').send(`
<!DOCTYPE html>
<html><body style="margin:0;font-family:monospace;">
<pre>${highlightedHtml}</pre>
</body></html>
`);
} else {
// 正常脚本加载:返回原始 JS,确保 Content-Type 正确
res.type('application/javascript')
.header('Cache-Control', 'public, max-age=31536000')
.sendFile(`./scripts/${req.params.file}`);
}
});⚠️ 重要注意事项:
- 该方案必须在服务端或可修改响应的网关层(如 Nginx、Cloudflare Workers、Service Worker)实现;纯前端 JavaScript 无法读取自身请求的 Accept 头(CORS 限制且无访问权限)。
- Service Worker 中可通过 event.request.headers.get('Accept') 安全获取(需在 fetch 事件中拦截),但注意:Chrome 对 import() 的预检请求可能不携带完整 Accept,建议以主请求为准。
- 避免仅依赖 User-Agent 或 URL 后缀(如 .js?view=1),前者易伪造,后者破坏语义与缓存。
- 生产环境务必设置正确的 Content-Type 响应头:HTML 页面返回 text/html,JS 文件严格返回 application/javascript(而非 text/plain),否则影响执行与安全策略(如 MIME-type sniffing)。
总结而言,利用 Accept 请求头的语义差异是一种轻量、标准且跨浏览器兼容的检测方式。它不依赖客户端特征,无需额外参数,即可让一份物理文件智能适配两种使用场景——既是可执行代码,也是可阅读文档。合理运用此技巧,可显著提升开发者工具类站点或静态文档站的用户体验。










