前言
前几天遇到一个批量处理文件的需求,需要用node来实现,由于第一次接触它,没啥经验,又想写TS,于是就搭建了这么一套环境,期间也踩了挺多坑。
本文就跟大家分享下我的实现过程,欢迎各位感兴趣的开发者阅读本文。
环境搭建
首先我们创建一个空项目,在项目根目录创建package.json
文件。在文件中填写项目的基础信息,如下所示:
{ "name": "ts-node-utils", "version": "1.0.0", "description": "一些用ts写的可执行node脚本", "private": false, "license": "MIT" }
上述代码中,各个字段的含义:
- name 项目名
- version 版本号
- description 项目的描述
- private 项目是否为私有状态
- license 项目所采用的开源协议
按照自己的实际情况填写即可。
注意:你也可以使用yarn或者npm来初始化一个项目,在初始化过程中会提示你填写上述信息,命令为:
yarn init | npm init
。
安装依赖
开源社区中有一个名为ts-node的库,它可以运行时解析ts
,执行node的API
,读完它的文档后,我们知道了在项目中安装它的方法,如下所示:
npm install -D typescript | yarn add typescript -D npm install -D ts-node | yarn add ts-node -D npm install -D tslib @types/node | yarn add tslib @types/node -D
上述命令中,我们安装了typescript,ts-node,tslib,@types/node
这四个包,上述代码中的|
是或者的意思,提供了npm
的安装方法和yarn
的安装方法,根据自己的实际需求执行对应的命令即可。
创建TS配置文件
在项目根目录创建tsconfig.json
文件,具体的配置请移步tsconfig配置,我的配置文件如下所示:
{ "compilerOptions": { "target": "esnext", "module": "esnext", "strict": true, "jsx": "preserve", "importHelpers": true, "moduleResolution": "node", "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, "baseUrl": ".", "outDir": "./output", "types": [ "webpack-env" ], "declaration": true,// 是否生成声明文件 "declarationDir": "dist/type",// 声明文件打包的位置 "lib": [ "esnext", "dom", "dom.iterable", "scripthost" ] }, "exclude": [ "node_modules" ] }
编写测试代码
接下来,我们引入几个node
的api来测试下上面的配置,看看能否正常运行。
如下所示,我在项目根目录创建了handle-themes-file
文件夹,并在文件夹内部创建了lib
文件夹和main.ts
文件。
我们在lib
文件夹下创建HandleThemes.ts
文件,在这里编写一个获取文件夹下所有文件的方法,代码如下所示:
import { readdir } from "fs"; export default class HandleThemes { public getFolderFiles(path: string): void { readdir(path, (errStatus, fileList) => { if (errStatus !== null) { console.log("文件读取失败, 错误原因: ", errStatus); return; } console.log("文件读取成功", fileList); }); } }
最后,我们在main.ts
下导入HandleThemes.ts
,实例化后,调用getFolderFiles
方法,如下所示:
import HandleThemes from "./lib/HandleThemes"; const handles = new HandleThemes(); handles.getFolderFiles("/Users/likai/Desktop/测试文件夹");
运行报错
在ts-node的文档中,我们知道了在终端/命令行进入我们的项目根目录,执行ts-node xxx.ts
就能执行了,此处我们运行的文件是main.ts
文件,那么要执行的命令就为:
ts-node handle-themes-file/main.ts
然而,事情并没我们想象的那么顺利,命令执行后,会看到如下所示的报错:
image-20210814145833539
(node:65039) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension. (Use `node --trace-warnings ...` to show where the warning was created) /Users/likai/Documents/WebProject/ts-node-utils/handle-themes-file/main.ts:1 import HandleThemes from "./lib/HandleThemes"; ^^^^^^ SyntaxError: Cannot use import statement outside a module at wrapSafe (internal/modules/cjs/loader.js:979:16) at Module._compile (internal/modules/cjs/loader.js:1027:27) at Module.m._compile (/Users/likai/Documents/WebProject/ts-node-utils/node_modules/ts-node/src/index.ts:1311:23) at Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Object.require.extensions.<computed> [as .ts] (/Users/likai/Documents/WebProject/ts-node-utils/node_modules/ts-node/src/index.ts:1314:12) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) at main (/Users/likai/Documents/WebProject/ts-node-utils/node_modules/ts-node/src/bin.ts:331:12) at Object.<anonymous> (/Users/likai/Documents/WebProject/ts-node-utils/node_modules/ts-node/src/bin.ts:482:3)
修改项目类型声明
看报错提示,让在package.json
中添加一个type
类型为module
的字段,那么我们就声明下,如下所示:
{ "type": "module" }
当我再次运行时,它又换了新的报错。
image-20210814150542095
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/likai/Documents/WebProject/ts-node-utils/handle-themes-file/main.ts at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:71:15) at Loader.getFormat (internal/modules/esm/loader.js:102:42) at Loader.getModuleJob (internal/modules/esm/loader.js:231:31) at async Loader.import (internal/modules/esm/loader.js:165:17) at async Object.loadESM (internal/process/esm_loader.js:68:5) { code: 'ERR_UNKNOWN_FILE_EXTENSION' }
百度这个报错时,基本上就一篇文章抄来抄去的
image-20210814150819838
这篇文章说是因为找不到导入的模块,需要在导入时添加文件的后缀名,且需要把ts后缀换成js,我跟着操作后,报错依然存在。