How does deno reuse node packages

Posted by sparshdharam on Mon, 27 Dec 2021 15:45:31 +0100

As mentioned above, the biggest problem of deno is ecology, that is, it is still unable to seamlessly inherit the ecology of nodejs. It also means that some nodejs resources can be used.

Taking AST (abstract syntax tree) as an example, it is still necessary to work at the bottom. We may use it to write a gadget to realize some simple code conversion deno.land Looking for a third-party library, but no suitable one was found.

What should I do?
At this time, your first thought should not be "it's time for our generation to make wheels", but should think, can node's npm package be reused?

node version

AST has various implementation versions, the more famous one is babel. Here I'm looking for two simple esprima and escogen.

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

Let's first look at the dependencies of these two packages on npm:


One is zero dependent, and the other is dependent on five packages. It is still very promising to escape through CDN.

deno version

Let's try CDN (usually https://esm.sh/ and https://cdn.skypack.dev /Two, choose one here) turn to the following:
https://cdn.skypack.dev/esprima

https://cdn.skypack.dev/escodegen

It seems possible, so we can try:

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

Execute DeNO run XX JS, success!

What pleasant news. That means we don't need to rebuild the wheel. In this way, even if there are any bug s in these two packages, you only need to go to github to raise the issue, and then upgrade the version.

be careful

However, it should be noted that if you want to use it in the project, you'd better write the version number, such as:

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

But that's not enough if you want to use deno's lock JSON file to ensure that all project members or environments can use the same version. The CDN we use does not guarantee that its hash value does not change (that is, the hash value corresponding to the interval time will change, which will also lead to the failure of deno cache --lock=lock.json verification), that is, the version number is fixed.
So what should we do?

Go back and take a closer look at the file generated by CDN above:

Here is a Pinned URL, which is the positive solution.
So the final code looks like this:

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

shortcoming

We use deno. It is recommended to use TS directly, but there is no TS file in this package, so there is no type file. Look at github:

Sure enough, it was written in js.
In view of this situation, we either put up with it, or we can only write it ourselves d.ts file.

typescript type inference

For the npm package written in ts, take jwfetch as an example, just add a? dts, such as:

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

Run the code and the console displays:
We see that type files d.ts has been downloaded. So type inference is available.

However, if we want to fix our version and hash according to the above, we can only:

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

In this case, there will be another problem. This is just a js file, and there is no type file. What should I do? Don't panic, just add / / @ 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);

summary

Taking AST as an example, this paper teaches you how to reuse the node package of npm by using CDN in the process of developing with deno. node.js has been developed for more than ten years, in which countless resources have been accumulated. We should reuse them as much as possible to improve development efficiency.

Topics: deno