Easy to understand introduction to Deno

Keywords: Javascript TypeScript Mac Windows

 

1, About Deno

Deno is a JavaScript/TypeScript runtime, which executes code in a secure environment by default, with excellent development experience. Deno has the following features:

Default security. External code does not have access to file system, network and environment unless it is explicitly enabled.

An environment that supports TypeScript out of the box.

Only one independent executable (deno) is distributed.

There are built-in toolkits, such as a dependency information viewer (deno info) and a code formatter (deno fmt).

There is an audited set of standard modules that can work on Deno.

Script code can be packaged as a separate JavaScript file.

Deno is a cross platform runtime, that is, a runtime environment based on Google V8 engine. The runtime environment is developed using the Rust language, and the Tokio library is used to build the event loop system. Deno is based on V8, Rust and Tokio. Its architecture is as follows:

1.1 Rust

Rust is a general and compiled programming language developed by Mozilla. The design principle is "safe, concurrent and practical". It supports functional, concurrent, procedural and object-oriented programming styles. Deno uses the Rust language to encapsulate the V8 engine. By libdeno binding, we can call the isolation function in JavaScript.

1.2 Tokio

Tokio is the asynchronous runtime of the rule programming language, which provides an asynchronous event driven platform to build fast, reliable and lightweight network applications. Using the ownership and concurrency model of Rust to ensure thread safety. Built on top of Rust, Tokio provides extremely fast performance, making it an ideal choice for high-performance server applications. In Deno, Tokio is used to execute all asynchronous IO tasks in parallel.

1.3 V8

V8 is an open source JavaScript engine developed by Google, which is used in Google Chrome and Chromium. V8 improves performance by compiling JavaScript into machine code before it runs, rather than bytecode or interpretation. Furthermore, methods such as inline caching are used to improve performance. With these features, JavaScript programs are as fast as binary compilation as V8 engines. In Deno, the V8 engine is used to execute JavaScript code.

2, Install Deno

Deno can run on Mac OS, Linux and Windows. Deno is a separate executable that has no additional dependencies. You can install it in the following ways:

Using shell (MAC OS and Linux):

curl -fsSL https://deno.land/x/install/install.sh | sh

Use PowerShell (Windows):

iwr https://deno.land/x/install/install.ps1 -useb | iex

Using Scoop (Windows):

scoop install deno

Using chocolate (Windows):

choco install deno

Using homebrew (MAC OS):

brew install deno

Using Cargo (Windows, Mac OS, Linux):

cargo install deno

Deno can also be installed manually, just from the github.com/denoland/deno/releases Download a zip file. It contains only a single executable. On Mac OS and Linux, you need to set execution permissions for it. After you have successfully installed, you can view the installed version of Deno by executing the deno --version command:

$ deno --version
deno 1.0.0
v8 8.4.300
typescript 3.9.2

2.1 deno-cli

The Deno cli command line interface provides a set of integration functions, which allows you to immerse yourself in Deno's proprietary development environment. The following are all the subcommands supported by Deno version 1.0.0:

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

 

2.2 REPL

Enter the deno command in the command, and you will start a REPL (read execute print loop):

$ deno
Deno 1.0.0
exit using ctrl+d or close()

1 + 2
3
const name = "semlinker";
undefined
console.log(name);
semlinker
undefined

3, Deno's first experience

3.1 welcome demo

I'm sure some readers can't wait to install Deno. Now let's experience the Deno application. First open the command line you are familiar with, and then type the following command at the command line:

$ deno run https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.land/std/examples/welcome.ts
Welcome to Deno 🦕

 

By observing the above output, we can know that when you run deno run https://deno.land/std/examples/welcome.ts After the command, Deno will https://Deno.land/std/examples/welcome.ts URL address download welcome.ts Document, the contents of which are:

console.log("Welcome to Deno 🦕");

When the file is downloaded successfully, Deno will welcome.ts File is compiled, that is, compiled into welcome.ts.js File, and then the compiled JavaScript file is executed through the V8 engine. Note that if you rerun the above command at the command line, the generated files in the cache will be executed and will not be downloaded from the Internet again welcome.ts Documents.

$ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno 🦕

 

How do you prove that when you execute the above command again, Deno will give priority to executing the JavaScript file generated by compiling in the cache? Let's start with the deno info command, which displays information about the cache or source file:

$ deno info
DENO_DIR location: "/Users/fer/Library/Caches/deno"
Remote modules cache: "/Users/fer/Library/Caches/deno/deps"
TypeScript compiler cache: "/Users/fer/Library/Caches/deno/gen"

 

In the above output information, we see the record of TypeScript compiler cache. It is obvious that this is the directory of TypeScript compiler cache. After entering this directory, through layer by layer searching, we finally find it in the examples directory welcome.ts.js File:

➜ examples ls
welcome.ts.js welcome.ts.js.map welcome.ts.meta

Open Directory welcome.ts.js File, we can see the following:

"use strict";
console.log("Welcome to Deno 🦕");
//# sourceMappingURL=file:///Users/fer/Library/Caches/deno/gen/https/deno.land/std/examples/welcome.ts.js.map

 

Let's modify the file and add a line of output information to the file console.log("Hello Semlinker, from Cache"); as follows:

"use strict";
console.log("Hello Semlinker, from Cache");
console.log("Welcome to Deno 🦕");
//# sourceMappingURL=file:///Users/fer/Library/Caches/deno/gen/https/deno.land/std/examples/welcome.ts.js.map

 

We then re execute the following command on the command line:

$ deno run https://deno.land/std/examples/welcome.ts
Hello Semlinker, from Cache
Welcome to Deno 🦕

 

Now the question is again, how to force a cache refresh, that is, recompile the TypeScript code? To solve this problem, when running the deno run command, we need to add the -- reload flag to tell Deno to refresh the specified file:

$ deno run --reload https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.land/std/examples/welcome.ts
Welcome to Deno 🦕

 

In addition to the -- reload flag, the Deno run command supports many other flags. Interested readers can run the deno run --help command to see more information.

3.2 TCP echo server

We've shown you how to run the official welcome example. Let's show you how to create a simple TCP echo server using Deno. First, we create a learn deny project, then create a quickstart directory under the project, and then create an echo_server.ts File and enter the following code:

const listener = Deno.listen({ port: 8080 });
console.log("listening on 0.0.0.0:8080");
for await (const conn of listener) {
Deno.copy(conn, conn);
}

for await...of Statement creates an iteration loop on an asynchronous or synchronous iteratable object, including String,Array,Array-like Objects (such as arguments perhaps NodeList),TypedArray,Map, Set And custom asynchronous or synchronous iteratable objects.

for await...of The syntax of is as follows:

for await (variable of iterable) {statement}

 

 

After entering the above code, I believe that many readers will run the following commands directly on the command line like me:

➜ quickstart deno run ./echo_server.ts
Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.ts
error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
at unwrapResponse (denodeno/ops/dispatch_json.ts:43:11)
at Object.sendSync (denodeno/ops/dispatch_json.ts:72:10)
at Object.listen (denodeno/ops/net.ts:51:10)
at Object.listen (denodeno/net.ts:152:22)
at file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.ts:1:23

 

It's obviously a permission error. From the error message, Deno tells us that we need to set the -- allow net flag to allow network access. Why is that? This is because Deno is a JavaScript/TypeScript runtime, which executes code in a secure environment by default. Let's add the -- allow net flag and run echo again_ server.ts File:

➜ quickstart deno run --allow-net ./echo_server.ts
listening on 0.0.0.0:8080

 

After the server runs successfully, we use the nc command to test the function of the server:

➜ ~ nc localhost 8080
hell semlinker
hell semlinker

 

After introducing how to use Deno to create a simple TCP echo server, let's introduce how to use Deno to create a simple HTTP server.

3.3 HTTP Server

As with TCP Server, in the quickstart directory, we create a new http_server.ts File and enter the following:

import { serve } from "https://deno.land/std@v0.50.0/http/server.ts";

const PORT = 8080;
const s = serve({ port: PORT });

console.log(Listening on <http://localhost>:${PORT}/);

for await (const req of s) {
req.respond({ body: "Hello Semlinker\n" });
}

 

 

Friendly tip: in the actual development process, you can https://deno.land/std Address to get the required standard library version. In the example, we explicitly specify the version. Of course, you can not specify the version. For example: https://deno.land/std/http/server.ts .

In the above code, we import the serve function in the HTTP module of the Deno standard library, and then use this function to quickly create an HTTP server. The definition of this function is as follows:

// std/http/server.ts
export function serve(addr: string | HTTPOptions): Server {
if (typeof addr === "string") {
const [hostname, port] = addr.split("😊;
addr = { hostname, port: Number(port) };
}

const listener = listen(addr);
return new Server(listener);
}

 

 

The serve function receives a parameter of type string | HTTPOptions, where the HTTPOptions interface is defined as follows:

/** Options for creating an HTTP server. */
export type HTTPOptions = Omit<Deno.ListenOptions, "transport">;

export interface ListenOptions {
/** The port to listen on. /
port: number;
/* A literal IP address or host name that can be resolved to an IP address.
* If not specified, defaults to 0.0.0.0. */
hostname?: string;
}

 

 

When the input parameter type is string, the serve function will use the colon to cut the string, obtain the hostname and port, then wrap them as objects and assign them to the addr parameter, then use the addr parameter to call the listen function to further create the listener object, and finally call the new server to create the HTTP server.

After creating the HTTP server, let's start the server, open the command line and enter the following command:

➜ quickstart deno run --allow-net ./http_server.ts
Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/http_server.ts
Listening on http://localhost:8080/

Then open the browser and type in the address bar http://localhost:8080 / address, and then you will see the following in the current page:

Hello World\n

 

4, Debug Deno

Deno supports V8 Inspector Protocol. Use Chrome Devtools or other clients (such as VSCode) that support the protocol to debug the Deno program. To enable debugging, run Deno with the -- inspect or -- inspect BRK options. The corresponding options are described as follows:

–inspect=HOST:PORT
activate inspector on host:port (default: 127.0.0.1:9229)

–inspect-brk=HOST:PORT
activate inspector on host:port and break at start of user script
 

The - inspect option allows the debugger to connect at any point in time, while the - inspect BRK option waits for the debugger to connect and pauses execution at the first line of code.

4.1 Chrome Devtools

Let's use the Chrome developer tool to debug a simple program. We will use the file from std_ server.ts , which is a simple static file service.

Use the -- inspect BRK option to pause execution at the first line of code.

$ deno run --inspect-brk --allow-read --allow-net https://deno.land/std@v0.50.0/http/file_server.ts
Debugger listening on ws://127.0.0.1:9229/ws/1e82c406-85a9-44ab-86b6-7341583480b1
Download https://deno.land/std@v0.50.0/http/file_server.ts
Compile https://deno.land/std@v0.50.0/http/file_server.ts
...

Open chrome://inspect , click Inspect next to Target.

For more detailed debugging instructions, visit https://deno.land/manual/tools/debugger URL address.

4.2 VSCode

Deno can be debugged in VSCode. Official support for plug-ins is under development https://github.com/denoland/vscode_deno/issues/12, which we can also provide manually launch.json Configure to connect to the debugger:

{
"version": "0.2.0",
"configurations": [
{
"name": "Deno",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "deno",
"runtimeArgs": ["run", "–inspect-brk", "-A", "<entry_point>"],
"port": 9229
}
]
}

 

Note: add < entry_ Replace point > with the actual script name.

Let's try to debug the local source file and create server.ts :

import { serve } from "https://deno.land/std@v0.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" });
}

 

 

Set < entry_ Change point > to server.ts , and then run.

I wonder if my friends are interested in Deno after reading this article? If so, welcome to leave a message to me. I'll write another article about developing Web API with Deno later.

5, Reference resources

Deno Chinese Manual

the-deno-handbook

deno-first-approach

Here is a study route map

 

Posted by Japet on Wed, 20 May 2020 05:44:00 -0700