feat: integrate SEO hook for dynamic metadata management
- Removed hardcoded canonical link from index.html. - Implemented useSEO hook in layout.tsx to dynamically update SEO metadata including title, description, and canonical URL based on the current route. - Added new use-seo.ts file containing the SEO hook logic for improved search engine optimization.
This commit is contained in:
		
							
								
								
									
										96
									
								
								src/hooks/use-seo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/hooks/use-seo.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| import { useEffect } from 'react'; | ||||
| import { useLocation } from 'react-router-dom'; | ||||
|  | ||||
| interface UseSEOOptions { | ||||
|   title?: string; | ||||
|   description?: string; | ||||
|   baseUrl?: string; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * SEO Hook - 动态更新页面 SEO 元数据 | ||||
|  *  | ||||
|  * @param options - SEO 配置选项 | ||||
|  * @param options.title - 页面标题(可选) | ||||
|  * @param options.description - 页面描述(可选) | ||||
|  * @param options.baseUrl - 网站基础 URL,默认为 https://litek.typist.cc | ||||
|  *  | ||||
|  * @example | ||||
|  * ```tsx | ||||
|  * // 在组件中使用 | ||||
|  * useSEO({ | ||||
|  *   title: 'UUID Generator', | ||||
|  *   description: 'Free online UUID generator tool' | ||||
|  * }); | ||||
|  * ``` | ||||
|  */ | ||||
| export const useSEO = (options: UseSEOOptions = {}) => { | ||||
|   const location = useLocation(); | ||||
|   const {  | ||||
|     title,  | ||||
|     description,  | ||||
|     baseUrl = 'https://litek.typist.cc'  | ||||
|   } = options; | ||||
|  | ||||
|   useEffect(() => { | ||||
|     // 构建当前页面的完整 URL | ||||
|     const canonicalUrl = `${baseUrl}${location.pathname}`; | ||||
|      | ||||
|     // 更新或创建 canonical 链接 | ||||
|     let canonical = document.querySelector('link[rel="canonical"]') as HTMLLinkElement; | ||||
|     if (!canonical) { | ||||
|       canonical = document.createElement('link'); | ||||
|       canonical.setAttribute('rel', 'canonical'); | ||||
|       document.head.appendChild(canonical); | ||||
|     } | ||||
|     canonical.setAttribute('href', canonicalUrl); | ||||
|  | ||||
|     // 更新页面标题 | ||||
|     if (title) { | ||||
|       document.title = `${title} - Lite Kit`; | ||||
|     } | ||||
|  | ||||
|     // 更新 meta description | ||||
|     if (description) { | ||||
|       let metaDescription = document.querySelector('meta[name="description"]') as HTMLMetaElement; | ||||
|       if (metaDescription) { | ||||
|         metaDescription.setAttribute('content', description); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // 更新 Open Graph URL | ||||
|     let ogUrl = document.querySelector('meta[property="og:url"]') as HTMLMetaElement; | ||||
|     if (ogUrl) { | ||||
|       ogUrl.setAttribute('content', canonicalUrl); | ||||
|     } | ||||
|  | ||||
|     // 更新 Open Graph Title | ||||
|     if (title) { | ||||
|       let ogTitle = document.querySelector('meta[property="og:title"]') as HTMLMetaElement; | ||||
|       if (ogTitle) { | ||||
|         ogTitle.setAttribute('content', `${title} - Lite Kit`); | ||||
|       } | ||||
|  | ||||
|       // 更新 Twitter Card Title | ||||
|       let twitterTitle = document.querySelector('meta[name="twitter:title"]') as HTMLMetaElement; | ||||
|       if (twitterTitle) { | ||||
|         twitterTitle.setAttribute('content', `${title} - Lite Kit`); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // 更新 Open Graph Description | ||||
|     if (description) { | ||||
|       let ogDescription = document.querySelector('meta[property="og:description"]') as HTMLMetaElement; | ||||
|       if (ogDescription) { | ||||
|         ogDescription.setAttribute('content', description); | ||||
|       } | ||||
|  | ||||
|       // 更新 Twitter Card Description | ||||
|       let twitterDescription = document.querySelector('meta[name="twitter:description"]') as HTMLMetaElement; | ||||
|       if (twitterDescription) { | ||||
|         twitterDescription.setAttribute('content', description); | ||||
|       } | ||||
|     } | ||||
|   }, [location.pathname, title, description, baseUrl]); | ||||
| }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 typist
					typist