本文以
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_INSTALL
和PATH
環境變量)json
vscode商店直接搜索安裝便可。地址api
我這裏遇到了一個問題:安裝好這個插件後,vscode
仍是會出現找不到Deno
的報錯(issue很多人也遇到了這個問題,若是無問題,則忽略後面),應該是缺乏對應 Deno 的聲明文件。這裏直接用npm i typescript-deno-plugin
把deno
的聲明文件安裝下來(或者手動將聲明文件拷貝一份)。bash
# 仍是用了node和npm...
npm install --save-dev typescript-deno-plugin typescript
複製代碼
既然deno
和node
都是執行的 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-node
、tsc
等命令便可直接執行ts
文件了
對於node
的原生模塊,deno
提供了對應的兼容包(它們存在於 deno 標準庫的node
包下),例如fs
、path
等。可是兼容是不徹底的,例如缺失某些 api(fs
裏面不提供流式操做)、一些node
原生包也沒支持。因此能作的就是儘可能使用Deno
api 實現,實在不行就用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
下的node
的path
便可
其實沒啥難度...到 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
便可執行咱們的程序了..可見,成功搞定
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
複製代碼
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-node
、babel
等東西
二、deno
命令具有了測試、打包、運行、格式化等於一體,不需按照額外一堆東西
缺點
一、第三方庫報錯信息很差看,由於是一個遠程 url,須要點過去,沒有本地那麼直觀
二、目前生態還不太好