跳过主内容
Deno 2 终于来了 🎉️
了解更多
Deno dinosaur flying with a lemon balloon

Fresh 1.1 - 自动 JSX、插件、DevTools 等

Fresh 是一个新的 Deno 全栈 Web 框架。默认情况下,使用 Fresh 构建的网页不会向客户端发送任何 JavaScript。该框架没有构建步骤,这使得开发体验和部署时间提高了数量级。

今天我们发布了 Fresh 的下一个重要版本。1.1 版本带来了许多重要的改进,使 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 支持

您现在可以使用适用于 ChromeFirefoxEdge 的 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 制作”徽章,你可以将其添加到你的网站或项目自述文件中。徽章也有深色变体。

Made with Fresh

Made with Fresh(dark)

按照以下说明将徽章添加到你的项目:https://github.com/denoland/fresh#badges