乐趣区

关于deno:deno怎么复用node的包

上文说过,deno 目前最大的问题是生态,也就是说仍无奈无缝继承 nodejs 的生态。那它也意味着能够应用一部分 nodejs 的资源。

以 AST(形象语法树)为例,它在底层工作时还是很有必要的,咱们可能会用它写个小工具,实现一些简略的代码转换。但咱们在 deno.land 中查找第三方库,却没有找到适合的。

怎么办?
这时你首先想到的不该是“正是我辈大展身手造轮子的时候到了”,而是应该想,node 的 npm 包是不是能够复用?

node 版本

AST 有各种实现版本,比拟闻名的是 babel。 这里我找两个简略的 esprimaescodegen

const esprima = require('esprima');
const escodegen = require('escodegen');

const encodeJs = function () {
    const str = `
    global.x = 10;
    name += '-abc';
    age = 12;
    `;
    const AST = esprima.parse(str);
    // console.log(AST);
    // console.log(AST.body[0].expression.left.object.name);
    // console.log(result.body[0].consequent.body[0].expression.left);

    AST.body.splice(0, 1); // remove global.x = 10;

    const originReback = escodegen.generate(AST);
    console.log(originReback); // name += '-abc';age = 12;
};

encodeJs();

咱们先在 npm 上看下这两个包的依赖状况:


一个零依赖,一个依赖了 5 个包。还是很有心愿通过 CDN 本义过去的。

deno 版本

咱们试试 CDN(通常有 https://esm.sh/ 和 https://cdn.skypack.dev/ 两个,这里任选一个)转下:
https://cdn.skypack.dev/esprima

https://cdn.skypack.dev/escodegen

仿佛是能够的,于是咱们能够试下:

import * as esprima from 'https://cdn.skypack.dev/esprima';
import * as escodegen from "https://cdn.skypack.dev/escodegen";

const encodeJs = function () {
    const str = `
    global.x = 10;
    name += '-abc';
    age = 12;
    `;
    const AST = esprima.parse(str);
 
    AST.body.splice(0, 1); // remove global.x = 10;

    const originReback = escodegen.generate(AST);
    console.log(originReback); // name += '-abc';age = 12;
};

encodeJs();

执行 deno run xx.js,胜利!

真是个欢快的音讯。这意味着咱们不须要再造轮子。这样即便这两个包有什么 bug,你只须要去 github 提 issue,到时候降级版本就行了。

留神

不过有点儿须要留神,假如你要在我的项目中应用,最好将 版本号 写上,比方:

import * as esprima from 'https://cdn.skypack.dev/esprima@v2.0.0';

但这样还不够,如果你要应用 deno 的 lock.json 文件来保障我的项目各成员或各个环境都能应用雷同的版本,咱们所用的这个 CDN 并不能保障它的 hash 值不变动(也就是说隔断工夫对应的 hash 值会变动,也会导致 deno cache –lock=lock.json 校验失败),即便版本号是固定的。
那么应该怎么办呢?

再回头认真看下面 CDN 生成的文件内容:

这里有个 Pinned URL,它便是正解。
所以,最终的代码变成这样:

import * as esprima from 'https://cdn.skypack.dev/pin/esprima@v4.0.1-2bFId5CSQMZAdjdZliQ2/mode=imports/optimized/esprima.js';
import * as escodegen from "https://cdn.skypack.dev/pin/escodegen@v2.0.0-MB39rvARiyYcecqDvQhe/mode=imports/optimized/escodegen.js";

const encodeJs = function () {
    const str = `
    global.x = 10;
    name += '-abc';
    age = 12;
    `;
    const AST = esprima.parse(str);
  
    AST.body.splice(0, 1); // remove global.x = 10;

    const originReback = escodegen.generate(AST);
    console.log(originReback); // name += '-abc';age = 12;
};

encodeJs();

毛病

咱们应用 deno,举荐间接应用 TS,但这个包没有 ts 文件,也就没有类型文件。到 github 上看下:

果然是用 js 写的。
针对这种状况,咱们要么这么忍了,要么只能本人给写个.d.ts 文件了。

typescript 类型推断

对于自身是用 ts 写的 npm 包,以 jwfetch 为例,只须要在前面加个 ?dts 即可,如:

import {BaseAjax} from "https://cdn.skypack.dev/jwfetch?dts";

运行代码,控制台显示:
咱们看到,类型文件.d.ts 都下载下来了。这样类型推断就有了。

但要按下面说的,固定咱们的版本与 hash 的话,就只能:

import {BaseAjax} from "https://cdn.skypack.dev/pin/jwfetch@v1.1.2-1LpCExuOCuNK2LPTj1mF/mode=imports/optimized/jwfetch.js";

这种状况又会有个问题,这只是一个 js 文件,并没有类型文件,怎么办?别慌,只须要加 // @deno-types 就行了:

// @deno-types='https://cdn.skypack.dev/-/jwfetch@v1.1.2-1LpCExuOCuNK2LPTj1mF/dist=es2019,mode=types/dist/index.d.ts'
import {BaseAjax} from "https://cdn.skypack.dev/pin/jwfetch@v1.1.2-1LpCExuOCuNK2LPTj1mF/mode=imports/optimized/jwfetch.js";

BaseAjax.defaults.baseURL = "https://api.github.com";
console.log(BaseAjax);

总结

本文以 AST 为例,教你在应用 deno 进行开发的过程中,如何利用 CDN 来复用 npm 的 node 包。node.js 曾经倒退了十余年,其中积攒了不可计数的资源,咱们要尽可能地复用它们,以晋升开发效率。

退出移动版