npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

maishu-chitu-react

v2.0.0

Published

用 chitu 替换 react-router 的兼容层(BrowserRouter / Routes / Route / Outlet / Link / hooks)

Readme

maishu-chitu-react

chitu.js 替换 react-router 的兼容层: 业务代码里 import { ... } from 'react-router' / 'react-router-dom' 基本不用改, 底层路由与页面管理由 chitu 的 PageMaster 承担。

兼容层实现的是目标项目实际用到的 react-router 子集(见下方「已实现 / 未实现」), 并非 react-router v6 的全部 API;path="*" 这类写法需按本文的模板语法调整。

自本版本起,本包只提供 react-router 兼容层。 不再导出 chitu 原生用法的 Application / PageProps / dataLoader —— 需要旧 API 的项目请锁定旧版本。

特性

  • 声明式路由零改动<BrowserRouter> / <Routes> / <Route> / <Outlet> / <Link> / <NavLink> 与 react-router 同形。
  • 真正的嵌套 Outlet:每个 <Outlet> 挂一个 chitu PageMaster,布局外壳始终挂载,只有子页面切换显隐。
  • 干净的 URL:地址栏就是 /admin/users 这类 pathname,不会被改写成 chitu 的 pageName 形式;一次导航 = 一条 history 记录。
  • 页面级缓存与卸载:chitu 按路由缓存页面(display:none 切换),页面关闭时自动 root.unmount() 清理副作用。
  • 路径模板与 node-shop-v2 同源:底层用 path-to-regexp(express 风格),支持 :id、花括号可选段 {/:page}/:page.css{*splat} 通配等。
  • 单一产物:整个包只有一份实现(dist/index.*),不存在多入口各带一份 context 的隐患。

安装

npm install maishu-chitu-react maishu-chitu react react-dom

maishu-chitu>=5.0.0)、react / react-dom>=18.3)为对等依赖。 兼容层本身不依赖 maishu-chituApplication,只使用 PageMaster

接入

// 直接用包名,不再需要 react-router / react-router-dom
import { BrowserRouter, Routes, Route, Outlet, Link, NavLink } from 'maishu-chitu-react';

旧项目迁移时把说明符批量替换即可(from "react-router" / from "react-router-dom"from "maishu-chitu-react")。 用 importmap 的项目只需映射 maishu-chitu-reactmaishu-chitu 两项。

../react-router./react-router-dom 三个入口都指向同一份 dist/index.*, 混用也不会出现「两份 React context」的问题(因此 maishu-chitu-react/react-router 这类旧写法仍可用)。

用法

import {
  BrowserRouter, Routes, Route, Outlet,
  Link, NavLink,
  useParams, useLocation, useNavigate, useSearchParams,
  generatePath,
} from 'maishu-chitu-react';

function Layout() {
  return (
    <div>
      <NavLink to="/">首页</NavLink>
      <NavLink to="/products">商品</NavLink>
      {/* 子路由渲染在这里 —— 布局本身不会被重新挂载 */}
      <Outlet />
    </div>
  );
}

createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="products" element={<ProductList />} />
        <Route path="products/:id" element={<ProductDetail />} />
        <Route path="admin" element={<AdminLayout />}>
          <Route index element={<AdminHome />} />
          <Route path="users" element={<AdminUsers />} />
        </Route>
        {/* catch-all:path-to-regexp 的通配写法(不支持 react-router 的裸 `*`) */}
        <Route path="*splat" element={<NotFound />} />
      </Route>
    </Routes>
  </BrowserRouter>,
);

已实现 / 未实现

已实现(即目标项目当前使用的全部符号):

| 类型 | API | | --- | --- | | 组件 | BrowserRouter Routes Route Outlet Link NavLink | | Hooks | useParams useLocation useNavigate useSearchParams | | 函数 | generatePath | | 类型 | LinkProps NavLinkProps NavigateFunction Location |

未实现(v6 的其余 API):NavigateuseRoutesuseMatchcreateBrowserRouter / RouterProviderMemoryRouterHashRouteruseOutletContextuseNavigationTypePrompt 等。 用到这些的业务代码需要自行改造。

需要改写的写法:catch-all 的 <Route path="*" /> 在本兼容层里要写成 <Route path="*splat" /> (通配内容读 useParams().splat;若需连 / 也命中则写 "{*splat}")—— 因为底层是 path-to-regexp,它不接受 react-router 的裸 *

行为差异useLocation()hash / state / key 为近似实现;generatePath 默认对参数值做 encodeURIComponent(react-router v6 不编码)。

路由模板(path-to-regexp 语法)

| 写法 | 含义 | | --- | --- | | /product/:id | 动态段,useParams().id | | /product-list{/:pageIndex} | 可选段(无值时整段省略) | | /{home} | 可选字面量段(既匹配 / 也匹配 /home) | | /{:page} | 花括号内的参数 | | /:page.css | 带字面量后缀的参数 | | *splat | 通配(catch-all),至少一段useParams().splat 读取内容 | | {*splat} | 通配且可为空 —— 等价 react-router 的 *(能匹配 / 本身),做 404 兜底请用这个 |

模板必须是 path-to-regexp v8 语法:不支持 react-router 的 :id?(写 {/:id})与裸 *(写 {*splat}; 注意 *splat 是「必填」,根路径不会命中,别拿它当 404 兜底)。 迁移已有项目时把这些写法改掉即可;服务端若也用 v8(如本项目配套的 node-shop-v2),两边模板可保持一致。

参数生成(generatePath)与匹配同源:必填段缺值抛错,通配段按 / 切分后拼接。

页面生命周期与性能

  • 页面按路由缓存(同一路由换参数不会新建节点),DOM 节点数 = 路由种类数。
  • 隐藏页面通过 display:none 切换,不参与布局与绘制,仅占用内存。
  • 页面关闭时 React rootunmount(),组件卸载并清理副作用。
  • 隐藏(未关闭)页面的 React 副作用仍可能后台运行,请在组件 useEffect 中做好清理。

开发

npm run build     # esbuild 打包 dist(cjs + mjs)+ tsc 生成类型声明
npm run start     # 启动本地 demo(PORT 环境变量,默认 8080)
npm test          # jest 运行测试(jsdom 环境)

demo 见 demo/rr-main.tsx:两级嵌套 Outlet、动态参数、query 读写、返回、catch-all, 面板会显示外壳挂载时间戳与浏览器地址栏,用于验证「外壳保持挂载 / 地址栏未被改写」。

许可证

MIT