一个 JavaScript 文件中的整个网站
这个网站是一个相当标准的演示网站;一个包含指向不同页面链接的网站。没什么特别的,除了整个网站都包含在一个 JavaScript 文件中,并且在边缘,靠近用户的地方,即时动态渲染。
路由相当简单:我们使用了router
模块,它底层使用了URLPattern
进行模式匹配。
/** @jsx h */
/// <reference no-default-lib="true"/>
/// <reference lib="dom" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />
import { serve } from "https://deno.land/std@0.140.0/http/server.ts";
import { router } from "https://crux.land/router@0.0.11";
import { h, ssr } from "https://crux.land/nanossr@0.0.4";
const render = (component) => ssr(() => <App>{component}</App>);
serve(router(
{
"/": () => render(<Landing />),
"/stats": () => render(<Stats />),
"/bagels": () => render(<Bagels />),
},
() => render(<NotFound />),
));
我们有3个路径:/
用于主页,/stats
用于一些统计数据,以及/bagels
用于展示我们销售的各种百吉饼。我们还有一个备用处理程序(代码片段中的最后一个参数),当没有路径匹配时会调用它,作为404页面。这些都是通过标准库提供的serve
函数来服务的。
为了渲染 JSX,我们使用了nanossr
,它是一个小型服务器端渲染器,底层使用twind
进行样式设置。通过使用ssr
函数来调用它,该函数会传入一个应返回 JSX 的回调。这个ssr
函数会返回一个Response
。我们创建了一个render
函数,以避免大量代码重复,从而使代码更整洁。
但在这一切之前,你可能已经注意到了一些奇怪的注释。让我们来一一了解它们。
/** @jsx h */
:这个 pragma 告诉 Deno 我们想要使用哪个函数来转译 JSX。/// <reference no-default-lib="true"/>
:Deno 默认启用各种 TypeScript 库;通过此注释,我们告诉它不要使用这些库,而只使用我们手动指定的库。/// <reference lib="dom" />
、/// <reference lib="dom.asynciterable" />
和/// <reference lib="deno.ns" />
:这些库提供了各种类型定义。其中dom
为我们提供了与 DOM 相关的各种类型定义,而dom.asynciterable
定义了需要异步迭代器的函数,因为这些函数在撰写本文时未包含在常规的dom
库中。deno.ns
库为我们提供了Deno.*
命名空间下任何函数和类的类型定义,例如Deno.readFile
。你可以在手册中阅读更多关于可用库的信息。
让我们看看一些实际代码;在前面的代码片段中,你可能已经注意到我们把所有的路由组件都封装在一个App
组件中。它的定义如下:
function App({ children }) {
return (
<div class="min-h-screen">
<NavBar />
{children}
</div>
);
}
它相当紧凑:它返回一个 div,其中包含我们的NavBar
,它是页面顶部的菜单导航。我们正在进行服务器端模板化,使用与客户端相同的方式在不同页面之间共享组件。

托管在Deno Deploy上,这个小型网站能够实现完美的页面速度得分。该网站通过遍布全球29个数据中心的加密 HTTP 从任播 IP 地址提供服务,完全由 Deno 管理,并将无限期免费提供。
这里提到的所有内容都可以在实验场中查看。