Skip to content

@sheng/no-ssr-unsafe-module-state ​

提醒 Nuxt use* composable 里的模块级可变状态必须显式声明 SSR 策略。

所属 config ​

  • nuxt-ssr-state:Nuxt 模块级 SSR 不安全状态边界。

为什么需要 ​

Nuxt 服务端渲染下,模块级可变状态可能在请求之间共享。业务数据、页面局部状态和跨组件 DOM 桥接应该有不同 owner;如果确实需要模块级 source,就要让目录或文件名显式表达 client-only 边界。

会提示 ​

ts
const tabBarIsSticky = ref(false)
const scrollRootElement = shallowRef<HTMLElement | null>(null)

export default function useProfileStickyState() {
  return {
    scrollRootElement,
    tabBarIsSticky,
  }
}

推荐写法 ​

可序列化业务数据优先放到 Pinia、useState 或请求缓存。页面局部状态放在组件 setup 内创建:

ts
export default function useProfileStickyState() {
  const tabBarIsSticky = ref(false)
  const scrollRootElement = shallowRef<HTMLElement | null>(null)

  return {
    scrollRootElement,
    tabBarIsSticky,
  }
}

跨组件 DOM 桥接如果确实需要模块级 source,需要放进项目约定的 client-only 边界,并让 SSR 返回 no-op。

适用边界 ​

优先在已经采用 nuxt-ssr-state 约定的项目里开启。历史代码较多时,先按目录或文件范围试跑,确认误报成本可以接受。

相关阅读 ​

这条规则对应中文文章 别等 review 才想起 SSR:给 Nuxt 模块级 composable 补上静态护栏。文章里的核心口径是:模块级状态先按可序列化业务数据、页面局部状态、跨组件 DOM 桥接分类,再分别选择 Pinia / useState、组件 setup 或显式 client-only source。

在线试一下 ​

接入方式 ​

@sheng/eslint-plugin 的内置 config 会以 warn 开启这条规则。需要单独配置时,可以这样写:

js
import sheng from '@sheng/eslint-plugin'

export default [
  {
    plugins: {
      '@sheng': sheng,
    },
    rules: {
      '@sheng/no-ssr-unsafe-module-state': 'warn',
    },
  },
]

选项 ​

这条规则支持 options,具体 schema 以规则实现和测试用例为准。补充或调整选项时,同步更新本页示例。

维护入口 ​

  • 规则源码:src/rules/no-ssr-unsafe-module-state/index.mjs
  • 规则短说明:src/rules/no-ssr-unsafe-module-state/README.md
  • 测试用例:tests/unit/architecture/

基于 MIT 协议发布。