https://deno.com/blog/a-whole-website-in-a-single-js-file
Deno
CLIBlogDeploy
Whole Website in a Single JavaScript File
A Whole Website in a Single JavaScript File
April 5, 2022
Leo Kettmeir, Ryan Dahl
---------------------------------------------------------------------
This site is a pretty standard demo website; a site with links to
different pages. Nothing to write home about except that the whole
website is contained within a single JavaScript file, and is rendered
dynamically, just in time, at the edge, close to the user.
The routing is fairly minimal: we use the router module which uses
URLPattern under the hood for pattern matching.
/** @jsx h */
///
///
///
///
import { serve } from "https://deno.land/std@0.133.0/http/server.ts";
import { router } from "https://crux.land/router@0.0.11";
import { h, ssr } from "https://crux.land/nanossr@0.0.4";
const render = (component) => ssr(() => {component});
serve(router(
{
"/": () => render(),
"/stats": () => render(),
"/bagels": () => render(),
},
() => render(),
));
We have 3 paths: / for the main page, and/stats for some statistics,
and /bagels to display various bagels that we sell. We also have a
fallback handler (the last argument in the snippet), which will be
called when none of the paths match, acting as a 404 page. These are
served using the serve function from the standard library.
For rendering of the JSX, we use nanossr, which is a tiny server-side
renderer that uses twind under the hood for styling. This is invoked
by using the ssr function, to which a callback is passed which should
return JSX. The ssr function returns a Response. We create a render
function to remove the need for larger duplication of code, just to
tidy things up.
But before any of this, you probably noticed some funny looking
comments. Let's go through them:
* /** @jsx h */: this pragma tells Deno which function we want to
use for transpiling the JSX.
* /// : Deno comes with various
TypeScript libraries enabled by default; with this comment, we
tell it to not use those, but instead only the ones we specify
manually.
* /// , /// , and /// :
these libraries provide various typings. The dom one gives us
various typings related to the DOM, and dom.asynciterable defines
functions that need async iterators as these are not included in
the normal dom library as of writing. The deno.ns library gives
us typings for any of the functions and classes under the Deno.*
namespace, like Deno.readFile. You can read more about the
various libraries available in the manual.
Let's look at some actual code; in the code snippet earlier you might
have noticed that we wrap all route components in an App component.
This is defined as:
function App({ children }) {
return (
{children}
);
}
It's fairly compact: it returns a div and inside that we have our
NavBar which is our menu navigation at the top of the page. We're
doing templating server-side, sharing components between different
pages using the same language one would do this client-side.
[pagespeed]
Hosted on Deno Deploy, this little website is able to acheive a
perfect pagespeed score. Serviced from an anycast IP address over
encrypted HTTP from 29 data centers around the world, the site is
fully managed and will be available indefinitely at zero cost.
Everything mentioned here can be viewed on a playground.
Deno
DeployManualRuntime APIStandard LibraryThird Party ModulesBlogCompany
System StatusPrivacy Policy