背景与目标
企业后台系统长期被认为“无需 SEO”,但当系统同时承载官网入口、营销落地页、公开查询等场景时,SEO 就变成基础能力。我负责的系统以 Vue3 + Vite + Element Plus 为主,核心目标是让首页在搜索引擎与社交分享中更易被发现,同时不影响现有路由与权限逻辑。
目标拆成三类:
- 搜索可见性:完善标题、描述、关键词、robots、canonical、结构化数据。
- 分享表现:补充 OpenGraph / Twitter 卡片。
- 可维护性:文案 i18n 化,避免硬编码。
现状问题
当时首页存在这些明显短板:
- 只有默认标题,没有 description / keywords / canonical。
- SPA 路由切换后,SEO 元信息不会更新。
- robots.txt 格式不规范,导致校验报错。
- 多语言文案与 SEO 文字分离,无法统一维护。
落地方案总览
整体做法是把 SEO 注入放到路由后置守卫里,集中处理首页元信息,同时把文案放入 i18n 配置,保证中文/英文统一入口,最后修复 robots.txt 的格式问题。
具体点包括:
- 路由切换后注入 title / meta / canonical / JSON-LD。
- 首页与非首页分开处理。
- i18n 中维护 SEO 文案。
- robots.txt 规范化。
关键实现
1) 路由后置守卫统一注入 SEO
我们在路由 afterEach 中调用 applySeoMeta,集中管理 SEO 逻辑,避免在页面内部分散配置。
function applySeoMeta(to: RouteLocationNormalized) {
const siteName = i18n.global.t('common.seo.siteName')
const isHome = to.name === 'Index' || to.meta?.i18nKey === 'index'
const metaTitle = to.meta?.i18nKey
? i18n.global.t(`router.${String(to.meta.i18nKey)}`, String(to.meta.title || ''))
: String(to.meta?.title || '')
const title = isHome
? i18n.global.t('common.seo.homeTitle', { siteName })
: (metaTitle ? `${metaTitle} - ${siteName}` : String(siteName))
document.title = title
const locale = i18n.global.locale.value
document.documentElement.lang = locale === 'zh' ? 'zh-CN' : 'en'
if (!isHome) {
return
}
const description = i18n.global.t('common.seo.homeDescription', { siteName })
const keywords = i18n.global.t('common.seo.homeKeywords', { siteName })
const canonical = `${window.location.origin}/`
setMetaTag('description', description)
setMetaTag('keywords', keywords)
setMetaTag('robots', 'index,follow')
setMetaProperty('og:title', title)
setMetaProperty('og:description', description)
setMetaProperty('og:type', 'website')
setMetaProperty('og:url', canonical)
setMetaProperty('og:site_name', String(siteName))
setMetaTag('twitter:card', 'summary')
setMetaTag('twitter:title', title)
setMetaTag('twitter:description', description)
setCanonicalUrl(canonical)
setStructuredData({
'@context': 'https://schema.org',
'@type': 'WebSite',
'name': siteName,
'url': canonical,
description,
'potentialAction': {
'@type': 'SearchAction',
'target': `${window.location.origin}/#/search-service/quick-search?q={search_term_string}`,
'query-input': 'required name=search_term_string',
},
})
}
这段逻辑将 title、description、keywords、robots、OG、Twitter、canonical、JSON-LD 全部统一生成,保证首页搜索信息完整。
2) i18n 统一维护 SEO 文案
把 SEO 文案放入 i18n 中,避免硬编码中文/英文,方便后续内容运营调整。
seo: {
siteName: '中外运集装箱运输客户服务平台',
homeTitle: '{siteName} - 订舱、船期、货物跟踪一站式平台',
homeDescription: '{siteName} 提供订舱管理、船期查询、货物跟踪与费用查询服务,提升物流协同效率。',
homeKeywords: '{siteName},订舱管理,船期查询,货物跟踪,集装箱运输,物流服务',
},
英文版本同样结构,避免维护成本翻倍。
3) robots.txt 修复与规范
robots.txt 必须格式正确,不然搜索引擎直接忽略。我们按规范添加基础规则,并限制静态资源目录爬取:
User-agent: *
Allow: /
Disallow: /assets/
Disallow: /favicon.ico
Disallow: /img/
Disallow: /js/
Disallow: /css/
Disallow: /fonts/
Disallow: /svg/
Disallow: /index.html
如果首页是唯一可公开抓取的页面,这套规则更安全,避免内部页面误入索引。
验证与检查清单
为了避免“改完就忘”,我会按以下步骤验证:
- 查看页面源代码,确认 title/description/keywords/OG/Twitter/canonical 是否存在。
- 用 Lighthouse / PageSpeed Insights 检查 SEO 分数。
- 用 Google Search Console 的 robots.txt 测试工具检查规则有效性。
- 分享到微信/企业 IM,观察卡片标题与描述是否正确。
实践中的经验点
- SEO 逻辑应集中在路由层,而不是分散在页面组件里。
- SEO 文案必须 i18n 化,否则多语言很难维护。
- robots.txt 的规则要兼顾“抓取控制”和“页面可见性”,过严会导致首页也被误阻。
- SPA 的 SEO 不是万能药,公开页面建议结合服务端渲染或静态化,但在内部系统中“基础 SEO”已经能覆盖大多数需求。
结语
这次优化的重点不是“追求极致 SEO”,而是把最关键的基础能力补齐,让系统在搜索、分享与合规层面更稳。对于 Vue3 SPA 来说,靠路由后置守卫 + i18n 文案集中管理是一条成本最低、收益稳定的路径。后续如果首页内容稳定且面向公开流量,再考虑 SSR 或预渲染会更合适。
如果你也在做企业级后台项目,建议从这套基础 SEO 开始,先把“能被发现、能被分享、能被正确识别”解决掉,再谈更复杂的优化。