关注「索引目录」公众号,获取更多干货。
去年我用 SvelteKit 开发了一个单页应用。没什么特别的——只有几个视图,客户端导航,完全不需要服务器端渲染。应该很简单,对吧?
并非如此。SvelteKit 默认你需要服务器端渲染 (SSR)、基于文件的路由以及数据加载机制。但我并不需要这些。我只需要一个 URL 来映射到组件。
所以我开始寻找其他方法。
|
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
我看了看,心想,为什么 URL 匹配需要 44 kB 呢?
单个正则表达式技巧
Texivia 的核心思想是:大多数路由器将路由存储在数组或树中,并在每次导航时遍历它们。你有 30 条路由?这意味着每次 URL 更改时最多需要进行 30 次模式匹配。时间复杂度为 O(n)。
Texivia 采用不同的方法。当你定义路由时,它会将所有路由编译成一个包含位置分组的组合正则表达式:
/^(?:\/)|(?:\/users\/(\d+))|(?:\/about)$/
只需调用一次即可regex.exec(url)。匹配组的位置(?<id>...)会告诉你命中了哪条路由。像这样的命名捕获组仅供内部参数提取使用——路由识别本身完全基于位置。无需迭代。我最初是在几年前为一个电信项目构建的 PHP 路由器发明了这项技术。其理念很简单:正则表达式引擎是任何语言运行时中最优化的代码之一。既然只需一次调用就能将整个问题交给引擎,为什么还要自己编写匹配循环呢?
最快的代码就是你永远不会执行的代码。
API
import { Router } from 'texivia-router'
import { Home } from './pages/Home.js'
import { Counter } from './pages/Counter.js'
import { RecipeDetail } from './pages/RecipeDetail.js'
import { NotFound } from './pages/NotFound.js'
export const router = new Router([
{ path: '/', view: Home },
{ path: '/counter', view: Counter },
{ path: '/recipe/{id}', view: RecipeDetail },
{ path: '*', view: NotFound },
])
router.start()
路由是普通对象,在 TypeScript 中定义如下:
type ConfigRoute<T> = {
path: string;
view?: T;
redirect?: string;
handler?: HookType<T>;
}
动态段使用{paramName}带有可选正则表达式约束的语法,例如{id:\\d+}。
导航方式可以是程序化的,也可以是事件驱动的:
router.navigate('/about');
每次导航都会触发一个原生事件CustomEvent:
document.addEventListener('texivia', (event) => {
const { route, params } = event.detail;
// render your view however you want
});
没有虚拟 DOM,也没有框架生命周期钩子。浏览器本身就有一套事件系统——Texivia 只是利用了它。
我故意省略的内容
我没有添加的每一个功能都是经过深思熟虑的决定。
没有懒加载 API。 await import('./HeavyView.js')语言层面已经存在懒加载功能。对其进行封装只是为了增加 API 接口的抽象性。
无需获取数据。路由层不应拥有数据层。将它们混在一起会造成耦合,导致三年后迁移时非常痛苦。
无需状态管理。路由器只了解 URL,无需了解应用程序状态。
无需依赖任何框架。事件texivia包含所有必要信息。您可以将其连接到 React、Svelte、Vue、lit-html 等document.getElementById框架——路由器对此并不关心。
哲学
我在企业软件领域工作了25年以上,主要使用C++、Java、Spring Boot和性能工程。我接手的一个项目运行时间长达225分钟,我把它缩短到了90秒。方法始终如一:找出代码中不必要的功能,然后停止执行。
前端生态系统十多年来一直在反其道而行之。每个框架都想掌控你技术栈的更多部分。你的路由器负责获取数据。你的元框架会代表你决定使用服务端渲染 (SSR) 还是客户端渲染 (CSR)。
Texivia 通过一次正则表达式调用将 URL 与路由名称匹配,触发一个自定义事件,然后便不再干扰您的操作。大小约为 1.2 kB。无需再进行任何移除。
npm: npm install texivia-router
GitHub: https://github.com/ferderer/texivia
关注「索引目录」公众号,获取更多干货。

