Vite中如何根据请求Cookie为<html>标签添加dir属性
根据项目渲染模式不同,分两种场景处理:
纯客户端渲染项目(普通SPA/静态站点)
这种场景不需要改Vite配置,直接在入口HTML中插入提前执行的内联脚本即可,核心是要在页面资源加载、DOM渲染前完成dir属性设置,避免布局闪烁。
- 打开项目根目录的
index.html,在<head>标签的最顶部(所有meta、资源引用、业务脚本之前)加入如下代码:
<script> // 按需补充你需要支持的RTL语言code const RTL_LANG_LIST = ['ar', 'fa', 'he', 'ur', 'ps', 'sd', 'ku', 'yi'] // 读取指定Cookie值 const getTargetCookie = (cookieKey) => { const regMatch = document.cookie.match(new RegExp('(^| )' + cookieKey + '=([^;]+)')) return regMatch ? decodeURIComponent(regMatch[2]) : null } // 替换成你项目中存储语言标识的Cookie键名 const currentLang = getTargetCookie('your_site_lang_key') const isRTLMode = currentLang && RTL_LANG_LIST.includes(currentLang.split('-')[0]) // 给html标签设置dir属性 document.documentElement.dir = isRTLMode ? 'rtl' : 'ltr' // 可选:同步设置lang属性,符合无障碍访问要求 if (currentLang) document.documentElement.lang = currentLang </script>
- 注意事项:这段脚本必须内联写在HTML头部最靠前的位置,不要抽成外部JS文件,也不要放到Vue/React等业务框架的挂载逻辑里执行,否则会出现页面先按默认LTR渲染、再跳转为RTL的布局闪动问题。
SSR/同构渲染项目
服务端渲染场景需要在服务端返回HTML时就注入正确的dir属性,避免客户端hydration时出现属性不匹配的报错,同时也能彻底避免闪屏。
- 首先修改
vite.config.js,让开发环境、生产预览环境的服务端逻辑都能根据请求Cookie自动注入dir属性:
import { defineConfig } from 'vite' // 和客户端保持一致的RTL语言列表 const RTL_LANG_LIST = ['ar', 'fa', 'he', 'ur', 'ps', 'sd', 'ku', 'yi'] // 替换成你项目存储语言的Cookie键名 const LANG_COOKIE_KEY = 'your_site_lang_key' export default defineConfig({ server: { transformIndexHtml(html, ctx) { // 从请求头中解析Cookie const cookieHeader = ctx.server.req.headers.cookie || '' const langMatch = cookieHeader.match(new RegExp(`${LANG_COOKIE_KEY}=([^;]+)`)) const currentLang = langMatch ? decodeURIComponent(langMatch[1]) : null const isRTLMode = currentLang && RTL_LANG_LIST.includes(currentLang.split('-')[0]) const dirValue = isRTLMode ? 'rtl' : 'ltr' // 替换html标签,注入dir和lang属性 return html.replace( '<html', `<html dir="${dirValue}"${currentLang ? ` lang="${currentLang}"` : ''}` ) } }, preview: { // 预览模式和开发环境保持一致的处理逻辑 transformIndexHtml(html, ctx) { const cookieHeader = ctx.req.headers.cookie || '' const langMatch = cookieHeader.match(new RegExp(`${LANG_COOKIE_KEY}=([^;]+)`)) const currentLang = langMatch ? decodeURIComponent(langMatch[1]) : null const isRTLMode = currentLang && RTL_LANG_LIST.includes(currentLang.split('-')[0]) const dirValue = isRTLMode ? 'rtl' : 'ltr' return html.replace( '<html', `<html dir="${dirValue}"${currentLang ? ` lang="${currentLang}"` : ''}` ) } } })
- 生产环境的SSR服务逻辑也要做相同处理:在收到请求时先从Cookie头解析语言,渲染HTML模板时直接把dir属性注入到
<html>标签上,不要依赖客户端二次修改。Node服务端的处理示例:
// 生产SSR服务逻辑片段 import fs from 'node:fs' const htmlTemplate = fs.readFileSync('./dist/index.html', 'utf-8') app.get('*', (req, res) => { const cookieHeader = req.headers.cookie || '' const langMatch = cookieHeader.match(new RegExp(`${LANG_COOKIE_KEY}=([^;]+)`)) const currentLang = langMatch ? decodeURIComponent(langMatch[1]) : null const isRTLMode = currentLang && RTL_LANG_LIST.includes(currentLang.split('-')[0]) const dirValue = isRTLMode ? 'rtl' : 'ltr' // 注入dir属性后的最终模板 const renderedTemplate = htmlTemplate.replace( '<html', `<html dir="${dirValue}"${currentLang ? ` lang="${currentLang}"` : ''}` ) // 后续走正常的SSR内容渲染、HTML返回流程即可 // ... })
额外提示:如果项目引入了第三方UI组件库,记得同步开启组件库自带的RTL适配配置,避免组件样式方向和页面设置不匹配。
内容的提问来源于stack exchange,提问作者jumpo marketing
相关产品推荐
相关产品推荐

