4
头图

This is the 99th original without water. If you want to get more original good articles, please search the public and follow us~ This article first appeared on the front-end blog of Zheng Caiyun: 1609b51c4d3add Talk about Deno's things

What is Deno

deno1

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

Deno is an anagram of Node, and its pronunciation is the abbreviation of dinosaur, "蒂诺".

It is built on:

  • Rust (The bottom layer of Deno is developed with Rust, while Node is developed with C++)
  • Tokio (Deno's event mechanism is based on Tokio, and Node is based on libuv)
  • TypeScript
  • V8

Deno's background

deno演讲.png

Deno originated from the creator of Node Ryan Dahl , which is one of the reasons why everyone is looking forward to the Deno project. On JSConfEu, Dahl in his speech some of the defects in Node, and explained how to make better decisions around the Node architecture. At the end of the speech, Deno was announced. And promised to build a better and safer runtime environment.

Defects of Node

Native API lacks Promise

The biggest highlight of Node is the event-driven, non-blocking I/O model, which makes Node has strong concurrent processing capabilities and is very suitable for writing network applications. Most I/O operations in Node are almost asynchronous, so Callback Hell is produced:

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

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

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

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);
  })

Lack of security

In Node, you can call fs.chmod to modify the read and write permissions of files or directories. It shows that the permissions of Node runtime are very high. If you import an untrusted software package in Node, it will most likely delete all files on your computer, so Node lacks a secure and modular runtime. Unless you manually provide a sandbox environment, a container environment such as Docker to solve the security problem.

const fs = require('fs');
//删除hello.txt
fs.unlinkSync('./hello.txt');
// 删除css文件夹
fs.rmdirSync('./css');

The build system is different from Chrome

v8编译.png

First of all, we need to understand what the build system is?

The children's shoes who are used to writing the front end may not understand what this thing is for? But in fact, you will usually come into contact with it, but the concept is different. The front-end is generally called packaged construction, similar to what tools such as webpack, rollup, and parcel do. In fact, their ultimate goal is to get some of the target file, where our goal is to compiled V8 code.

Node's V8 build system is (Generate Your Projects), while Chrome's V8 has been upgraded to GN (Generate Ninja). We know that V8 was developed by Google, which also proves that Node and Google’s son Chrome are drifting away, and the construction speed of GN is 20 times faster than GYP, because GN is written in C++, which is faster than GYP written in python a lot of. But the underlying architecture of Node is irretrievable.

Complex package management model

deno模块太阳.png

In Node's own NPM ecosystem, due to the heavy reliance on semantic version control and complex dependency graphs, it is indispensable to deal with package.json and node_modules. Although the design of node_modules can meet most scenarios, it still has various defects, especially in the field of front-end engineering, which has caused many problems. Especially when the dependency versions of different packages are inconsistent, various problems will follow one after another, so yarn lock and npm lock appear on the scene.

However, there are still many scenarios that cannot be covered by lock. For example, when we install a dependency for the first time, even if the third-party library contains the lock file, npm install|, yarn install will not read the third-party Dependent lock, which leads to the possibility of triggering bugs when the project is created for the first time. Moreover, due to cross-dependency, node_modules is full of various repeated versions of packages, resulting in a huge waste of space, also causing install dependent packages to be very slow, and require algorithms to read files are becoming more and more complicated.

Complicated reading of files

Node uses require reference other script files, and its internal logic is as follows:

当 Node 遇到 require(X) 时,按下面的顺序处理。
(1)如果 X 是内置模块(比如 require('http'))
  a. 返回该模块。
  b. 不再继续执行。

(2)如果 X 以 "./" 或者 "/" 或者 "../" 开头
  a. 根据 X 所在的父模块,确定 X 的绝对路径。
  b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
      X
      X.js
      X.json
      X.node
  c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
      X/package.json(main字段)
      X/index.js
      X/index.json
      X/index.node
      
(3)如果 X 不带路径
  a. 根据 X 所在的父模块,确定 X 可能的安装目录。
  b. 依次在每个目录中,将 X 当成文件名或目录名加载。

(4) 抛出 "not found"

It can be seen that the read logic of require is very complicated. Although it is cute to use, it is not necessary.

Deno's architecture

deno源码.png

  1. Deno uses Rust as the startup entry, executes C++ code through Rust FFI, and then introduces V8 examples into C++.
  2. Initialize V8 objects and inject external C++ methods, such as send and recv methods.
  3. Inject Deno objects into the global scope of V8, exposing some basic Deno APIs to JavaScript.
  4. Through the C++ method bound to V8, call the corresponding Rust method to execute the underlying logic.

It is not difficult to find that Deno is actually similar to RN and Flutter frameworks, because it essentially runs a JS engine, but this JS engine is V8 and is not responsible for UI binding. Therefore, the essence of the architecture is the re-engraving of ideas and the reorganization of modules.

Features of Deno

Safety

deno-sec.png

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

  • File system
  • The internet
  • Environment variable

You can turn on the permissions that are turned off by default through command line parameters, similar to the following:

// 授予从磁盘读取和侦听网络的权限
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts

// 授予从磁盘filepath读取白名单文件的权限
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts

// 授予所有权限
deno run --allow-all https://deno.land/std/http/file_server.ts

Or control permissions through programming, similar to the following:

// 检测是否有读取权限
const status = await Deno.permissions.query({ name: "write" });
if (status.state !== "granted") {
  throw new Error("need write permission");
}

// 读取log文件
const log = await Deno.open("request.log", "a+");

// 关闭读写权限
await Deno.permissions.revoke({ name: "read" });
await Deno.permissions.revoke({ name: "write" });

// 打印log内容
const encoder = new TextEncoder();
await log.write(encoder.encode("hello\n"));

Built-in tools

deno恐龙标志

Deno currently provides the following built-in tools, which are very useful when using JavaScript and TypeScript. You only need to execute the following commands:

  • deno bundler (With packaging and tree shaking functions, we can package our code into a single file)
  • deno compile (build the Deno project as a completely independent executable file)
  • deno installe (our code can be generated into an executable file for direct use)
  • deno info (View the dependency tree of all modules)
  • deno doc (generate documentation from the comments in the source code)
  • deno fmt (recursively format each file in each subdirectory)
  • deno repl (start a read-eval-print-loop, which allows you to interactively build the program state in the global context)
  • deno test (unit test the file named .test)
  • deno lint (code detector)

Support TyprScript

tsbanner.jpeg

Using Deno to run TypeScript code does not require compilation steps and tedious configuration files-Deno will automatically perform this step for you.

source code , we found that Deno actually integrates a TypeScript compiler and a small compiler host for runtime snapshots. The converted core code as follows:

// globalThis.exec 这个函数在/cli/tsc/99_main_compiler.js中
// 其主要作用就是把TypeScript转换成JavaScript
let exec_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)?;

Some time ago, Deno's internal discussion of changing TS back to JS was very lively, but it does not mean that Deno gave up TypeScript, it is still a safe TS/JS Runtime.

E.g:

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

You can run it directly on the command line and print out the hello word:

deno run index.ts

Support ES module standard

Deno uses the browser implementation of ES Module. ES Module should be familiar to everyone. It is the official standardized module system of JavaScript. Its browser implementation is as follows:

// 从 URL 导入import 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";

It should be noted that Deno does not support the following writing methods:

import foo from "foo.js";import bar from "bar/index.js";import zoo from "./index"; // 没有后缀

Compatible with browser API

chromebanner.png

Deno reduces everyone's awareness by keeping it consistent with the browser API.

  • Module system: It can be seen from the above introduction that Deno is implemented in full compliance with the browser.
  • Secure by default
  • Return Promise for asynchronous operation
  • Use ArrayBuffer to process binary
  • There is a window global variable
  • Supports web standards such as fetch, webCrypto, worker, etc., and also supports event operation functions such as onload, onunload, addEventListener, etc.
console.log(window === this, window === self, window === globalThis); // true true true

Support Promise

promisebanner.png

All asynchronous operations of Deno always return Promise and support await globally.

// 读取异步接口数据const response = await 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));

Decentralized package

Deno does not have package.json and node_modules, so how does it manage package? Let's look at the following example first:

// index.jsimport { white, bgRed } from "https://deno.land/std/fmt/colors.ts";console.log(bgRed(white("hello world!")));// 命令行执行> deno run index.jsDownload https://deno.land/std/fmt/colors.tsCompile https://deno.land/std/fmt/colors.tshello world!

We see that there will be Download and Compile during execution, so we will have a few questions:

1. Do I have to download every time I execute it?

Answer: There is no need to download every time, there is a cache mechanism.

> deno run index.jshello world!

2. Where are the files for Download and Compile?

Answer: We can check the dependencies through 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)

3. What should I do if the dependent code is updated?

Answer: When the dependent module is updated, we can --reload , for example:

> deno run --reload index.js// 通过白名单的方式更新部分依赖> deno run --reload=https://deno.land index.js

4. How to deal with multiple versions?

Answer: There is no good solution for the time being, only the version can be distinguished by git tag.

Deno imports code via URL, and can host modules anywhere on the Internet. And compared to Node's require to read files, it is more lightweight and exquisite, and it can distribute Deno software packages without a centralized registry. No package.json file and dependency list are needed, because all modules are downloaded, compiled and cached while the application is running.

Get started with Deno

installation

Use Shell (macOS 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

Run deno --version , if it prints out the Deno version, the installation is successful.

> deno --versiondeno 1.8.1 (release, aarch64-apple-darwin)v8 9.0.257.3typescript 4.2.2

Actual combat experience

deno-getting-started.jpeg

Hello Word

Create an index.ts file locally, the content is as follows:

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

Open the terminal and enter the following command line:

> deno run index.ts

The above output is "Welcome to Deno 🦕".

HTTP request

Create a http.ts file locally, the content is as follows:

const url = Deno.args[0]; // 取得第一个命令行参数,存储到变量 url。const res = await fetch(url); // 向指定的地址发出请求,等待响应,然后存储到变量 res。const body = new Uint8Array(await res.arrayBuffer()); // 把响应体解析为一个 ArrayBuffer,等待接收完毕,将其转换为 Uint8Array,最后存储到变量 body。await Deno.stdout.write(body); // 把 body 的内容写入标准输出流 stdout。

Open the terminal and enter the following command line:

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

The above outputs the json object.

Remote import

add and multiply method from the remote module:

import {  add,  multiply,} from "https://x.nest.land/ramda@0.27.0/source/index.js";function totalCost(outbound: number, inbound: number, tax: number): number {  return multiply(add(outbound, inbound), tax);}console.log(totalCost(19, 31, 1.2)); // 60console.log(totalCost(45, 27, 1.15)); // 82.8

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, 0, 1, 112, 0, 0,  5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145,  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, 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());

Open the terminal and enter the following command line:

> deno run wasm.ts

The above outputs the number 42.

RESTful service

// restful.tsimport { Application, Router } from "https://deno.land/x/oak/mod.ts";const books = new Map<string, any>();books.set("1", {  id: "1",  title: "平凡的世界",  author: "路遥",});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 });

Enter the following command in the terminal:

> deno run  --allow-net restful.ts

Local access to http://localhost:8000/book/1 will return the book data with id 1.

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(), // 静态资源的根路径  });});await app.listen({ hostname: "127.0.0.1", port: 8000 });

Enter the following command in the terminal:

> deno run  --allow-net --allow-read static.ts

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

Concluding remarks

Deno is a very great project, but it is not "Next Generation Nods.js" . Ryan Dahl himself said: "Node.js isn't going anywhere" . In addition, Deno is still under development and its function is not stable, so it is not recommended to be used in a production environment. However, it is already a usable tool, and there are many new features that Node does not have. You can try it out.

Recommended reading

data visualization exploration

H5 page list caching scheme

Recruitment

ZooTeam, a young, passionate and creative front-end team, is affiliated to the product development department of Zheng Caiyun. The Base is located in picturesque Hangzhou. The team now has more than 40 front-end partners with an average age of 27 years old. Nearly 30% are full-stack engineers, a proper youth storm troupe. The membership consists of not only “veteran” soldiers from Ali and Netease, as well as newcomers from Zhejiang University, University of Science and Technology of China, Hangzhou Electric Power and other schools. In addition to the daily business docking, the team also conducts technical exploration and actual combat in the material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, and promotes and implements a series of internal technical products. Explore the new boundaries of the front-end technology system.

If you want to change that you have been tossed by things, hope to start to toss things; if you want to change and have been warned, you need more ideas, but you can’t break the game; if you want to change you have the ability to make that result, but you don’t need you; If you want to change what you want to accomplish, you need a team to support, but there is no position for you to lead people; if you want to change the established rhythm, it will be "5 years of work time and 3 years of work experience"; if you want to change the original The comprehension is good, but there is always the ambiguity of the window paper... If you believe in the power of belief, believe that ordinary people can achieve extraordinary things, believe that you can meet a better self. If you want to participate in the process of business take-off, and personally promote the growth of a front-end team with in-depth business understanding, complete technical system, technology to create value, and influence spillover, I think we should talk. Anytime, waiting for you to write something, send it to ZooTeam@cai-inc.com


政采云前端团队
3.8k 声望4k 粉丝

Z 是政采云拼音首字母,oo 是无穷的符号,结合 Zoo 有生物圈的含义。寄望我们的前端 ZooTeam 团队,不论是人才梯队,还是技术体系,都能各面兼备,成长为一个生态,卓越且持续卓越。