Let's explore the Deno Lands
AndrΓ© Michel Andy
Posted on May 14, 2020
On May 13th 2020, a new runtime has been released to the JavaScript ecosystem: Deno. Developed by Ryan Dahl and his team, Deno aims for a better experience in developing Node.js apps. It includes first-class support for TypeScript, a permission scheme that makes our code secure and ESModules as the official way to import packages.
Today is the big day! I am writing this article on the very first day of release, so letβs see what Deno can do and my first impressions.
Installing Deno π
Here are the installation instructions for Deno. Iβm using Windows, so this is the command I used in PowerShell:
iwr https://deno.land/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0
and the result was:
Deno was installed successfully to C:\Users\Andy\.deno\bin\deno.exe
Run 'deno --help' to get started
Well, I'm lying to you a little bit π
this was the actual result:
PS C:\Users\Andy> iwr https://deno.land/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0
File .\install.ps1 : cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at
https:/go.microsoft.com/fwlink/?LinkID=135170.
At line: 1 char: 70
+ ... d/x/install/install.ps1 -useb -outf install.ps1; .\install.ps1 v1.0.0
+ ~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
But don't worry, just run this command to allow downloaded scripts to be executed:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
(I am not a PowerShell user, so I will check for a command to revert or change the execution policy to its defaults after the installation. You should do it too)
Let's check if everything is okay with:
deno --version
Ok, everything sees to be fine:
C:\Users\Andy>deno --version
deno 1.0.0
v8 8.4.300
typescript 3.9.2
Running my first "hello world" π€
As the tradition says, let's write a hello world
in TypeScript
const message: String = "Hello world"; // I used type annotations just to make sure that this TS
console.log(message);
The console says something interesting:
C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Compile file:///C:/Users/Andy/Desktop/GitHub/DenoExperiments/helloworld.ts
Hello world
But after running it again:
C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Hello world
Wait, what? Let's make a small change and try again:
C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.ts
Compile file:///C:/Users/Andy/Desktop/GitHub/DenoExperiments/helloworld.ts
Hello world from TS
Ok, now in JS:
C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno run helloworld.js
Hello world from JS
Interesting π€― I wasn't expecting that compilation message. Yes, it sounds pretty obvious because TS needs to be compiled before running, but I really thought that no compilation was needed π However, it's great to run TS code without using an external tool.
Time to see the REPL in action:
C:\Users\Andy\Desktop\GitHub\DenoExperiments>deno repl
Deno 1.0.0
exit using ctrl+d or close()
> var hello: String = "hello world"
Uncaught SyntaxError: Unexpected token ':'
at evaluate ($deno$/repl.ts:45:34)
at Object.replLoop ($deno$/repl.ts:136:13)
No TS code, only JS. But okay, that idea sounded very unrealistic. If you want to use your own compiler options, just pass them as parameter:
deno run -c tsconfig.json mod.ts
More information at Deno's manual
Integrating with VS Code π»
At this moment, there are just 5 extensions for Deno in VSCode Marketplace, 2 of them with many reviews:
I have installed this, and although it's very limited, it removes TS error messages of URL imports and top-level await (Deno supports it):
After (it may require a first run):
This example is from Deno's website, here's the code
import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
req.respond({ body: "Hello World\n" });
}
Run it with --allow-net
flag or else:
In Deno, we need to grant permissions to some operations like networking, filesystem and running subprocesses.
Exploring third-party packages π¦
Deno has no official package manager (No NPM). You can just import packages just from URLs, so there is no central repository for packages. However, there are some packages listed in Deno's website.
So, what we can do? There's already a web server inspired by Koa, Oak. Also, a ejs template engine.
So, with both packages, we can create an extremely simple CRUD:
// Dependencies
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { renderFile } from "https://deno.land/x/dejs/mod.ts";
const { copy, Buffer } = Deno;
const app = new Application();
const router = new Router();
// A CRUD of Dua Lipa's songs
const duaLipaSongs = [{
name: "Don't start now",
yearOfRelease: 2019,
}, {
name: "One kiss",
yearOfRelease: 2017,
}];
router.get("/index", async (context: any) => {
// We can use the template engine as always
const output = await renderFile(`${Deno.cwd()}/template.ejs`, {
songsList: duaLipaSongs,
});
// The file needs to be copied to a buffer
const buf = new Buffer();
await copy(output, buf);
// It can be sent via context.response.body
context.response.body = new TextDecoder().decode(buf.bytes());
});
router.post("/song", async (context: any) => {
// Currently, only JSON-encoded body can be read
const body = await context.request.body();
duaLipaSongs.push(body.value);
// There isn't method to redirect a client yet
context.response.body = "/index";
});
app.use(router.routes());
const PORT = 8080;
// And no way to add an event listener, so maybe this log is not 100% accurate
console.log(`Listening on ${PORT}`);
await app.listen({ port: PORT });
But, what we can do if a script has so many dependencies? We can use named exports from a file named deps.ts
// deps.ts
// Dependencies
export * as Oak from "https://deno.land/x/oak/mod.ts";
export * as Dejs from "https://deno.land/x/dejs/mod.ts";
And now the dependencies are:
// app.ts
// Dependencies
import { Oak, Dejs } from "./deps.ts";
const { Application, Router } = Oak;
const { renderFile } = Dejs;
You can check and download all of the code from here.
Conclusions β
Deno comes with a new proposal for developing JavaScript apps. Now, it looks very limited and even slower than Node.js, but everything will improve over time. Today, Deno is NOT a replacement of Node.js, only time will tell what will happen with Deno and Node.js.
If you like this article, please share with your friends or coworkers. Follow me here on DEV, Twitter and GitHub, only if you want. Did I make a mistake? Drop a comment and I will correct it as soon as posible.
Thank you for reading!
Posted on May 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
October 2, 2024