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,須要點過去,沒有本地那麼直觀

二、目前生態還不太好

相關文章
相關標籤/搜索