Deno 初体验,实战记录一个node项目迁移到Deno须要作什么

本文以csdnsynchexo迁移到deno实现进行一步步探索说明。html

csdnsynchexo是一个爬取 csdn 博客内容生成 hexo 源文件内容的简单工具,正常版本使用 nodejs 实现,。最近 node 之父 ry 大神的 deno 也发布了 1.0,就想实践一下,从 node 版本迁移升级到 deno。本文主要记录一个 nodejs 应用迁移到 deno 须要作哪些工做,还涉及到一些很是基础的 deno 概念。若是你熟悉 nodejs,阅读本文的难度几乎为 0node

迁移后项目github地址git

安装deno

安装文档github

文档中有不少方式,咱们按需选择便可。这里我直接选择mac的脚本安装形式。执行一个脚本而后按照提示设置环境变量便可typescript

curl -fsSL https://deno.land/x/install/install.sh | sh
# 根据提示设置环境变量
# add the directory to your $HOME/.zshrc (or similar)
export DENO_INSTALL="/Users/name/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
复制代码

安装deno vscode 插件

这个插件的做用以下:shell

区别于node中的ts, deno中引入文件必须以.ts结尾(有详细后缀),而在node环境下是不须要的,这个插件能解决这个问题,会提示你须要加后缀npm

deno能够引入远程文件路径,这个插件能够根据路径下载下来的文件,自动推断对应包的类型(依赖了DENO_INSTALLPATH环境变量)json

vscode商店直接搜索安装便可。地址api

我这里遇到了一个问题:安装好这个插件后,vscode仍是会出现找不到Deno的报错(issue很多人也遇到了这个问题,若是无问题,则忽略后面),应该是缺乏对应 Deno 的声明文件。这里直接用npm i typescript-deno-plugindeno的声明文件安装下来(或者手动将声明文件拷贝一份)。bash

# 仍是用了node和npm...
npm install --save-dev typescript-deno-plugin typescript
复制代码

第三方依赖模块的迁移

既然denonode都是执行的 ts/js代码,那么其实只要解决了第三方包和 api 问题,逻辑都同样直接用的,那么本项目的第三方依赖以下,只要解决了这些依赖的问题就能够了

{
    "dependencies": {
        "cheerio": "^1.0.0-rc.2",
        "commander": "^2.19.0",
        "filenamify": "^4.1.0",
        "node-fetch": "^2.1.2",
        "sitdown": "^1.1.6"
    }
}
复制代码

deno实现了w3c api标准,已经了内置了fetch,因此咱们的node-fetch再也不须要了)

模块迁移指南参考

按照官方推荐,Deno项目中建议用一个deps.ts文件来统一管理全部依赖,别的地方直接从deps.ts统一引入,例如本项目的deps.ts以下

export { default as cheerio } from "https://dev.jspm.io/cheerio";
export { default as sitdown } from "https://dev.jspm.io/sitdown";
export { default as Command } from "https://deno.land/x/denomander/mod.ts";
export * as fs from "https://deno.land/std/node/fs.ts";
export * as path from "https://deno.land/std/node/path.ts";
export { default as filenamify } from "https://dev.jspm.io/filenamify";
复制代码

那么问题来了,这些模块如何找呢。模块迁移指南中也有大概的介绍,这里简单描述下

一、首先推荐到pika中去寻找这个模块,若是搜出来能直接用,不会报红,代表能够完美在 deno 中使用,直接用pika中的模块连接在deps.ts中引入便可。pika中都自带了.d.ts类型文件,配合deno vscode插件就能实现类型的推断

例如这里的cheerio就直接在deno中使用

二、若是这个模块在pika中不支持(或者pika抽风..好像不少模块莫名奇妙 404 或者 502),则用https://dev.jspm.io/模块名的地址引入,这些引入通常是没有 ts 声明文件的,可能须要手动引入下对应库的声明文件或者直接添加@ts-ignore忽略掉对应的 ts。(dev.jspm.io中的模块可能用了某些 deno 不支持的 api?..须要判断了)

// cheerio是经过dev.jspm.io引入的,无类型文件
// @ts-ignore
const $ = cheerio.load(html, {
    decodeEntities: true,
});
复制代码

三、若是 一、2 找不到,则谷歌搜索deno 对应模块名看有没有合适的替代方案了。例如本项目,就是用denomander代替 node 的commander

因为 deno 自带了typescript支持,咱们无需ts-nodetsc等命令便可直接执行ts文件了

node 原生 api 的迁移

对于node的原生模块,deno提供了对应的兼容包(它们存在于 deno 标准库的node包下),例如fspath等。可是兼容是不彻底的,例如缺失某些 api(fs里面不提供流式操做)、一些node原生包也没支持。因此能作的就是尽可能使用Denoapi 实现,实在不行就用node包下的看看。我这个项目迁移基本知足了需求...

csdnsynchexo有很多调用fs的文件操做,主要是建立文件、写文件。

Deno把全部的 api 都放在了Deno这个命名空间下了...Deno使用await实现异步,全局顶层能够直接使用await

简单举例..

// node中判断文件是否存在
import fs from "fs";
export const fsExistsSync = (way: string): boolean => {
    try {
        fs.accessSync(way, fs.constants.W_OK);
    } catch (e) {
        return false;
    }
    return true;
};
// 对应的deno api实现
export const fsExistsSync = (way: string): boolean => {
    try {
        Deno.statSync(way);
    } catch (e) {
        return false;
    }
    return true;
};
复制代码
// 生成文件,写文件操做
const writeStream = fs.createWriteStream(
    path.join(output, `./${filenamify(title)}.md`),
    "utf8"
);
writeStream.write(`title: ${title}\n`);
writeStream.close();

// deno
const file = Deno.createSync(path.join(output, `./${filenamify(title)}.md`));
const encoder = new TextEncoder();
Deno.writeSync(file.rid, encoder.encode(`title: ${title}\n`));
Deno.close(file.rid);
复制代码

path.join好像没有对应实现,咱们直接使用标准库std下的nodepath便可

其实没啥难度...到 deno 文档找一遍有没有相似的 api 便可

执行程序

对于 node,deno 有严格的权限管理,例如若是咱们须要网络权限,必须添加--allow-net才能实现网络请求。

本项目会用到文件读写、网络请求权限,因此咱们执行的时候须要deno run --allow-read --allow-net --allow-write ./src/index.ts hsync --config=./config.json执行

可能你还怀念npm..每次执行一堆参数很爽,咱们能够利用Makefile来实现脚本编写

# makefile
run:
	deno run --allow-read  --allow-net --allow-write ./src/index.ts hsync --config=./config.json

cache:
	deno cache ./src/index.ts
复制代码

直接根目录下新建makefile文件,这时候咱们直接执行make run便可执行咱们的程序了..可见,成功搞定

img

打包

deno bundle自带打包和tree shaking功能,能够将咱们的代码打包成单文件

deno install能够将咱们的代码生成可执行文件进行直接使用

能够创建对应的make脚本

bundle:
	deno bundle ./src/index.ts ./hsync.js
install:
	deno install --allow-read  --allow-net --allow-write -n hsync ./src/index.ts
复制代码

cli

deno cli 对比node就强大不少了。具有了测试、打包、运行、格式化等于一体

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
复制代码

通过一系列操做,一个简单的 node 项目就迁移成 deno 项目了,今天经历了从装 deno 到使用 deno。对于 deno 的直观感觉以下

优势

一、自带 ts 支持,不要再装ts-nodebabel等东西

二、deno命令具有了测试、打包、运行、格式化等于一体,不需按照额外一堆东西

缺点

一、第三方库报错信息很差看,由于是一个远程 url,须要点过去,没有本地那么直观

二、目前生态还不太好

相关文章
相关标签/搜索