This is the 99th unwatered original, want to get more original good articles, please search the public number to follow us ~ this article first appeared in the political cloud front blog: Talk about Deno those things

What is Deno

Deno is a simple, modern, and secure JavaScript, TypeScript, Webassembly runtime environment.

Deno is an anagram of “Node”, pronounced “dino”, short for “dinosaur”.

It is built on:

  • Rust (the underlying Deno is developed with Rust, whereas Node is developed with C++)
  • Tokio (Deno’s event mechanism is based on Tokio, Node is based on Libuv)
  • TypeScript
  • V8

Deno background

Deno originated with Ryan Dahl, the founder of Node, which is one of the reasons why the Deno project is so exciting. At JSConfEu, Dahl spoke about some of Node’s flaws and explained how to make better decisions around Node’s architecture. At the end of his talk, he announced the first prototype of Deno and promised to build a better and safer runtime environment.

The defect of the Node

Native apis lack promises

The biggest highlight of Node is its event-driven, non-blocking I/O model, which enables Node to have strong concurrent processing capability and is very suitable for writing network applications. Most I/O operations in Node are almost asynchronous, so Callback Hell produces:

// fs.js
const fs = require('fs');
const myFile = '/tmp/test';

fs.readFile(myFile, 'utf8'.(err, txt) = > {
  if (!err) {
    fs.writeFile(myFile);
  }
});
Copy the code

To implement chained calls, you need to repackage the native API with a Promise, as follows:

const fs = require("fs");
const myFile = '/tmp/test';

function readFile_promise(path) {
  return new Promise((resolve, reject) = > {
    fs.readfile(path, "utf-8".(err, data) = > {
      if (err) {
        reject(err);
      } else{ resolve(data); }})}); } readFile_promise(myFile) .then((res) = > {
    fs.writeFile(myFile, res);
  })
Copy the code

Lack of security

In Node, you can call fs.chmod to change read/write permissions on a file or directory. Note Nodes have high permissions when running. If you import an untrusted package into Node, chances are it will delete all the files on your computer, so Node lacks a secure modular runtime. Unless you manually provide a sandbox environment, a container environment like Docker solves the security problem.

const fs = require('fs');
/ / remove the hello. TXT
fs.unlinkSync('./hello.txt');
// Delete the CSS folder
fs.rmdirSync('./css');
Copy the code

The build system is different from Chrome

The first thing we need to understand is what is a build system?

Write to be used to the front end of children’s shoes may not understand this thing is very dry what to use? But in fact, you will be exposed to the ordinary, just a different concept. The front end is what we call a packaged build, similar to what tools like WebPack, Rollup, and Parcel do. They all end up trying to get some targeted files, in this case compiling V8 code.

Node’s V8 build system is GYP (Generate Your Projects), while Chrome’s V8 has been upgraded to GN (Generate Ninja). We know that V8 was developed by Google, which proves that Node is drifting away from Google’s own son Chrome, and that GN is 20 times faster to build than GYP because GN is written in C++, which is much faster than GYP written in python. However, the underlying Node architecture is irreparable.

Complex package management patterns

Node’s own NPM ecosystem relies heavily on semantic versioning and complex dependency diagrams, making it necessary to deal with package.json and node_modules. The design of Node_modules can satisfy most scenarios, but it still has many defects, especially in the field of front-end engineering, causing a lot of problems. In particular, when different packages depend on different versions, various problems arise one after another. This is why YARN Lock and NPM Lock appear.

However there are still a lot of scenarios is the lock cannot be covered, such as when we install a rely on for the first time, this time even if the third party database contains the lock file, but the NPM install |, yarn, the install will not go to read the third party relies on the lock, This causes bugs to be triggered the first time the project is created. And because of cross-dependencies, node_modules is full of duplicate packages, resulting in a huge waste of space, slow install dependencies, and increasingly complex algorithms that require reading files.

File reading complexity

Node uses require to reference other script files. Its internal logic is as follows:

When the Noderequire(X), in the following order. (1If X is a built-in module (e.grequire('http')) a. Return the module. B. No further action is required. (2) if X begins with". /"or"/"or".. /"Start a. Determine the absolute path of X according to the parent module where X resides. B. Consider X as a file and look for the following files in turn. If one of the files exists, the file is returned. X.js x.son x.ode c. Consider X as a directory and search for the following files one by one. If any of them exists, the file is returned. X/package.json (main field) X/index.js X/index.json X/index.node (main field) X/index.js X/index.json X/index.node (3) If X does not have a path a. Determine the possible installation directory of X based on the parent module where X resides. B. Load X as a file name or directory name in each directory in turn. (4) throws"not found"
Copy the code

As you can see, the read logic for require is quite complex and, while cute to use, unnecessary.

Deno architecture

  1. Deno starts with Rust, executes C++ code through Rust FFI, and then introduces V8 instances in C++.

  2. Initialize V8 objects and inject external C++ methods such as send, recv, and so on.

  3. Inject Deno objects into the V8 global scope, exposing some of Deno’s basic apis to JavaScript.

  4. Using C++ methods bound to V8, invoke the corresponding Rust method to execute the underlying logic.

It’s not hard to see that Deno is very similar to frameworks like RN and Flutter, because it’s basically a JS engine, but it’s a V8 JS engine that doesn’t handle UI binding. So the essence of architecture is to copy ideas and restructure modules.

The characteristics of Deno

security

In contrast to Node, Deno executes code in a sandbox by default, which means that the following permissions cannot be accessed at runtime:

  • The file system
  • network
  • The environment variable

You can enable the default permissions by using command-line arguments like this:

// Grant the permission to read and listen on the network from disk
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts

// Grant permission to read whitelisted files from disk filepath
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts

// Grant all permissions
deno run --allow-all https://deno.land/std/http/file_server.ts

Copy the code

Or programmatically control permissions, like this:

// Check whether you have read permission
const status = await Deno.permissions.query({ name: "write" });
if(status.state ! = ="granted") {
  throw new Error("need write permission");
}

// Read the log file
const log = await Deno.open("request.log"."a+");

// Disable the read and write permission
await Deno.permissions.revoke({ name: "read" });
await Deno.permissions.revoke({ name: "write" });

// Print the log contents
const encoder = new TextEncoder();
await log.write(encoder.encode("hello\n"));
Copy the code

Built-in tools

Deno currently provides the following built-in tools that are useful when working with JavaScript and TypeScript by executing the following commands:

  • Deno Bundler (comes with packaging and Tree Shaking to package our code into a single file)
  • Deno compile (build the DENo project into a fully independent executable file)
  • Deno Installe (can generate executable files from our code for direct use)
  • Deno Info (view dependency tree for all modules)
  • Deno doc (document comments in source code)
  • Deno FMT (recursively formats each file in each subdirectory)
  • Deno repl (starts a read-eval-print-loop, which allows you to interactively build program state in a global context)
  • Deno test (unit tests a file named.test)
  • Deno Lint (code detector)

Support TyprScript

Running TypeScript code with Deno doesn’t require compilation steps and tedious configuration files — Deno does it for you automatically.

In the source code, we find that Deno actually integrates a TypeScript compiler with a small compiler host for runtime snapshots. The core code for the transformation is as follows:

// The globalthis. exec function is in /cli/ TSC /99_main_compiler.js
// The main function is to convert TypeScript to JavaScript
letexec_source = format! ("globalThis.exec({})", request_str);

  runtime
    .execute("[native code]", startup_source)
    .context("Could not properly start the compiler runtime.")? ; runtime.execute("[native_code]", &exec_source)? ;Copy the code

There has been a lot of talk within Deno about changing TS back to JS, but that doesn’t mean Deno is abandoning TypeScript. It’s still a secure TS/JS Runtime.

Such as:

// index.ts
const str: string = 'hello word';
console.log(str);
Copy the code

You can run it directly from the command line and print out Hello Word:

deno run index.ts
Copy the code

Supports the ES module standard

Deno uses the browser implementation of the ES Module. ES Module is the official, standardized JavaScript Module system. The browser implementation looks like this:

/ / from the URL to import the import the React from "https://cdn.bootcdn.net/ajax/libs/react/17.0.1/cjs/react-jsx-dev-runtime.development.js". // Import * as Api from "./service.js"; // Import "/index.js" from the absolute path;
Copy the code

Note that Deno does not support the following:

import foo from "foo.js";import bar from "bar/index.js";import zoo from "./index"; // No suffix
Copy the code

Compatible with browser API

Deno reduces awareness by being consistent with the browser API.

  • Modular system: As you can see from the above, Deno is fully browser-compliant.
  • The default security
  • Returns a Promise for asynchronous operations
  • Use ArrayBuffer to process binary
  • The window global variable exists
  • It supports Web standards such as FETCH, webCrypto and Worker, as well as event operation functions such as OnLoad, onUnload and addEventListener
console.log(window= = =this.window === self, window === globalThis); // true true true
Copy the code

Supporting Promise

Deno returns promises for all asynchronous operations and supports await globally.

/ / read asynchronous interface data const response = await the fetch (" http://my.json.host/data.json "); console.log(response.status)console.log(response.statusText); const jsonData = await response.json(); Const decoder = new TextDecoder(" utF-8 "); const data = await Deno.readFile("hello.txt"); console.log(decoder.decode(data));
Copy the code

Decentralized packages

Deno has no package.json, node_modules, so how does it manage packages? Let’s start with the following example:

// index.jsimport { white, bgRed } from "https://deno.land/std/fmt/colors.ts"; console.log(bgRed(white("hello world!" ))); / / command line to perform > deno run index. JsDownload https://deno.land/std/fmt/colors.tsCompile https://deno.land/std/fmt/colors.tshello world!
Copy the code

We see that there are two steps, Compile and Download, so we have a few questions:

1. Do you need to download each execution?

A: No need for every download, there is a caching mechanism.

> deno run index.jshello world!
Copy the code

Where are the files for Download and Compile?

A: You can view dependencies using the built-in tool deno Info described above.

> deno info index.jslocal: /Users/xxx/Desktop/index.tstype: TypeScriptemit: /Users/xxx/Library/Caches/deno/gen/file/Users/xxx/Desktop/index.ts.jsdependencies: 0 unique (total 41B)file:///Users/xxx/Desktop/index.ts (41B)
Copy the code

3. What if the dependent code is updated?

A: When a dependent module is updated, we can update the cache with –reload, for example:

> deno run --reload index.js// Update partial dependencies by whitelist > deno run --reload=https://deno.land index.js
Copy the code

4. How to deal with multiple versions?

A: There is no good solution for the time being, and we can only use Git tag to distinguish versions.

Deno is a URL import code that can host modules anywhere on the Internet. It’s also much smaller than Node’s require to read files, and distributes Deno packages without a centralized registry. There is no need for package.json files and dependency lists because all modules are downloaded, compiled, and cached while the application is running.

Overhand Deno

The installation

Using Shell (macOS and Linux):

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

Using PowerShell (Windows) :

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

Run deno –version. If it prints out the DENO version, the installation is successful.

> deno --versiondeno 1.81. (release, aarch64-apple-darwin)v8 9.0257..3typescript 4.22.
Copy the code

Actual combat experience

Hello Word

Create a local index.ts file with the following contents:

// index.tsconsole.log("Welcome to Deno 🦕");
Copy the code

Open the terminal and enter the following command line:

> deno run index.ts
Copy the code

The above output is “Welcome to Deno 🦕”.

The HTTP request

Create a local http.ts file with the following contents:

const url = Deno.args[0]; // Get the first command-line argument and store it in the variable URL. const res = await fetch(url); // Send the request to the specified address, wait for the response, and then store it in the variable res. const body = new Uint8Array(await res.arrayBuffer()); // Parse the response body into an ArrayBuffer, wait for it to be received, convert it into Uint8Array and store it in the body variable. await Deno.stdout.write(body); // Write the body contents to stdout.
Copy the code

Open the terminal and enter the following command line:

deno run --allow-net=api.github.com http.ts https://api.github.com/users/answer518
Copy the code

The above output json objects.

Remote import

Import the Add and Multiply methods from a remote module:

import {  add,  multiply,} from "https://x.nest.land/[email protected]/source/index.js";function totalCost(outbound: number, inbound: number, tax: number) :number {  returnmultiply(add(outbound, inbound), tax); }console.log(totalCost(19.31.1.2)); / / 60 console. The log (totalCost (45, 27, 1.15)); / / 82.8
Copy the code

Support WASM

// wasm.tsconst wasmCode = new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 128, 0, 0, 65, 42, 11]); const wasmModule = new WebAssembly.Module(wasmCode); const wasmInstance = new WebAssembly.Instance(wasmModule); const main = wasmInstance.exports.main as CallableFunction; console.log(main().toString());
Copy the code

Open the terminal and enter the following command line:

> deno run wasm.ts
Copy the code

The above output number 42.

RESTful services

// restful.tsimport { Application, Router } from "https://deno.land/x/oak/mod.ts"; const books = new Map
      
       (); Books. Set (" 1 ", {id: "1", the title: "ordinary world", the author: "lu yao,"}); const router = new Router(); router .get("/", (context) => { context.response.body = "Hello world!" ; }) .get("/book", (context) => { context.response.body = Array.from(books.values()); }) .get("/book/:id", (context) => { if (context.params && context.params.id && books.has(context.params.id)) { context.response.body = books.get(context.params.id); }}); const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods()); Await app.listen({hostname: '127.0.0.1', port: 8000});
      ,>
Copy the code

The terminal enters the following command:

> deno run  --allow-net restful.ts
Copy the code

Local access http://localhost:8000/book/1 will return id of 1 book data.

Static resource service

// static.tsimport { Application } from "https://deno.land/x/oak/mod.ts"; const app = new Application(); App.use (async (context) => {await context.send({root: deno.cwd (), // root path of static resource}); }); Await app.listen({hostname: "127.0.0.1", port: 8000});
Copy the code

The terminal enters the following command:

> deno run  --allow-net --allow-read static.ts
Copy the code

Local access http://localhost:8000/static.ts will return the static. The source code of ts.

conclusion

Deno is a great project, but it’s not “next generation nodes.js”. Ryan Dahl himself said, “Node.js isn’t going anywhere.” In addition, Deno is still under development and its functionality is not yet stable, so it is not recommended for production. However, it is already a usable tool, and there are many new features that Node does not have that you can play with.

Recommended reading

SpreadJS for data visualization exploration

H5 Page list caching scheme

, recruiting

ZooTeam (ZooTeam), a young and creative team, belongs to the product RESEARCH and development department of ZooTeam, based in picturesque Hangzhou. The team now has more than 40 front end partners, the average age of 27 years old, nearly 30% are full stack engineers, no problem youth storm team. The membership consists of “old” soldiers from Alibaba and netease, as well as fresh graduates from Zhejiang University, University of Science and Technology of China, Hangzhou Electric And other universities. In addition to the daily business connection, the team also carried out technical exploration and actual practice in the direction of material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, promoted and implemented a series of internal technical products, and continued to explore the new boundary of the front-end technology system.

If you want to change the things you’ve been doing, you want to start doing things. If you want to change, you’ve been told you need to think more, but you can’t change; If you want to change, you have the power to achieve that result, but you are not needed; If you want to change what you want to accomplish, you need a team to support you, but there is no place for you to bring people; If you want a change of pace, it’s “3 years of experience in 5 years”; If you want to change the original savvy is good, but there is always a layer of fuzzy window paper… If you believe in the power of belief, that ordinary people can achieve extraordinary things, that you can meet a better version of yourself. If you want to get involved in the growth of a front end team with a deep understanding of the business, a sound technology system, technology that creates value, and spillover impact as the business takes off, I think we should talk about it. Any time, waiting for you to write something, to [email protected]