@mini-dev/unipath
v0.1.0
Published
Generate scene-scoped URLs from (name, extraParams), decoupled from page path resolution
Maintainers
Readme
@mini-dev/unipath
根据 (name, type) 生成场景化统一 URL 的轻量工具库。
1. 背景
小程序页面分享(以及其他需要生成"入口 URL"的场景,如 push、深链接)默认携带当前页面的真实 path,这会带来两个问题:
- 分享出去的链接与页面文件路径强绑定,后续重构页面目录会导致旧链接失效;
- 不同场景生成 URL 的方式散落在各处,格式不统一。
UniPath 的核心思路:用一个稳定的 name 代替易变的 path 编码进 URL 的 query,name 到真实页面路径的解析完全交给落地页自己负责,与本库无关。
2. 定位
本库只做一件事:根据 (name, extraParams) 生成一个统一格式的 URL 字符串。
- 不感知"分享"等具体业务语义,不区分场景的具体含义(
type只是一个不透明字符串); - 不做 name → path 的映射/注册/查询——这是落地页或业务方自己的职责;
- 不解析 URL、不调用任何小程序导航 API(
navigateTo等); - 不做跨平台检测,是一个纯字符串处理工具,可以在任意 JS 运行时使用。
3. 用法
一个 UniPath 实例只服务于一种固定场景:构造时绑定 basePath(落地页路径)、type(场景标识)与 paramsFn(query 编码规则),之后反复调用 buildUrl 生成不同 name 对应的 URL。
import { UniPath } from '@mini-dev/unipath';
// 分享场景专用实例
const shareUrl = new UniPath({
basePath: 'pages/index/index',
type: 'share',
paramsFn: (name, type) => ({ to: name, type })
});
shareUrl.buildUrl('detail');
// => 'pages/index/index?to=detail&type=share'
shareUrl.buildUrl('detail', { id: 123 });
// => 'pages/index/index?to=detail&type=share&id=123'
shareUrl.buildUrl('detail', { to: 'other' });
// => 'pages/index/index?to=other&type=share' (extraParams 覆盖 paramsFn 同名 key)paramsFn 完全决定编码规则,库不做任何约束——比如可以忽略 type 参数,只编码 name:
// push 场景专用实例,不需要编码 type
const pushUrl = new UniPath({
basePath: 'pages/entry/index',
type: 'push',
paramsFn: (name) => ({ page: name })
});
pushUrl.buildUrl('home');
// => 'pages/entry/index?page=home'buildUrl 的执行流程
- 调用
paramsFn(name, type)得到基础键值对; - 与
extraParams合并(extraParams同名 key 覆盖paramsFn结果); - 序列化成 query string;
- 若合并后的参数为空,直接返回
basePath;否则按basePath是否已含?选择?或&拼接。
query 序列化规则
null/undefined编码为空字符串;0/false等假值原样保留(0 → '0',false → 'false');- key 和 value 默认均经过
encodeURIComponent处理,可通过encodeKey/encodeValue分别关闭。
// 关闭 value 的 encodeURIComponent(比如 value 已经是合法的 URL 片段)
const rawValueUrl = new UniPath({
basePath: 'pages/index/index',
type: 'share',
paramsFn: (name, type) => ({ to: name, type }),
encodeValue: false
});
rawValueUrl.buildUrl('detail', { back: 'pages/a/a?x=1' });
// => 'pages/index/index?to=detail&type=share&back=pages/a/a?x=1'4. API
type ParamValue = string | number | boolean | null | undefined;
type ParamRecord = Record<string, ParamValue>;
type ParamsFn = (name: string, type: string) => ParamRecord;
interface UniPathOptions {
basePath: string; // 落地页的固定路径
type: string; // 当前实例代表的场景,构造后不变
paramsFn: ParamsFn; // 编码规则,由调用方完全决定
encodeKey?: boolean; // 是否对 query 的 key 做 encodeURIComponent,默认 true
encodeValue?: boolean; // 是否对 query 的 value 做 encodeURIComponent,默认 true
}
class UniPath {
constructor(options: UniPathOptions);
buildUrl(name: string, extraParams?: ParamRecord): string;
}basePath、type、paramsFn 均为必填,encodeKey/encodeValue 可选,默认均为 true。
5. 安装
npm i @mini-dev/unipath发布产物同时提供 CommonJS 与 ESM 两份构建,按项目的构建方式任选一种写法即可:
// CommonJS
const { UniPath } = require('@mini-dev/unipath');// ES Module
import { UniPath } from '@mini-dev/unipath';如需在小程序 IDE 中使用,需先执行「构建 npm」以将 @mini-dev/unipath 构建到 miniprogram_npm/。
6. 不在范围内
- name → path 的映射/注册/查询(由落地页或业务方自己维护);
- URL 解析(从 query string 中解析出
to/type等字段); - 任何小程序导航 API 调用(
navigateTo、redirectTo等); - 跨平台检测(本库是纯字符串工具,不感知运行环境)。
7. 开发
npm install
npm test # 单元测试
npm run build # 构建 dist/cjs 与 dist/esm
npm run test:dist # 验证构建产物在 CJS/ESM 下均可正常加载