In this new -- ongoing series -- I want to talk about Deeno. Or Dehno. Or Déno.
Eh, *Dunno, Take your pick.
This article is a transcript of a Youtube video I made.
Deno is a JavaScript runtime, just like Node. Actually, the creator of Node, Ryan Dahl, initialized the Deno project. Maybe you
noticed that Deno is an anagram for Node. Clever.
For the past ten years or so, ECMA International -- the people responsible for standardizing JavaScript -- and browser
manufacturers have been hard at work improving the JavaScript ecosystem.
In retrospect, the design decisions made by the Node creators are feeling more and more foreign.
That's what Ryan said during a presentation in 2018.
So TL;DR Deno is a secure JavaScript runtime that feels more in-line with the modern JavaScript ecosystem. The project bundles more of
the techs that the community loves; things like TypeScript, a linter, testing tools and WASM.
Okay, so let's go over what makes Deno different than Node.
ES Modules
So, the first thing -- which might be shocking if you're coming from Node -- is ECMAScript modules. That is "importing" files instead of "requiring" files.
I know you're going to say "Node has ES modules too," which is stable since version 15 -- But -- Node doesn't accept full URL as the target; every script must be downloaded locally, usually via NPM.
I think it's good that Deno implemented module fetching like the browsers do. It makes for a more consistent code base and, it's the first step toward portable code.
With this feature you can decentralize module registries; You can either import from local files, host them yourself or use a third-party registry like deno/x
or nest.land
.
import { serve } from "https://deno.land/std@0.88.0/http/server.ts";
Web Platform API
Next up is the "Web Platform API" -- when it makes sense, the Deno team implements APIs using the Whataburger (WHATWG) specs.
That means that things like fetch,
WebSocket and Workers are available out-of-the-box.
These kinds of efforts help bridge the gap between "browser code" and "server code," -- making it possible to write code that works everywhere.
fetch("https://randomuser.me/api")
.then(response => response.json());
TypeScript
Next on the list is "A TypeScript compiler" [confettis]. You heard that right. Deno is a polyglot.
In the same project, you can have JavaScript and TypeScript files without any extra step.
No Babel, no Webpack, no nothing else.
Considering the ceiling shattering rise of TypeScript in recent years, having TypeScript as a first-citizen format is a game-changer that surely will make a lot of developers life easier.
Permissions
Have you ever worried that a Node module might be spying on you, uploading your browser history or stealing your bitcoins for the 4th time? Enter the Permission API.
Straight from the CLI, you can specify if a program can read or write to local files or make network requests.
The rules can be pretty granular, which should give you peace of mind when running code you found on the Internet. But also, it lets your users know that they can trust your module.
deno run --allow-net=randomuser.me
WebAssembly
Remember when I told you that Deno was a polyglot?
Well Deno can also execute WebAssembly modules - which means that, through WASM, Deno can execute code from any language that can be compiled down to the binary byte code format.
Support for this is fairly common in other languages like C, C++ and Rust.
That feature makes it possible to port existing libraries with close to native performance.
Community
Last but not least, is the community. The Deno community is very active and very helpful.
Most of the action happens on the official Discord server.
If you're curious to know more about Deno and haven't yet, I highly recommend that you join the server.
Alright, so with all of this covered, I think it would be great to show you Deno in action!
First we can define a function to experiment with. Notice that we can use TypeScript without any extra-step. Our getUser
function will fetch a random user and return a Promise
.
// users.ts
export const targetURL = "https://randomuser.me/api/";
interface Users {
name: string;
email: string;
login: {
uuid: string;
};
}
export function getUser (): Promise<Users> {
return fetch(`${targetURL}?inc=name,email,login,id`)
.then(response => response.json())
.then(({ results: [ user ] }) => user);
}
Next we could create a new file to run some tests on our function. The Deno namespace comes with a test
function.
// users_test.ts
import { assert } from "https://deno.land/std@0.90.0/testing/asserts.ts";
import { getUser } from "./users.ts";
Deno.test("getUser", async () => {
const user = await getUser();
assert(typeof user === "object", "The user is not an object.");
assert(user.name, "The user does not have a name.");
assert(user.email, "The user does not have an email.");
});
To run our test, we can use the deno test
sub-command, with the appropriate permissions.
deno test --allow-net=randomuser.me users_test.ts
The Deno test runner will detect any resource leak and throw an error. This is a great way to find bugs early.
// users_test.ts
...
Deno.test("getUser: leaking", async () => {
getUser();
});
deno test --allow-net=randomuser.me users_test.ts
[error]
Finally, we can create a new file to be used as CLI that will write a JSON file to the File System using our previous getUser
function. Notice that most I/O functions are available under the Deno namespace.
// cli.ts
import { getUser } from "./users.ts";
export async function writeUserFile () {
const user = await getUser();
return Deno.writeFile(`./${user.login.uuid}.json`, new TextEncoder().encode(JSON.stringify(user, null, 2)));
}
if (import.meta.meta) {
console.log("%cGenerating a new user...", "color: blue");
await writeUserFile();
console.log("%cDone!", "color: green");
}
We can run our new tool with the appropriate permissions.
deno run --allow-write=$(pwd) --allow-net=randomuser.me cli.ts
Cherry on top, we can use the deno install
sub-command to create a system named command. This is a great way to share utility CLI to colleague and friends.
deno install --allow-read=$(pwd) --allow-write=$(pwd) --allow-net=randomuser.me -n generate-users https://raw.githubusercontent.com/sebastienfilion/i-y/main/01/cli.ts
Now, everything you need a random user, you can just run this nifty little command.
generate-users
That's all folks.
In this article, we talked about Deno, what makes it unique, and we went through an example of Deno in action.
I hope this made you curious to learn more about this fantastic project.
In the next article, we will cover the tools that come out of the box with Deno and how the community deals with modules -- no more package.json.
Top comments (0)