# React Helmet 完整指南
# 1. 简介
React Helmet 是一个用于管理 HTML 文档头的 React 组件。它允许您以声明式的方式修改文档的 <head>
部分,包括 title、meta、link 等标签。
# 2. 安装
# 使用 npm
npm install react-helmet-async
# 使用 yarn
yarn add react-helmet-async
# 使用 pnpm
pnpm add react-helmet-async
# 3. 基础配置
# 3.1 在应用根组件中设置
// src/App.tsx
import { HelmetProvider } from 'react-helmet-async';
const App = () => {
return (
<HelmetProvider>
{/* 你的应用内容 */}
</HelmetProvider>
);
};
# 3.2 基本用法
import { Helmet } from 'react-helmet-async';
const HomePage = () => {
return (
<>
<Helmet>
<title>首页标题</title>
<meta name="description" content="页面描述" />
</Helmet>
{/* 页面内容 */}
</>
);
};
# 4. 常用功能
# 4.1 设置多种 Meta 标签
<Helmet>
{/* 基本 Meta 标签 */}
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="网站描述" />
<meta name="keywords" content="关键词1,关键词2" />
{/* Open Graph Meta 标签 */}
<meta property="og:title" content="页面标题" />
<meta property="og:description" content="页面描述" />
<meta property="og:image" content="图片URL" />
<meta property="og:url" content="页面URL" />
{/* Twitter Card Meta 标签 */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="页面标题" />
<meta name="twitter:description" content="页面描述" />
<meta name="twitter:image" content="图片URL" />
</Helmet>
# 4.2 添加样式表和脚本
<Helmet>
{/* 外部样式表 */}
<link rel="stylesheet" href="styles.css" />
{/* 内联样式 */}
<style>{`
body {
background-color: #f0f0f0;
}
`}</style>
{/* 外部脚本 */}
<script src="external-script.js" type="text/javascript" />
{/* 内联脚本 */}
<script>{`
console.log('Hello from Helmet!');
`}</script>
</Helmet>
# 4.3 条件渲染
<Helmet>
<title>{isLoggedIn ? '用户首页' : '请登录'}</title>
{needsAnalytics && (
<script src="analytics.js" type="text/javascript" />
)}
</Helmet>
# 5. 高级用法
# 5.1 创建可重用的 SEO 组件
// src/components/SEO/index.tsx
import { Helmet } from 'react-helmet-async';
interface SEOProps {
title: string;
description?: string;
keywords?: string;
image?: string;
url?: string;
type?: string;
children?: React.ReactNode;
}
export const SEO: React.FC<SEOProps> = ({
title,
description,
keywords,
image,
url,
type = 'website',
children
}) => {
const siteName = '网站名称';
const defaultDescription = '默认描述';
const defaultImage = '/default-og-image.jpg';
return (
<Helmet>
{/* 基本标签 */}
<title>{`${title} | ${siteName}`}</title>
<meta name="description" content={description || defaultDescription} />
{keywords && <meta name="keywords" content={keywords} />}
{/* Open Graph */}
<meta property="og:site_name" content={siteName} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description || defaultDescription} />
<meta property="og:image" content={image || defaultImage} />
{url && <meta property="og:url" content={url} />}
<meta property="og:type" content={type} />
{/* Twitter Card */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description || defaultDescription} />
<meta name="twitter:image" content={image || defaultImage} />
{children}
</Helmet>
);
};
# 5.2 在页面中使用 SEO 组件
// src/pages/ProductPage.tsx
const ProductPage = ({ product }) => {
return (
<>
<SEO
title={product.name}
description={product.description}
keywords={product.tags.join(',')}
image={product.image}
url={`https://yoursite.com/products/${product.id}`}
type="product"
/>
{/* 页面内容 */}
</>
);
};
# 5.3 动态更新标题
const DynamicPage = () => {
const [count, setCount] = useState(0);
return (
<>
<Helmet>
<title>{`(${count}) 新消息`}</title>
{count > 0 && (
<link rel="icon" href="/favicon-notification.ico" />
)}
</Helmet>
<button onClick={() => setCount(count + 1)}>
增加消息
</button>
</>
);
};
# 6. 最佳实践
# 6.1 默认配置
// src/config/helmet.ts
export const defaultSEO = {
title: '网站名称',
description: '网站默认描述',
keywords: '默认关键词',
image: '/default-og-image.jpg',
url: 'https://yoursite.com',
twitterHandle: '@yourhandle',
};
// src/components/DefaultHelmet.tsx
import { defaultSEO } from '../config/helmet';
export const DefaultHelmet = () => (
<Helmet>
<html lang="zh-CN" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>{defaultSEO.title}</title>
<meta name="description" content={defaultSEO.description} />
<meta name="keywords" content={defaultSEO.keywords} />
<meta property="og:site_name" content={defaultSEO.title} />
<meta property="og:title" content={defaultSEO.title} />
<meta property="og:description" content={defaultSEO.description} />
<meta property="og:image" content={defaultSEO.image} />
<meta property="og:url" content={defaultSEO.url} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content={defaultSEO.twitterHandle} />
<link rel="icon" href="/favicon.ico" />
</Helmet>
);
# 6.2 异步数据加载
const AsyncPage = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchData().then(result => {
setData(result);
setLoading(false);
});
}, []);
return (
<>
<Helmet>
<title>{loading ? '加载中...' : data.title}</title>
{!loading && (
<>
<meta name="description" content={data.description} />
<meta property="og:title" content={data.title} />
</>
)}
</Helmet>
{/* 页面内容 */}
</>
);
};
# 7. 注意事项
服务端渲染:
- 使用
react-helmet-async
而不是react-helmet
- 确保在服务端正确提取和注入头部信息
- 使用
性能考虑:
- 避免频繁更新 Helmet 内容
- 对于动态内容,考虑使用防抖或节流
SEO 最佳实践:
- 确保每个页面都有唯一的标题和描述
- 使用合适的 Open Graph 和 Twitter Card 标签
- 保持标题长度在 60 个字符以内
- 描述内容保持在 155-160 个字符以内
# 8. 常见问题解决
标题不更新:
- 检查是否正确嵌套了 HelmetProvider
- 确保组件正确导入了 Helmet
重复标签:
- Helmet 会自动处理重复标签,保留最后定义的值
- 检查是否在多个地方定义了相同的标签
动态内容:
- 使用条件渲染确保内容已加载
- 考虑添加加载状态的处理