文章目录
实践目标 - 权限 SDK
今天我们要封装一个「权限 SDK」用于 React + Rollup(或者 Vite) + TypeScript 项目,这是一个非常实用的场景,特别是在中后台系统中。
这类 SDK 通常用于:
- 获取当前用户权限信息(如菜单、按钮、资源权限等)
- 权限校验(如是否能访问页面、是否展示某个按钮)
- 提供权限判断方法或指令式组件(如
<Auth>
、useAuth
)
权限 SDK 要解决的问题
- 获取用户权限数据(通常是数组,如
['page.view', 'user.edit']
) - 提供权限校验方法(如
hasPermission('user.edit')
) - 提供 React Context 和组件支持(如
permissionContext
,<Auth check="user.edit" />
) - 能根据权限隐藏/禁用页面内容或组件
- 可扩展、类型安全、低耦合
支持拓展的点
- 自动拉取权限接口
fetchPermissions()
,并结合用户登录 - 增加权限校验模式(全匹配 / 任一匹配)
- 添加权限模式(
read-only
,edit-only
) - 针对多个项目做微前端适配
- 权限缓存(localStorage/sessionStorage)
- 添加 debug 模式和日志输出
实践:基于现代打包工具 Vite
Vite 可能是现在前端更常用的工具,所以我们接下来会选择它来具体实践。当然也推荐使用 Rollup。
第一步:创建目录
如下目录是使用 vite 构建命令自动生成的基于 React+Typescript 的项目,其中我们新增了:
- index.ts
- permissionContext.ts
- Auth.tsx
permission-sdk/
├── src/
│ ├── index.ts # SDK 入口
│ ├── react/
│ │ ├── Auth.tsx # 权限组件
│ │ └── permissionContext.ts # 权限 Context
├── vite.config.ts # 打包配置
├── package.json
├── tsconfig.json
第二步:初始化 SDK 包信息
同样,构建命令自动生成了一份 package.json
,我们主要是修改了 name
、version
、main
、module
、types
、files
等字段。
{
"name": "@hg-data/permission-sdk",
"version": "1.3.0",
"main": "dist/index.umd.js",
"module": "dist/index.es.js",
"types": "dist/index.es.d.ts",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"files": ["dist"],
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@eslint/js": "^9.22.0",
"@types/node": "^22.14.1",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.22.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.0.0",
"typescript": "~5.7.2",
"typescript-eslint": "^8.26.1",
"vite": "^6.3.0",
"vite-plugin-dts": "^4.5.3"
},
}
注意,其中 vite-plugin-dts
是另外单独 pnpm install 的,在后续的 vite.config.ts
中会进行配置,具体使用方法可阅读 vite-plugin-dts。
第三步:SDK 源码编写
1. permissionContext 实现
import {
createContext, useContext, useReducer, JSX } from 'react';
type Action =
| {
type: 'SET_PERMISSIONS'; id: string; payload: string[] }
| {
type: 'ADD_PERMISSION'; id: string; payload: string }
| {
type: 'REMOVE_PERMISSION'; id: string; payload: string }
| {
type: 'RESET' };
type State = Record<string, string[]>