一个完整的网站,只需一个 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/[email protected]/http/server.ts";
import { router } from "https://crux.land/[email protected]";
import { h, ssr } from "https://crux.land/[email protected]";
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,在 div 中包含我们的 NavBar
,这是我们页面顶部的菜单导航。我们正在服务器端进行模板化,使用与客户端相同的语言在不同页面之间共享组件。
托管在 Deno Deploy 上,这个小型网站能够实现 完美的页面速度评分。通过全球 29 个数据中心的加密 HTTP 从 anycast IP 地址提供服务,该网站完全托管,并且将在无限期内免费提供。
这里提到的所有内容都可以在 游乐场 上查看。