
本文介绍在 Vite 项目中仅于生产环境动态注入 <link rel="preload"> 标签的可靠方案,结合 react-helmet-async 实现运行时条件渲染,避免构建时硬编码或污染开发 HTML 模板。
本文介绍在 vite 项目中仅于生产环境动态注入 `` 标签的可靠方案,结合 `react-helmet-async` 实现运行时条件渲染,避免构建时硬编码或污染开发 html 模板。
在 Vite 中,HTML 模板(如 index.html)是静态文件,无法直接根据构建模式(开发/生产)动态插入资源标签。若将 <link rel="preload"> 硬写入 index.html,它会在所有环境中加载,不仅违背“仅生产启用”的需求,还可能干扰开发调试(例如触发不必要的字体预加载或跨域报错)。因此,推荐采用运行时条件注入策略——利用前端框架能力,在应用挂载时按环境变量决定是否渲染。
以 React 项目为例,react-helmet-async 是管理文档头部内容(<head>)的事实标准库,支持服务端渲染与客户端动态更新。配合 Vite 提供的 import.meta.env.PROD 编译时环境标志(构建后自动替换为 true/false),可精准控制标签生效时机:
import { HelmetProvider, Helmet } from "react-helmet-async";
function App() {
return (
<HelmetProvider>
<Helmet>
{import.meta.env.PROD && (
<link
rel="preload"
href="assets/inter-latin-400-normal.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
)}
</Helmet>
{/* 其他组件 */}
<main>...</main>
</HelmetProvider>
);
}
export default App;✅ 关键说明:
- import.meta.env.PROD 是 Vite 内置只读布尔变量,构建时静态内联,不会在客户端暴露未使用分支,确保零运行时开销;
- crossOrigin="anonymous"(注意属性名大小写)必须显式设置,否则字体预加载可能因 CORS 策略失败;
- 路径 assets/inter-latin-400-normal.woff2 需与 Vite 构建后实际输出路径一致(默认位于 dist/assets/ 下,可通过 build.assetsDir 配置调整);
- 此方案不依赖 HTML 模板修改,开发时完全静默,生产构建后自动生效,符合现代前端工程化最佳实践。
⚠️ 注意:若项目未使用 React 或 SSR,也可通过纯 JavaScript 在 main.tsx 或入口逻辑中操作 document.head,但需手动处理重复插入、卸载清理等问题;react-helmet-async 则自动保障唯一性与生命周期安全。


















