🍋 Why use Deno Fresh? #
- Deno Fresh builds fast sites so you get first class user experience (UX),
- it uses the platform so getting started with Deno Fresh is quick if you already know the JavaScript APIs (even if you have to learn them you are not locked into Fresh, use them with Remix, Astro or SvelteKit),
- amazing Developer Experience (DX) — it’s serverless with no build step, deploys are live almost instantly.
🤷🏽 What is Deno Fresh? #
Deno Fresh is a Next Gen site builder. It builds Server-Side Rendered (SSR) sites and supports partial hydration. Fresh runs in the Deno JavaScript runtime which prioritises security and performance. In Deno, JavaScript APIs are first-class citizens — it uses the platform. This makes Deno quicker and easier to learn. Deno renders your site on the server and by default ships zero JavaScript to the browser. This makes Fresh a fine choice for content sites. By content sites we mean those which are largely documentation, blogs and such like, typically not heavily interactive.
When you need interactivity on a Fresh site, you can use Fresh's partial hydration feature set. This means only the parts of the page which are interactive, also known as islands of interactivity, get hydrated. Hydration is just the step in the page loading in the browser where code allowing interactivity gets loaded and the state of these components becomes consistent.
🎬 How do you Spin up a Fresh Fresh App? #
To get going you will need Deno in your development environment. If you do not yet have it installed, it is quick to set up from the Terminal with Homebrew on MacOS or a shell script on Linux:
In contrast to Node.js runtime-based tooling, with Deno typically you run apps and access packages via a URL. This is exactly what we can do to spin up a new Deno Fresh app. Once you have Deno installed, type these commands in the Terminal to get going:
🧐 Getting Started with Deno Fresh: What’s Inside? #
-
With Deno Fresh, you write your components in Preact (just pretend it’s React
if its your first time with Preact). Your Preact component files get placed in the
components
orislands
directory depending on whether they are interactive or not. So a button which changes state can go inislands
but a form which uses the platform and WebAPIs can go intocomponents
. -
deno.json
this loosely maps to apackage.json
file in Node.js. The includedstart
task is what you run to start your app and tells Deno to run thedev.ts
file (also listed above), -
main.ts
: this is where we run the in-built web server from. You can add additional config for TLS and what not here, -
routes
: this folder contains files which map to actual pages on your site. If you already use Astro, Remix or Next.js the file-based routing system will be very familiar.routes/index.tsx
will map tohttps://example.com/
on your final site, while aroutes/about.tsx
will map tohttps://example.com/about
.routes/[name].tsx
is a dynamic page template. This provides mechanism for example, to create/offices/london
,/offices/berlin
and/offices/mumbai
all from a single file without duplicated the content and with access to the city name parameter within the template (/offices/[office-name].tsx
). -
static
is for anything which does not need processing like favicons,manifest.webmanifest
files for PWAs or logos.
What’s deliberately missing? #
Notice there is no:
-
package.json
: with Deno Fresh, you can useimport_map.json
for dependencies and thetasks
field indeno.json
for scripts, -
tsconfig.json
: Deno Fresh comes with in-built TypeScript support and selects sensible defaults under the hood to help you get going quicker on new projects, -
eslint.js
&eslint.config.js
: just use thedeno lint
command — no need to configure this, -
.prettierrc
&.prettierignore
: similar to Rust, formatting is also integrated into the tooling. Rundeno fmt
when you want to tidy your code, -
vitest.config.ts
: you guessed it… Deno has integrated testing built into the tooling too!
🗳 Poll #
💫 9 Quick Tips for Getting Started with Deno #
- Permissions: Deno prioritises security and gives you more control over what
your app has access to.
The
-A
flag in thestart
script grants our app access to all permissions including the file system (read and write), environment variables and the network. If you want finer grained control remove it and restart your app. You will now see prompts asking for various permissions in the Terminal. - Environment Variables
In the cloud you can define secrets in the Deno deploy console (or your host’s equivalent). Locally, as with other tooling you can use a
.env
file. Remember to add this to your.gitignore
file so secrets are not committed to your git repo. - VS Code Setup: you might already have a
`.vscode/extensions.json` file in the project (depending on how you answered the setup
prompts).
This will cause VS Code to prompt you to install the Deno extension when you open the project. I noticed the extension was connecting to the network even in non Deno projects. Because of that, now I install it as normal, then in VS Code Extensions, find Deno, and click the Disable button. Finally, I click the dropdown to select Enable (Workspace).
The extension adds linting hints and formatting capabilities. To format on save, update
.vscode/settings.json
:I notice the auto-format saved files change ever so slightly when I run
deno fmt
from the Terminal, but imagine this will be addressed soon. - Browser vs. Server in other frameworks you might remember having to run a little
check to make sure a block of code only runs in the client. You can see an example of how to achieve
this in Deno in
components/Button.tsx
:Here the button is disabled if the code is not running in the browser, but you might also use this if you are working with local storage (for example) and need to access it on the client via
window.localStorage
. - Deno std we added the
std
package toimport_map.json
earlier to accessdotenv
. This is the Deno Standard Library (Deno has a standard library just like C and Rust). Apart fromdotenv
you might also usestd
for:-
$std/crypto
: to access WebCrypto APIs in your server side code, -
$std/encoding
: for extracting front matter from Markdown files or to generate base64 for BasicAuth HTTP headers, -
$std/http
for working with HTTP cookies. -
$std/path
for file manipulations you might find innode:path
, -
$std/assert/mod.ts
,$std/testing/bdd
and$std/testing/snapshot.ts
for Jest styleasserts
as well as Behaviour Driven Testingdescribe
andit
. For Chai styleexpect
tryhttps://cdn.skypack.dev/[email protected]?dts
.
-
- Finding Packages: Deno is a little different to Node.js in that you do
not have to use NPM as your package repository and also that you can import packages from
URLs. Under the hood, Deno caches the packages locally (a little like pnpm) so that you do
not need to download them afresh each time you start up your app. Three sources for third
party modules are:
-
Deno X:
https://deno.land/x?
find Deno specific modules here, -
Skypack:
https://cdn.skypack.dev/
an alternative with NPM packages, -
esm.sh:
https://esm.sh/
another NPM package alternative.
-
Deno X:
- More Aliases as well as adding aliases for your external modules, you can
also define them for your project folders. As an example, update
import_map.json
:Now we can tidy up the import statements in
routes/index.tsx
:This can make your code look cleaner and also make it easier mentally to map where the import is coming from.
- 404 Page: create a custom page not found template by adding a
routes/_404.tsx
file to your project:Note we use the
Head
component here to add the<title>
element to the HTML<head>
for our page. - Where do Favicons go? we mentioned earlier you can put favicons, logos and
manifest.webmanifest for a PWA in the project
static
folder. This is also a great place to add your self-hosted fonts and even CSS. If you are using PostCSS then you might want to have your input CSS in a separatestyles
folder at the root of the project then have PostCSS output the transpiled CSS tostatic/styles
. We will see further down how you can automatically append hashes to the served filenames so they cache-bust when updated. - how Deno Fresh Islands work,
- Deno’s inbuilt testing framework,
- creating API Routes and a whole lot more!
- how create a new Deno Fresh app,
- some useful Deno standard library functions,
- how to pass data into a client React page.
Does Deno Fresh work with Svelte? #
- Currently Deno Fresh only supports Preact. Preact uses the React APIs but it highly optimised, so if your reason for preferring Svelte is speed, give Deno Fresh a try anyway. Deno uses web standards so is quick to pick up. Especially for content sites, you should see a massive speed pickup from partial hydration.
Which serverless database services are a good match for Deno? #
- Deno deploys to a serverless environment. For caching, a service like Upstash Redis is a fantastic choice as it is quick to integrate. Also consider Fauna for object storage, though in reality any modern database service designed for serverless applications will fit.
What `batteries` are included with Deno? #
- Deno is a batteries included runtime. By that we mean there is a plethora of tooling included. This can save you time and let you get going on the actual coding phase of your project much quicker. You will not need to set up Prettier, ESLint, TypeScript or Jest. That is because Deno has in-built tooling for handling all of the tasks those are designed for. On top, there is even a benchmarking utility. As well as benchmarking, we have `deno fmt` to format your code, `deno lint` to spot those errors ESLint handles in node. Finally, there is no `tsconfig.json` file: Deno comes with sensible defaults baked in.
By default, the main.ts
file in the project root directory includes
a $std/dotenv/load.ts
import, which adds local .env
support to your project. In your source code, you can access a secret variable using Deno.env.get()
:
9 Quick Tips for Getting Started with Deno Continued (5 – 9) #
As an aside, the import format
from $std/fmt/bytes.ts
for formatting file sizes into easily human readable strings.
Anatomy of a Deno Route File #
As a first step, take a look at the routes/index.tsx
file
included in the Deno Fresh skeleton content. It exports a default function which is a Preact
component. If you are familiar with React or Preact then there is nothing too interesting
for you here.
Even on a fairly basic site you might want to use content from a database or even
Markdown files within the project. This is work which Deno Fresh lets you do on the
server and sourced using a Deno handler function. The handler function
can sit in the same file as the rendered content (the exported React component in routes/index.tsx
, for example). I like this pattern of sourcing the data in the same file as the
rendered content. For smaller sites it can help debug a lot faster or even help you
remember how a page you wrote a few months back works.
Deno Fresh Route Request Handler #
I trimmed down a source file from a little Deno app for scheduling Tweets, it’s a kind of poor cousin of Hootsuite or Buffer. This will help us illustrate some more real-world Deno Fresh features. Let’s see the data handling part first:
The TypeScript support comes out of-the-box and we add nothing to get it to work. You
can see the handler
has a two components: a GET
handler, while will be called when the page loads and a PUT
handler which we will invoke by submitting a form (front-end code coming up). Notice how
GET
and PUT
are named after
HTTP request methods — Deno loves the platform! These functions take a request
and context
parameter as inputs. The request
is a standard WebAPI Request and we can apply the formData()
, json()
or text()
methods
to manipulate the request body. We can also destructure headers
, method
, url
etc. from
it.
Meanwhile context
contains a params
object. For a template route (remember the offices in london
, mumbai
, etc. example)? There our template file name
was routes/offices/[office-name].tsx
. Well, if for
example, we want to pull the phone number for the right office from the database when
the visitor goes to https://example.com/offices/mumbai
we
can access the mumbai
part using the context:
context.render()
#
As well as letting us access path parameters, the context object also defines a render
method. This is what provides the server-side rendering for us. By returning it, we can
pass the data into the client template. Let’s see that next.
Client React Code #
Remember we can keep things simple, placing this code in the same file as the handler.
We didn’t handle it above in the handler (to keep things simple), but we could
have returned an error if we had some issue pulling scheduled tweets from the database.
Checking for that error in the client code, we can let the user know something is not
right. Here <Fragment></Fragment>
is
syntactically equivalent to using <></>
. If you are new to React or Preact you might not know, our rendered elements must
have a single top level element (that is why wrap the other elements in Fragment
, otherwise HTMLHead
, Header
, etc would all be top level elements).
If we need to access the page URL, we can do so using the ctx
prop. Finally, notice we have a form to handle submitting a new tweet. This works using
the platform and with no need for additional JavaScript. Check the MDN docs if you are new
to this. Learn it once and use it here in Deno Fresh, in SvelteKit, in Remix, in Astro or
even a plain old HTML/CSS website! When the user clicks the button, the action="/twitter/tweet-queue" method="post"
on the form element means the browser will send a POST
HTTP request to /twitter/tweet-queue
(this exact route).
The POST
function in the handler above will then take care
of it. Are you not entertained 😅
🙌🏽 Getting Started with Deno Fresh: Wrapping Up #
We’re only just getting started! However, so the post doesn’t get too long, in a follow-up we will see:
The journey so far… we have taken a quick look at getting started with Deno Fresh. In particular, we saw:
Check out the Fresh docs for further details. Get in touch if you would like to see more content on Deno and Fresh. I hope you found the content useful and am keen to hear about possible improvements.
🏁 Getting Started with Deno Fresh: Summary #
🙏🏽 Getting Started with Deno Fresh: Feedback #
Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, then please consider supporting me through Buy me a Coffee.
Just dropped a new post on getting started with 🦖 Deno Fresh...
— Rodney (@askRodney) January 6, 2023
🍋 Deno Fresh:
- builds fast SSR sites,
- lets you use the platform,
- deploys instantly with no build step for marvellous DX
Have a read, hope you find it useful!
https://t.co/rdXCCvEDus
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter, @[email protected] on Mastodon and also the #rodney Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as Deno. Also, subscribe to the newsletter to keep up-to-date with our latest projects.