Fresh 1.1 - 自动 JSX、插件、DevTools 等
Fresh 是一个新的 Deno 全栈 Web 框架。默认情况下,使用 Fresh 构建的网页不会向客户端发送任何 JavaScript。该框架没有构建步骤,这使得开发体验和部署时间提高了数量级。
今天我们发布了 Fresh 的下一个重要版本。1.1 版本带来了许多重要的改进,使 Fresh 更易于使用、更快,并且更实用。本版本的一些亮点
- 自动 JSX
- 插件
- Preact Signals 支持
- Preact DevTools 支持
- 显式渲染 404 页面
- 堆叠中间件
- 实验性
Deno.serve
支持 - 展示和“使用 Fresh 制作”徽章
要创建新的 Fresh 项目,您可以运行
$ deno run -A -r https://fresh.deno.dev my-app
要将项目更新到最新版本的 Fresh,请从项目根目录运行更新脚本
$ deno run -A -r https://fresh.deno.dev/update .
除了更新 Fresh 及其依赖项之外,此脚本还可以将代码修改应用于您的代码库,以使其与 Fresh 项目的最新建议保持一致。另请查看 概念:更新 文档页面。
自动 JSX
新的项目现在默认设置为使用自动模式 JSX。这意味着您不再需要 /** @jsx h */
标记和 import { h } from "preact";
在所有文件的顶部。这是开发体验的重大改进,并消除了新用户常见的错误来源。
- /** @jsx h */
- import { h } from "preact";
export default function AboutPage() {
return (
<main>
<h1>About</h1>
<p>This is the about page.</p>
</main>
);
}
现有项目可以使用 Fresh 更新脚本中的代码修改来更新以使用自动模式。或者,可以通过将以下几行添加到项目根目录的 deno.json
文件中来手动启用它
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
执行此操作后,您必须从您的 JSX/TSX 文件中删除所有 /** @jsx h */
标记和 import { h } from "preact";
导入。自动模式和非自动模式不能在同一个项目中混合使用。
插件
插件是一种新的扩展 Fresh 功能的方法,无需对 Fresh 本身进行侵入式更改。现在,插件只能用于协调渲染并将样式和脚本注入到渲染后的 HTML 中。这对于像 twind 这样的样式框架很有用。这也可以用于执行诸如将 Google Analytics 脚本注入页面或全局加载 Web 组件 之类的操作。
插件通过 plugins
属性在传递给 main.ts
文件中 start
函数的选项包中定义。
这只是插件的第一个迭代。未来版本将添加更多插件可以用来扩展 Fresh 功能的钩子。将来,插件将能够向项目中添加新的路由、中间件和岛屿。
插件的文档可在 概念:插件 文档页面中找到。
截至目前,只有一个官方插件可用。随着插件系统的功能扩展,将来会添加更多插件。
twind
插件
官方 Twind 是一个小型 Tailwind-in-JS 实现,它可以根据 JSX 中使用的类实时生成 CSS。以前的 Fresh 版本有一个选项可以在项目初始化期间自动为您配置 Twind,但这会导致大量的样板代码。
借助新的插件系统,我们现在为 Twind 提供了一个第一方 Fresh 插件。此插件会自动为您配置 Twind,以最大程度地减少项目中的样板代码。使用它非常简单,如下所示
// main.ts
import { start } from "$fresh/server.ts";
import manifest from "./fresh.gen.ts";
+ import twindPlugin from "$fresh/plugins/twind.ts";
+ import twindConfig from "./twind.config.js";
await start(manifest, {
+ plugins: [
+ twindPlugin(twindConfig),
+ ],
});
使用此新插件,在项目中使用 Twind 类变得更加简单。以前,您必须从 twind
模块导入 tw
函数,并将所有类名包装在其中。现在,您只需在 JSX 组件中直接指定类名,插件会处理其余工作。
// pages/index.tsx
- import { tw } from "@twind";
export default function IndexPage() {
return (
- <h1 class={tw`text-4xl font-bold`}>Hello, world!</h1>
+ <h1 class="text-4xl font-bold">Hello, world!</h1>
);
}
借助新插件,Twind 在客户端渲染期间也能更加可靠地工作,并且能够更好地解决服务器渲染和客户端渲染样式表之间的冲突。
项目初始化脚本已更新以使用新的 Twind 插件,现在还生成所有必需的文件,以便能够使用 Twind VSCode 扩展。
更新脚本可用于通过代码修改将您的项目更新为使用新的 Twind 插件。
Preact Signals 支持
新的 Fresh 项目现在自动设置为使用新的 Preact Signals。Signals 是 Preact 的一种新的反应式状态管理原语。它们的设计比钩子和上下文更快,同时更易于使用。
以下是用信号而不是钩子实现的基本“计数器”组件的示例。
import { useSignal } from "@preact/signals";
import { Button } from "../components/Button.tsx";
interface CounterProps {
start: number;
}
export default function Counter(props: CounterProps) {
const count = useSignal(props.start);
return (
<div>
<p>{count}</p>
<button onClick={() => count.value--}>-1</button>
<button onClick={() => count.value++}>+1</button>
</div>
);
}
Signals 还提供了一种极好的方法来管理 Fresh 项目中多个岛屿之间的共享状态。查看 使用 Signals 的 Fresh 演示,了解它是如何工作的。
对于现有项目,更新器脚本会自动将 @preact/signals
依赖项添加到您的导入映射中。您也可以手动将依赖项添加到导入映射中 - 只需确保还将 preact-render-to-string
更新为 >=5.2.3。
Preact DevTools 支持
您现在可以使用适用于 Chrome、Firefox 和 Edge 的 Preact DevTools 扩展来检查 Fresh 项目的组件树。
这是一种调试岛屿问题和了解 Preact 如何渲染组件的好方法。
要使用此功能,不需要任何额外配置。只需更新到最新版本的 Fresh 并为您的浏览器安装 Preact DevTools 扩展。
此功能仅在开发期间可用。在生产环境中,Preact DevTools 集成不可用。这样做是为了减少发送到客户端的 JavaScript 数量。
感谢 Marvin Hagemeister 为此功能做出贡献,以及 改进基于岛屿的 hydration 的 Preact DevTools 支持。
显式渲染 404 页面
现在可以从路由处理程序显式渲染 404 页面。如果您想根据数据库查询的结果渲染 404 页面,或者在路由处理程序中进行更复杂的路由,这将非常有用。
要渲染 404 页面,只需从你的路由处理程序中调用 `ctx.renderNotFound()` 而不是调用 `ctx.render()` 或返回自定义的 `Response` 对象。就像使用 `ctx.render()` 一样,你可以在将返回的 `Response` 对象发送到客户端之前修改它。
// routes/index.ts
export const handler: Handlers = {
GET(req, ctx) {
const url = new URL(req.url);
const id = url.searchParams.get("id");
if (!id) return ctx.renderNotFound(); // return a 404 page if no id is provided
return ctx.render({ id });
},
};
// ... page component here ...
感谢 Steven Yung 为此功能做出贡献。
堆叠中间件
现在可以为单个中间件路由设置多个中间件函数。如果你有多个不同的中间件函数,它们都应该应用于给定的匹配器,这将很有用。这可以通过从中间件文件导出数组而不是单个函数来实现。
以下是一个包含两个中间件函数的中间件模块的示例:一个用于执行日志记录,另一个用于向响应添加计时标题。
// routes/_middleware.ts
export const handler = [
timing,
logging,
];
async function timing(
_req: Request,
ctx: MiddlewareHandlerContext,
): Promise<Response> {
const start = performance.now();
const res = await ctx.next();
const end = performance.now();
const dur = (end - start).toFixed(1);
res.headers.set("Server-Timing", `handler;dur=${dur}`);
return res;
}
async function logging(
req: Request,
ctx: MiddlewareHandlerContext,
): Promise<Response> {
const res = await ctx.next();
console.log(`${req.method} ${req.url} ${res.status}`);
return res;
}
感谢 @ahuigo 为此功能做出贡献。
实验性 `Deno.serve` 支持
Deno v1.25 为 Deno 添加了一个新的高性能 HTTP 服务器。你可以在 Deno 1.25 版本说明 中阅读更多相关信息。它仅在 Deno v1.25 及更高版本中可用,并且在使用 `--unstable` 标志运行时可用。
此版本的 Fresh 为使用新的 `Deno.serve` API(而不是现有的 `std/http` 服务器)添加了实验性支持。`Deno.serve` 尚未稳定,因此你不应在生产环境中使用它。`Deno.serve` 在 Deno Deploy 上也不可用,因为它仍在实验阶段。
要启用新的服务器,你必须在传递给 `main.ts` 文件中 `start()` 方法的选项包中指定 `experimentalDenoServe: true`。
展示和“使用 Fresh 制作”徽章
Fresh 主页现在有一个 展示区,你可以在其中找到使用 Fresh 的项目列表。如果你有一个使用 Fresh 的项目,请 将其添加到列表中!
除了展示区之外,我们现在还提供一个“使用 Fresh 制作”徽章,你可以将其添加到你的网站或项目自述文件中。徽章也有深色变体。
按照以下说明将徽章添加到你的项目:https://github.com/denoland/fresh#badges