惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
B
Blog
阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Jina AI
Jina AI
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
L
LangChain Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
F
Fortinet All Blogs
H
Help Net Security
B
Blog RSS Feed
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
S
SegmentFault 最新的问题

Deno

Deno 2.8 | Deno Claw Patrol: an open-source security firewall for agents | Deno Fresh 2.3: Zero JS by default, View Transitions, and Temporal support | Deno Deno 2.7: Temporal API, Windows ARM, and npm overrides | Deno Build a dinosaur runner game with Deno, pt. 6 | Deno Build a dinosaur runner game with Deno, pt. 5 | Deno Deno Deploy is Generally Available | Deno Introducing Deno Sandbox | Deno Build a dinosaur runner game with Deno, pt. 4 | Deno Build a dinosaur runner game with Deno, pt. 3 | Deno Build a dinosaur runner game with Deno, pt. 2 | Deno React / Next.js Denial-of-Service Vulnerability: Deno Deploy users protected | Deno Deno 2.6: dx is the new npx | Deno Build a dinosaur runner game with Deno, pt. 1 | Deno React Server Functions / Next.js Vulnerability: Deno Deploy users protected | Deno My highlights from the new Deno Deploy | Deno Deno's Other Open Source Projects | Deno How Deno protects against npm exploits | Deno Help Us Raise $200k to Free JavaScript from Oracle | Deno Deno 2.5: Permissions in the config file | Deno Fresh 2.0 Graduates to Beta, Adds Vite Support | Deno Deno 2.4: deno bundle is back | Deno JavaScript™ Trademark Update | Deno What's coming to JavaScript | Deno A brief history of JavaScript | Deno Reports of Deno's Demise Have Been Greatly Exaggerated | Deno An Update on Fresh | Deno How Plaid migrated 100 services to a new database platform 5x faster with Deno | Deno Deno 2.3: Improved deno compile, local npm packages, and more | Deno Add JSR packages with pnpm and Yarn | Deno
Fresh 1.3 – Simplified Route Components and More | Deno
Marvin Hagem · 2023-07-18 · via Deno

A mere month has passed since we released Fresh 1.2 into the wild and we’re already back with another release! We’re planning to release new minor versions of Fresh on a monthly cadence going forward.

This cycle contained lots of incredible PRs from the community, which is nothing short of amazing! The documentation has been expanded and improved, many bugs fixed and new features added. Thank you to everyone who helped in making this release possible. But enough talk, let’s look at all the improvements we made to Fresh.

  • Async Route Components
  • Adding routes and/or middlewares from plugins
  • 500 error template fallback
  • Error Boundaries
  • Export multiple islands in the same file
  • Fresh linting rules
  • Support for Deno.serve
  • More quality of life improvements

Async Route Components

We heard a lot of feedback that passing data from a route handler to the page’s component requires a bit of annoying boilerplate. To ensure type-safety, you’d always have to create an interface for the component’s props, pass that to the Handlers type as a generic and use that in the component definition. That’s quite a lot of steps!


interface Data {
  foo: number;
}

export const handler: Handlers<Data> = {
  async GET(req, ctx) {
    const value = await loadFooValue();
    ctx.render({ foo: value });
  },
};

export default function MyPage(props: PageProps<Data>) {
  return <p>foo is: {props.data.foo}</p>;
}

Since the GET handler is very often highly coupled to the component it will render, the obvious question is why we don’t just merge the two together? And that’s exactly what we did. In Fresh 1.3 we can simplify the snippet from before significantly:

export default async function MyPage(req: Request, ctx: RouteContext) {
  const value = await loadFooValue();
  return <p>foo is: {value}</p>;
}

Since both the handler and the component are in the same function there is no need to declare an intermediate interface to pass data between the two; you can just pass the data directly.

But don’t worry, there is no need to rewrite all your routes. In fact we’re not fans of having to rewrite code ourselves. The new way is nothing more than an additional option and can make simple routes a bit easier to write. It is not a requirement to use async routes.

When you’re responding to other HTTP verbs like POST you might need a handler anyway:

export const handler: Handlers<{}> = {
  POST(req) {
    
  },
};

export default async function MyPage(req: Request, ctx: RouteContext) {
  const value = await loadFooValue();
  return <p>foo is: {value}</p>;
}

Moreover, the existing way of rendering routes from a handler via ctx.render() and a separate component function will continue to work and makes it possible to test rendering and the data retrieval mechanisms in isolation.

Adding routes and/or middlewares from plugins

Plugins are quite powerful in extending Fresh’s built-in capabilities. With Fresh 1.3 they can inject virtual routes and middlewares. This is especially useful for plugins adding development specific routes or admin dashboards.

function myPlugin() {
  return {
    name: "my-plugin",
    middlewares: [
      {
        middleware: { handler: () => new Response("Hello!") },
        path: "/hello",
      },
    ],
    routes: [
      {
        path: "/admin/hello",
        component: () => <p>Hello from /admin/hello</p>,
      },
    ],
  };
}

Thanks to Reed von Redwitz and iccee0 for the contribution.

500 error template fallback

As much as we programmers try to account for every scenario, there often remain unexpected cases in which an error occurs. We’ve simplified error handling a bit and Fresh will now automatically render the _500.tsx template as a fallback when an error is thrown in a route handler.

export const handler = (req: Request, ctx: HandlerContext): Response => {
  
  throw new Error("Catch me if you can");
};

Thanks to Kamil Ogórek for adding this.

Error Boundaries

Although a little rarer than errors in handlers, errors can also be thrown during rendering. For this reason we added basic support for error boundaries. When Preact detects that a class component that has a componentDidCatch() method or a static getDerivedStateFromError method, the component is treated as an error boundary. When an error is thrown during rendering, those components can catch the error and render a fallback UI:

class ErrorBoundary extends Component {
  state = { error: null };

  static getDerivedStateFromError(error) {
    return { error };
  }

  render() {
    return this.state.error
      ? this.props.fallback(this.state.error)
      : this.props.children;
  }
}


<ErrorBoundary fallback={(error) => <p>Error happened: {error.message}</p>}>
  <SomeComponentThatThrows />
</ErrorBoundary>;

This is useful for when you’re dealing with highly dynamic data and want to render a fallback UI instead of rendering the 500 error page. Whilst the changes in Fresh 1.3 lay the foundation for catching rendering errors, we’re already thinking of ways we could make the API feel more ingrained with Fresh itself.

Export multiple islands in the same file

In previous Fresh versions every island was expected to live in its own file and be exported via a default export. Every island file is treated as its own entry point and shipped in a separate JavaScript file to the browser. This limitation has been removed and you can now export as many islands in a single file as you want.



export default function SayHello() {
  
}

export function OtherIsland() {
  
}

export function AndAnotherIsland() {
  
}

Grouping islands in a single file reduces the number of request a site has to make and can even make some sites a little faster! Note, that whilst it’s tempting to put all islands in the same file that pattern might have the opposite effect. A good rule of thumb is that grouping islands that are used together on the same page gives you the most performant result.

Thanks to Reed von Redwitz for the contribution.

Fresh linting rules

The best way to give feedback is right in the editor. We started to keep track of common accidental mistakes like naming the handler export handlers instead of handler and integrated that into our linter. You’ll get those squiggly lines right in your editor whenever we detect that something is wrong.

screenshot of lint

A common source for confusion were the often cryptic error messages Fresh presented to the user when something was misconfigured or went outright wrong. We went through the most common errors and rewrote the error messages to be much more human readable. Whilst we think we covered a large area already, there are probably more cases where we can do a better job. So if you run into any error message that’s confusing to you, reach out to us!

The new linting rules work out of the box for new Fresh projects. To use them with existing projects just put this in your deno.json file:

{
  "lint": {
    "rules": {
      "tags": ["fresh", "recommended"]
    }
  }
}

Support for Deno.serve

With the recent Deno 1.35.0 release, the Deno.serve API was marked stable. We followed suit in Fresh and with version 1.3 we’ll use Deno.serve when it’s available. This new API is not just faster, but also a lot simpler than the previous serve API from std/http.

Thanks to Lino Le Van for the contribution.

More quality of life improvements

We shipped a bunch of minor improvements like being able to access route parameters from every handler or middleware. BigInt values can now be passed to islands as props. The starter template looks a lot better now, and much more!

Screenshot