A beginners Guide to Deno - Secure runtime for JavaScript
In this tutorial, we are going to learn about what is Deno and how to getting started with it.
What is Deno?
Deno is a secure runtime for executing the JavaScript and TypeScript outside the browser environment. Which is built on top of V8, Rust, Tokio (event loop), and TypeScript.
If you know about Node.js creator Ryan Dhal, the same person is created Deno with the similar goals that Node offers to us.
Features of Deno
-
Secure by default, it means deno doesn’t allow you to use, network, file access, or environment access unless you need to enable explicitly.
-
It supports modern JavaScript features like es modules and top-level await.
-
First-class TypeScript support, so that we can use typescript in our apps without any extra tooling.
-
Deno is distributed as a single executable file.
-
It has some built-in tools for bundling the modules and formatting the code, etc.
Installing the Deno
Let’s install the deno, by running the following command inside your terminal.
curl -fsSL https://deno.land/x/install/install.sh | sh
Have you seen, inside the terminal you are seeing some instructions like in the above screenshot?
According to the instructions, we need to add the following paths inside the .bash_profile
or .zhsrc
file.
export DENO_INSTALL="/Users/saigowtham/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
To verify the successful installation, you need to run deno --help
command in your terminal.
If it shows the following output then you are successfully installed deno on your machine.
➜ ~ deno --help
deno 1.0.0
A secure JavaScript and TypeScript runtime
Docs: https://deno.land/std/manual.md
Modules: https://deno.land/std/ https://deno.land/x/
Bugs: https://github.com/denoland/deno/issues
To start the REPL:
deno
To execute a script:
deno run https://deno.land/std/examples/welcome.ts
To evaluate code in the shell:
deno eval "console.log(30933 + 404)"
USAGE:
deno [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help
Prints help information
-L, --log-level <log-level>
Set log level [possible values: debug, info]
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-V, --version
Prints version information
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to given version
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
DENO_INSTALL_ROOT Set deno install's output directory
(defaults to $HOME/.deno/bin)
NO_COLOR Set to disable color
HTTP_PROXY Proxy address for HTTP requests
(module downloads, fetch)
HTTPS_PROXY Same but for HTTPS
Getting started
Open your terminal and run the deno
command to start the REPL (read-execute-print-loop).
➜ ~ deno
Deno 1.0.0
exit using ctrl+d or close()
> 1+2
3
> console.log('hi deno');
hi deno
undefined
>
to exit the repl use
ctrl+d
orclose()
command.
Writing our first deno program
Let’s write our first hello world program using deno.
For this, we need to create a new directory called deno-examples
.
mkdir deno-examples
cd deno-examples
Now, open the directory using your favorite code editor (mine is vscode) and create a new file called index.js
then add the following code.
const a = "Hello world";
console.log(a);
To run our program, we need to use the deno run
command followed by the file-name.
deno run index.js
Output:
➜ deno-examples deno run index.js
Hello world
Creating the HTTP server
Let’s create a simple HTTP server using Deno.
Create a new file called server.js
and add the following code.
import { serve } from 'https://deno.land/std/http/server.ts'
console.log('server is running on port 3000');
for await (const req of serve({port: 3000})) {
req.respond({ body: '<h1>Welcome to deno land</h1>' });
}
In the above code, we first imported the server
function from the deno http
standard module.
Inside the for
loop, we are responding to the requests
we got on localhost:3000
.
Now, run the program using deno run server.js
.
Deno starts downloading the http
module and its related dependencies then it caches in your system (so, you can use this module when you are offline).
➜ deno-examples deno run server.js
Download https://deno.land/std/http/server.ts
Compile https://deno.land/std/http/server.ts
Download https://deno.land/std/encoding/utf8.ts
Download https://deno.land/std/io/bufio.ts
Download https://deno.land/std/testing/asserts.ts
Download https://deno.land/std/async/mod.ts
Download https://deno.land/std/http/_io.ts
Download https://deno.land/std/io/util.ts
Download https://deno.land/std/path/mod.ts
Download https://deno.land/std/path/win32.ts
Download https://deno.land/std/path/posix.ts
Download https://deno.land/std/path/common.ts
Download https://deno.land/std/path/separator.ts
Download https://deno.land/std/path/interface.ts
Download https://deno.land/std/path/glob.ts
Download https://deno.land/std/path/_constants.ts
Download https://deno.land/std/path/_util.ts
Download https://deno.land/std/fmt/colors.ts
Download https://deno.land/std/testing/diff.ts
Download https://deno.land/std/path/_globrex.ts
Download https://deno.land/std/async/deferred.ts
Download https://deno.land/std/async/delay.ts
Download https://deno.land/std/async/mux_async_iterator.ts
Download https://deno.land/std/textproto/mod.ts
Download https://deno.land/std/http/http_status.ts
Download https://deno.land/std/bytes/mod.ts
error: Uncaught PermissionDenied: network access to ":3000", run again with the --allow-net flag
at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
at Object.listen ($deno$/ops/net.ts:51:10)
at listen ($deno$/net.ts:152:22)
at serve (https://deno.land/std/http/server.ts:261:20)
at file:///Users/saigowtham/deno-examples/server.js:4:25
At the last, we see an error related to network access
.
This error has occurred because our code is executed in a secure sandbox.so that by default scripts don’t have permission to access the file system or opening network connections.Unless we need to explicitly give the permissions.
To give the above program a network access, we need to pass a --allow-net
flag to the command.
deno run --allow-net server.js
Output:
➜ deno-examples deno run --allow-net server.js
server is running on port 3000
Now, open your browser and navigate to localhost:3000
you will see a h1
element is rendered on the screen.
Dependency inspector
Deno has a built-in dependency inspector by using that we can view the dependency tree of our programs.
Let’s see the dependency tree of our server.js
file by running the below command.
deno info server.js
Now, you can see the following output in your terminal.
➜ deno-examples deno info server.js
local: /Users/saigowtham/deno-examples/server.js
type: JavaScript
deps:
file:///Users/saigowtham/deno-examples/server.js
└─┬ https://deno.land/std/http/server.ts
├── https://deno.land/std/encoding/utf8.ts
├─┬ https://deno.land/std/io/bufio.ts
│ ├─┬ https://deno.land/std/io/util.ts
│ │ ├─┬ https://deno.land/std/path/mod.ts
│ │ │ ├─┬ https://deno.land/std/path/win32.ts
│ │ │ │ ├── https://deno.land/std/path/_constants.ts
│ │ │ │ ├─┬ https://deno.land/std/path/_util.ts
│ │ │ │ │ └── https://deno.land/std/path/_constants.ts
│ │ │ │ └─┬ https://deno.land/std/testing/asserts.ts
│ │ │ │ ├── https://deno.land/std/fmt/colors.ts
│ │ │ │ └── https://deno.land/std/testing/diff.ts
│ │ │ ├─┬ https://deno.land/std/path/posix.ts
│ │ │ │ ├── https://deno.land/std/path/_constants.ts
│ │ │ │ └── https://deno.land/std/path/_util.ts
│ │ │ ├─┬ https://deno.land/std/path/common.ts
│ │ │ │ └── https://deno.land/std/path/separator.ts
│ │ │ ├── https://deno.land/std/path/separator.ts
│ │ │ ├── https://deno.land/std/path/interface.ts
│ │ │ └─┬ https://deno.land/std/path/glob.ts
│ │ │ ├── https://deno.land/std/path/separator.ts
│ │ │ ├── https://deno.land/std/path/_globrex.ts
│ │ │ ├── https://deno.land/std/path/mod.ts
│ │ │ └── https://deno.land/std/testing/asserts.ts
│ │ └── https://deno.land/std/encoding/utf8.ts
│ └── https://deno.land/std/testing/asserts.ts
├── https://deno.land/std/testing/asserts.ts
├─┬ https://deno.land/std/async/mod.ts
│ ├── https://deno.land/std/async/deferred.ts
│ ├── https://deno.land/std/async/delay.ts
│ └─┬ https://deno.land/std/async/mux_async_iterator.ts
│ └── https://deno.land/std/async/deferred.ts
└─┬ https://deno.land/std/http/_io.ts
├── https://deno.land/std/io/bufio.ts
├─┬ https://deno.land/std/textproto/mod.ts
│ ├── https://deno.land/std/io/util.ts
│ ├─┬ https://deno.land/std/bytes/mod.ts
│ │ └── https://deno.land/std/io/util.ts
│ └── https://deno.land/std/encoding/utf8.ts
├── https://deno.land/std/testing/asserts.ts
├── https://deno.land/std/encoding/utf8.ts
├── https://deno.land/std/http/server.ts
└── https://deno.land/std/http/http_status.ts
Code formatting
Deno also has built-in code formatter to format our code, and also adds missing semicolons to our code.
To use this, we need to run the deno fmt
command.
deno fmt
It formats all files in your app.
If you want to format a single file, you need to run deno fmt
command followed by the file-name.
deno fmt server.js
Resources
Here are some resources, you can learn more about deno.