用Fresh构建全栈应用的踩坑经验与核心技巧分享

设计师菲菲 框架 阅读 1,528
赞 16 收藏
二维码
手机扫码查看
反馈

先看效果,再看代码

最近在折腾 Fresh,Denoland 推出的全栈框架。说实话,这玩意儿刚上手时真让我头疼了一阵子,但用熟了之后感觉还挺香的。如果你也在找一个轻量、快速、不依赖太多复杂配置的框架,建议直接试试 Fresh。

用Fresh构建全栈应用的踩坑经验与核心技巧分享

比如我做的一个小项目,API 和前端打包在一起,整个项目不到 500KB,启动速度飞快。核心代码就这几行:

import { start } from "https://deno.land/x/fresh@1.1.2/server.ts";

await start("./main.ts", {
  port: 8000,
});

这个 start 方法会加载你的 main.ts 文件,然后运行一个服务,默认监听 8000 端口。简单吧?但别急,接下来才是重点。

路由和组件渲染,这里注意下

Fresh 的路由设计有点特别,它是基于文件系统的,也就是说你的文件夹结构决定了路由。举个例子:

/routes/
  index.tsx
  about.tsx
  blog/
    [slug].tsx

上面这种结构会自动生成以下路由:

  • / 对应 index.tsx
  • /about 对应 about.tsx
  • /blog/:slug 对应 [slug].tsx

亲测有效,但有个坑点需要注意:文件命名必须严格遵守规则。比如 [slug].tsx 这种动态路由,中括号是强制要求的,写成其他格式会报错。踩过好几次坑,折腾了半天才发现是命名问题。

再说说组件渲染。Fresh 默认使用 Preact(React 的轻量版),所以如果你熟悉 React,上手基本没啥难度:

import { IS_BROWSER } from "$fresh/runtime.ts";

export default function About() {
  return (
    <div>
      <h1>About Page</h1>
      <p>{IS_BROWSER ? "Running in browser" : "Rendering on server"}</p>
    </div>
  );
}

这里的 IS_BROWSER 是个很有用的变量,可以判断当前代码是在服务器端还是客户端运行。建议多用这个变量来优化性能,比如只在客户端加载某些脚本。

这个场景最好用:前后端一体化开发

如果你需要一个前后端一体化的框架,Fresh 真的是个不错的选择。它内置了对 Deno 的支持,所以你可以直接用 TypeScript 写 API,而且不需要额外的构建工具。

举个实际例子,我之前写了一个博客系统,后端直接从数据库取数据,然后通过 API 返回给前端:

// /routes/api/posts.ts
import { serve } from "https://deno.land/std@0.167.0/http/server.ts";

export const handler = async (req: Request) => {
  const posts = await fetch("https://jztheme.com/api/posts").then((res) => res.json());
  return new Response(JSON.stringify(posts), {
    headers: { "Content-Type": "application/json" },
  });
};

前端调用也很简单:

const response = await fetch("/api/posts");
const posts = await response.json();
console.log(posts);

整个流程非常流畅,完全不需要额外的配置。但这里提醒一下,如果你的 API 需要处理复杂的逻辑,记得把逻辑抽离到单独的模块中,保持代码清晰。否则后期维护起来会很痛苦。

踩坑提醒:这三点一定注意

虽然 Fresh 很强大,但也有一些小坑需要注意,尤其是刚上手的时候:

  1. Deno 版本问题:Fresh 对 Deno 的版本要求比较严格,建议每次升级前先看官方文档的说明。我有一次直接升级 Deno,结果发现 Fresh 的某些功能直接挂了。
  2. 热更新有时不生效:开发环境下,修改文件后偶尔会出现热更新失效的情况。解决方法是手动重启服务,虽然麻烦,但至少能保证正常运行。
  3. 缺少成熟的生态支持:相比于 Next.js 或 Nuxt.js,Fresh 的社区还不够大,很多第三方库的支持不够完善。比如我想用某个 UI 库,结果发现它依赖 Webpack,而 Fresh 不支持 Webpack。

高级技巧:自定义中间件和插件

Fresh 支持自定义中间件,这在处理跨域、日志记录等场景时非常有用。比如我写了一个简单的日志中间件:

export const handler = async (req: Request, ctx: any) => {
  console.log(Request received: ${req.url});
  const resp = await ctx.next();
  console.log(Response sent: ${resp.status});
  return resp;
};

把这个中间件加到你的路由中,就可以轻松实现请求和响应的日志记录。

另外,Fresh 还支持插件机制,可以通过 config.ts 文件进行配置:

import { defineConfig } from "$fresh/server.ts";

export default defineConfig({
  plugins: [
    // 自定义插件
  ],
});

不过插件这块目前还在发展中,功能相对有限。如果你有特殊需求,可能需要自己动手实现。

总结一下,聊聊拓展用法

总的来说,Fresh 是一个非常轻量且高效的框架,尤其适合那些不想被复杂配置束缚的开发者。它的设计理念很现代,前后端一体化、无构建工具、基于文件系统的路由,这些特性都非常吸引人。

当然,Fresh 目前还在快速发展中,有些功能可能还不够成熟。不过我觉得这正是它的魅力所在——你可以参与到一个新兴技术的成长过程中。

这个技巧的拓展用法还有很多,比如如何优化 SEO、如何集成第三方服务等等,后续我会继续分享这类博客。以上是我踩坑后的总结,希望对你有帮助!

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论