Skip to content

feat: support global unique ID generation with SSR compatibility #3607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: ospp-2025/tiny-vue-nuxt
Choose a base branch
from

Conversation

codermmy
Copy link

feat: ✨ 支持SSR兼容的全局唯一ID生成及与Vue 3.5+ useId 的集成

动机与背景

在服务端渲染(SSR)场景下,我们原有的 guid() 工具函数依赖 Math.random() 生成ID。这会导致服务端和客户端生成的ID不一致,从而在Vue/Nuxt等框架中引发“水合不匹配 (hydration mismatch)”错误。这个问题严重影响了组件在同构应用中的稳定性和开发体验。

为了彻底解决此问题,并与Vue生态系统的最新进展保持一致,我们引入了一个全新的、SSR安全的唯一ID生成机制。

实现描述

本次更新的核心是新增了 @opentiny/vue-hooks 包下的 useId 组合式函数,旨在提供一个稳定、可靠且向后兼容的ID生成方案。
技术方案、流程可详见文档:https://www.yuque.com/yuqueyonghu5l1o0n/hvdsrk/bviuxw7zawxov2uv?singleDoc# 《全局唯一 ID 新方案》

  1. 全新的 useId 钩子:

    • SSR 安全: 通过 provide/inject 机制 (ID_INJECTION_KEY) 在应用级别共享ID生成器状态。在SSR环境下,开发者必须显式提供一个ID上下文,以确保服务端和客户端生成的ID序列完全一致,从而避免水合问题。如果未提供,将在服务端打印警告提示。
    • 兼容 Vue 3.5+: 新钩子会自动检测当前Vue版本。当版本大于等于3.5时,将优先使用Vue框架内置的 useId API,以实现最佳的框架集成和未来维护性。对于旧版本,则平滑降级至我们自己的实现。
    • 向后兼容: useId 被设计为 guid() 的无缝替代品。我们已经将内部受影响的组件(如 Autocomplete, CollapseItem, Dropdown, Popover, Tooltip 等)从 guid() 切换到了 useId,确保了功能的一致性且无破坏性变更。
  2. 安全性增强:

    • 更新了 @opentiny/utils 中的 random 函数,在客户端环境下使用更安全的 globalThis.crypto.getRandomValues API来生成随机数。
  3. 代码重构:

    • 调整了 xss 库的导入方式,以解决潜在的模块互操作性问题。

使用方法 (针对SSR应用)

在SSR应用(如Nuxt项目)中使用TinyVue时,你需要在应用的入口处配置ID生成器,以确保ID的稳定性:

// main.js or app.js
import { createApp } from 'vue'
import App from './App.vue'
import { ID_INJECTION_KEY } from '@opentiny/vue-hooks'

const app = createApp(App)

// 为了确保SSR ID安全,请提供一个稳定的ID上下文
app.provide(ID_INJECTION_KEY, {
  prefix: 1, // 或者其他应用级别的静态数字
  current: 0,
})

app.mount('#app')

测试截图或GIF
下图为修改前的全局id在ssr场景下的id不一致报错:
image

下图为vue3.5之后的效果
4

下图为vue3.5之前的效果:
6
控制台也无水合错误
7

…Vue 3.5+ useId integration

- Implement a global unique ID generation mechanism to ensure consistent IDs across client and server rendering, preventing hydration mismatches.
- Maintain backward compatibility with existing usage scenarios; no breaking changes introduced.
- For Vue 3.5 and above, leverage the official `useId` API to align with framework conventions and reduce maintenance overhead.
- Fallback gracefully to custom ID generation logic in earlier Vue versions.
- Added warnings for SSR environments when no ID provider is configured to avoid potential hydration issues.
Copy link

coderabbitai bot commented Jul 24, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • release-*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the enhancement New feature or request (功能增强) label Jul 24, 2025
@zzcr zzcr added the ospp-2025 开源之夏2025 label Jul 24, 2025
@@ -0,0 +1,80 @@
import type { InjectionKey, Ref } from 'vue'
import { inject, getCurrentInstance, unref } from 'vue'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TinyVue同时需要兼容vue2和vue3,所以这里所有vue相关的api都需要从vue-common中引入

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TinyVue同时需要兼容vue2和vue3,所以这里所有vue相关的api都需要从vue-common中引入

get

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request (功能增强) ospp-2025 开源之夏2025
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants