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

推荐订阅源

Project Zero
Project Zero
F
Fortinet All Blogs
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
S
Schneier on Security
N
News and Events Feed by Topic
N
News | PayPal Newsroom
H
Help Net Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
Attack and Defense Labs
Attack and Defense Labs
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
A
About on SuperTechFans
AWS News Blog
AWS News Blog
S
Secure Thoughts
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
爱范儿
爱范儿
C
Cybersecurity and Infrastructure Security Agency CISA
V2EX - 技术
V2EX - 技术
Recorded Future
Recorded Future
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
Latest news
Latest news
C
Cyber Attacks, Cyber Crime and Cyber Security
大猫的无限游戏
大猫的无限游戏
The Last Watchdog
The Last Watchdog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
月光博客
月光博客
H
Hacker News: Front Page
P
Proofpoint News Feed
N
News and Events Feed by Topic
H
Heimdal Security Blog
L
Lohrmann on Cybersecurity
有赞技术团队
有赞技术团队
L
LangChain Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog

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 Zero-config Debugging with Deno and OpenTelemetry | Deno Exploring Art with TypeScript, Jupyter, Polars, and Observable Plot | Deno Deno v Oracle Update 3: Fighting the JavaScript Trademark | Deno Build a custom RAG AI agent in TypeScript and Jupyter | Deno How to get deep traces in your Node.js backend with OTel and Deno | Deno toranoana.deno #20 登録受付中(2025年3月14日) | Deno Node just added TypeScript support. What does that mean for Deno? | Deno The Dino 🦕, the Llama 🦙, and the Whale 🐋 | Deno Publish a lint rule, get a prize | Deno Deno 2.2: OpenTelemetry, Lint Plugins, node:sqlite | Deno If you're not using npm specifiers, you're doing it wrong | Deno How Deno's documentation is evolving | Deno Oracle justified its JavaScript trademark with Node.js—now it wants that ignored | Deno Introducing the JSR open governance board | Deno Intro to Wasm in Deno | Deno Announcing OpenAI on JSR | Deno Deno in 2024 | Deno Goodbye WinterCG, welcome WinterTC | Deno Build a SolidJS app with Deno | Deno Run your Next.js SSR app on Deno Deploy | Deno Solve Advent of Code 2024 with Deno and Win Prizes! | Deno Deno v. Oracle: Canceling the JavaScript Trademark | Deno Deno 2.1: Wasm Imports and other enhancements | Deno Build a Typesafe API with tRPC and Deno | Deno Self-contained Executable Programs with Deno Compile | Deno Build a Database App with Drizzle ORM and Deno | Deno Introducing your new JavaScript package manager: Deno | Deno Announcing Growthbook on JSR | Deno Build an Astro site with Deno | Deno How to convert CommonJS to ESM | Deno Announcing Deno 2 | Deno The Final Touches: What’s New In v2.0.0-rc.10 | Deno Announcing Stable V8 Bindings for Rust | Deno Deno 2.0 Release Candidate | Deno Secure, efficient private npm registries with Cloudsmith and Deno | Deno Painting the Plane as We Fly It: Designing JSR | Deno Introducing Web Cache API support on Deno Deploy | Deno Deno 1.46: The Last 1.x Release | Deno Protect your cloud spend with new Deno Deploy spend limits | Deno What we got wrong about HTTP imports | Deno Benchmarking AWS Lambda Cold Starts Across JavaScript Runtimes | Deno Announcing Supabase on JSR | Deno Deno 1.45: Workspace and Monorepo Support | Deno Introducing KV Backup for Deno Subhosting | Deno A Gentle Intro to TypeScript | Deno Announcing Hono on JSR | Deno How We Made the Deno Language Server Ten Times Faster | Deno How the Guardian uses Deno to audit accessibility and performance across their 2.7 million articles | Deno Introducing More Flexible Domain Association for Deno Subhosting | Deno The stabilization process of the Standard Library has begun | Deno Deno 1.44: Private npm registries, improved Node.js compat, and performance boosts | Deno How we built a secure, performant, multi-tenant cloud platform to run untrusted code | Deno The Deno Standard Library is now available on JSR | Deno How to document your JavaScript package | Deno Your Low Code Solution Needs an Escape Hatch | Deno Deno 1.43: Improved Language Server performance | Deno How Slack used Deno to save months of engineering effort in launching their new platform | Deno JSR Is Not Another Package Manager | Deno Announcing the Hookdeck SDK on JSR | Deno Announcing the Neon Serverless Driver on JSR | Deno An intro to TSConfig for JavaScript Developers | Deno How we built JSR | Deno How Netlify used Deno Subhosting to build a successful edge functions product | Deno Introducing Simpler Project Creation in Deno Deploy | Deno Deno 1.42: Better dependency management with JSR | Deno Introducing deployctl, the command line interface for Deno Deploy | Deno Introducing JSR - the JavaScript Registry | Deno How to add Monaco to a Next.js app and securely run untrusted user code | Deno Survey Results and Roadmap | Deno Deno 1.41: smaller deno compile binaries | Deno
Fresh 1.6: Tailwind CSS plugin, simplified typings and more | Deno
Marvin Hagem · 2023-12-01 · via Deno

In this cycle we’ve worked on making first class Tailwind CSS support a reality and expanding our plugin API. Apart from that we spent time on various developer experience improvements.

Remember: you can start a new Fresh project by running

deno run -Ar https://fresh.deno.dev

or update an existing project by running

deno run -Ar https://fresh.deno.dev/update

in your project folder.

Here’s an overview of what’s new in 1.6. Read on for all the details, plus what to expect in the next iteration of Fresh.

Fresh 1.6 at a glance

  • 🌊 First class Tailwind CSS plugin We’re moving from Twind to Tailwind CSS. It features better Editor integrations and moves the CSS generation out of the rendering path.
  • 📨 Partials with forms Partials are now supported on Form elements.
  • 🧯 Partials on error pages Partials can now be used to render error pages.
  • 🕵️‍♀️ Closable error overlay The custom error overlay that is shown during development can now be closed, so that you can see the projects 500 page.
  • ⚡️ Improved islands bundling strategy Islands are now bundled together in a smarter way that leads to less files and allows you to group related islands together.
  • ⚔️ Less manifest merge conflicts The identifiers in the manifest file are now derived from the file name instead of being an incremented number. This reduces the chance for merge conflicts greatly.
  • 📦 Support for pre-generated assets Fresh will give generated assets priority when serving them when it encouters the same file in _fresh/static.
  • 🧩 Plugin API enhancements The Plugin API now supports adding islands from plugins, adding <link>-elements and has a new configResolved hook.
  • 🏁 Faster route matching The route matching performance has been improved, especially when a project has many static files.
  • 🛣️ Serving from a sub path Fresh projects can now be served under a sub path like `https://example.com/foo/bar` instead of the root of the domain.
  • 🏆 Simplified typings The number of different context types has been reduced from 6 down to 2 and there is now only one props type instead of four.

First class Tailwind CSS plugin

It has been a long time coming and Fresh now ships with a proper Tailwind CSS plugin. It’s using the exact same npm package as you would do in Node. This means we’re putting our Twind plugin on life support and mark it as deprecated.

Tailwind CSS has many benefits over Twind, with the most important one being that Tailwind CSS is actively maintained and supports a much more polished editor experience. You’ll get some nice performance benefits too by switching over to Tailwind CSS as it only needs to generate CSS once on deployment, vs on the fly on every request with Twind.

To switch from Twind to Tailwind CSS, follow this guide in our documentation. Note that this plugin requires ahead of time builds to be set up for your project.

Tailwind CSS vscode extension in action on a Fresh project.

Thanks to Jason Gardner for prototyping the initial tailwindcss plugin integration!

Partials with forms

We’ve expanded the capabilities for Partials to work with <form> -elements. Similar to the existing Partials support for <a>-elements, Fresh will opt into partials with forms when the parent element of the submitter has a “truthy” f-client-nav attribute. This even works when the submit button is outside of the enclosing form element.

<form id="foo">
  <Partial name="slot-1">
    <input type="text" value={value} name="name" />
  </Partial>
</form>
<button
  type="submit"
  form="foo"
  formaction="/form"
  f-partial="/form"
  formmethod="POST"
>
  submit
</button>

Partials on error pages

With Fresh 1.6 you can now use Partials for error pages too. Previously, a partial navigation would error when the response status code was not ok. This limitation has been removed and we only check if the response content type is HTML.

While we were working on that part of the code, we also added support for following redirects automatically for partial navigations.

Closable error overlay

With Fresh 1.5 we added an error overlay during development that shows detailed information about where the error occurred. Problem was that this overrode the user’s _500.tsx error page. We fixed that and now the error overlay is a proper error overlay that can be closed.

Improved islands bundling strategy

In the browser we noticed that we could improve the way we serve the JavaScript code for islands. Previously, every island component would be moved into a separate bundle, which would lead to many .js files being generated that are less than <1kb. The new strategy adheres to the original files to give you much more control on how best to bundle islands for your project. By respecting the original files you can group related islands together and include them in the same bundle.

Less manifest merge conflicts

Whilst we want to get rid of the manifest in the long term, we felt that we can improve the current pain points of frequently running into merge conflicts when adding new routes or renaming them. Previously, identifiers would be composed of $<number> where the number part was merely incrementing. The new approach converts the file name to a valid JavaScript identifier and only appends a number if an existing identifier with the same name is found.

Thanks to Reed von Redwitz for bringing this over the finish line!

Screenshot of a fresh.gen.ts manifest file where import names are serialized file names instead of a `$` with an incremented number

Support for pre-generated assets

There are many scenarios where you’d want to generate asset files for deployment. These could include file optimisations or generating CSS like for the Tailwind CSS plugin. The way it works is that Fresh gives static files residing in <project>/_fresh/static higher priority over the default <project>/static directory.

Plugin API enhancements

The plugin API was an area we always wanted to improve but didn’t have the time for. With this release we set aside dedicated time to expand it with some new features users have been asking for.

Islands from plugins

Among the most exciting of them is the ability to add islands from plugins. By specifying file paths to your island file, Fresh will treat them the same way as if they had been placed inside the islands/ directory.

import { Plugin } from "$fresh/server.ts";
import * as path from "https://deno.land/std@0.208.0/path/mod.ts";

const __dirname = path.dirname(path.fromFileUrl(import.meta.url));

export default function myIslandPlugin(): Plugin {
  return {
    name: "my-island-plugin",
    islands: {
      baseLocation: import.meta.url,
      paths: [
        "./plugin-islands/MyIsland.tsx",
        "./plugin-islands/OtherPluginIsland.tsx",
      ],
    },
  };
}

Thanks to Reed von Redwitz for working out all the details.

Plugins can now add <link> -elements to add additional stylesheets or similar things.

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

function MyPlugin(): Plugin {
  return {
    name: "link-inject",
    render(ctx) {
      ctx.render();
      return {
        links: [{ rel: "stylesheet", href: "styles.css" }],
      };
    },
  };
}

Thanks to Adam Gregory for enabling this feature!

New configResolved hook

There are often scenarios where your plugin needs to apply different logic based on the Fresh configuration. We already pass the config to onBuildStart(config) but that is too late for other sections of the plugin API. Therefore we’ve added a new configResolved hook similar to vite which allows you to grab the fully resolved Fresh configuration.

import { Plugin, ResolvedFreshConfig } from "$fresh/server.ts";

function MyPlugin(): Plugin {
  let config: ResolvedFreshConfig;

  return {
    name: "my-cool-plugin",
    configResolved(resolvedConfig) {
      config = resolvedConfig;
    },
  };
}

Faster route matching

Another area we looked at to make Fresh faster, was our router. We’ve noticed some inefficiencies in the way we process and match routes, especially when a project has many static files. We added another optimisation that detects if the route has no dynamic parts and will fall back to a simple string comparisons.

Overall, with all optimisations applied we see a 4-10x speedup in route matching times on deno.com .

Serving from a sub path

Not every project is served at the root domain address and a popular request among users was to be able to serve Fresh from a sub path. Instead of hosted at https://example.com/ it should be available under https://example.com/foo/bar for example. This is now possible with the new router.basePath config option.


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

export default defineConfig({
  router: {
    basePath: "/foo/bar",
  },
});

Thanks again to Reed von Redwitz for bringing this over the finish line!

Simplified typings

One thing that I always felt we could do better has to do with how we type our API that users interface this. Take a look at the various middleware and route context types for example:

  • MiddlewareHandlerContext
  • AppContext
  • ErrorHandlerContext
  • HandlerContext
  • LayoutContext
  • UnknownHandlerContext

That’s quite a lot of types to be aware of. With recent code cleanups and simplifications of our internals we realised that they are mostly the same type. So we reduced the number of context types down to just two.

  • FreshContext
  • RouteContext (for async routes/layouts/app wrapper)

In the future we might be even able to reduce it further to just one. Note, that we’re still keeping the old types around as aliases to the new ones to not make this a breaking change.

In the midst of simplifying our core we noticed that our props typings were similarly complex, more than they should’ve been.

  • ErrorPageProps
  • AppProps
  • UnknownPageProps
  • LayoutProps

Those four types have been reduced to a single type:

  • PageProps

We’re pretty happy with the simplifications so far as it eases the mental burden of working with Fresh.

Together with the type simplifications we made sure that the Fresh context object is exposed everywhere. It’s now passed to middlewares and routes as well. On top of we now pass the fully resolved Fresh config inside context, so that you can apply different logic based on it.

What’s on the horizon?

As with every release there is more that I would’ve loved to be able to include in this release. The truth is that these features need a little more time to polish. Curious Deno readers might have noticed the new “precompile” JSX transform in recent Deno release notes. It’s something I spent quite a bit of time on during this cycle and something I want to bring to Fresh as soon as possible. It’s mostly a performance change in how JSX is transpiled that will speed up most Fresh sites by 2-4x.

Another thing that I’ve worked on with Bartek is HMR for Deno. The initial prototype landed in Deno 1.38 as well, but there is more work to be done to wire it up in Fresh and make it feel smooth.

And of course, there is more work to be done surrounding Partials! I really want to have a proper way to specify pending states, do error handling and expose the functionality so that you can call it from an event listener. I don’t know exactly how all of this will look like, but it’s something I really want to have a good answer for in Fresh.

The December cycle will be a bit shorter than usual due to vacations around Christmas. It’s likely that we’ll skip a feature release and only do another patch release at the end of the year. The current iteration plan can be seen in the December iteration plan