ts-node/esno/tsx 运行 ES module TS 运行时差异
Node.js + TypeScript 使用 ts-node/esno/tsx 对 ES Module 的支持使用时有何异同
- 直接运行
.ts
文件 - 模块导入时,文件后缀的是否可以忽略
- ts-node 的多种运行方式以及限制
- 运行时中模块与ts/esm
ts 文件
传统方式:
- tsc 类型检查,编译 ts 文件
- 运行 js
- 程序运行,或者服务启动
开发一个库
一般开发库选用 TS
,已经很常见了,选择 rollup
编译出 ES Module
/Commonjs
等同类型的模块,提供给第三方使用。
但是,直接运行 ts
/tsx
文件?
模块基础
ES Module 模块中的关键字
import/import() 静态和动态导入
from
export
default
模块配合(路径相关的模块)
- 浏览器:
URL
- 浏览器:
import.meta
- nodejs:
url 模块
- nodejs:
path 模块
注意: import.meta
需要在支持了 ES Module
才能正常使用:
- 浏览器使用
<script type="module" src=""></script>
支持 Node.js
使用{ type: "module" }
整个 Node 应用程序处在 ES Module 环境下支持- 其次
Node.js
是.mjs
文件表示 ES Module, 可以直接使用node ./xx.mjs
运行
涉及文件类型
.js
/.cjs
/.mjs
.ts
/.cts
/.mts
ES Module 完整的路径
所谓完整路径,就是支持网络下载(需要完整的路径才知道在哪里下),这一点与 Node.js
的包模块设计不同。
// commonjs
const foo = require('./foo')
// es module
import foo from './foo.js' // .js 需要完整的路径,并且补充完整,可以是相对路径
- 需要完整的路径(可以是相对路径)
ES Module import.meta
对象
暴露特定上下文的元数据属性的对象
完整的路径(注意文件协议
)
Node.js
import.meta
保存文件协议
console.log(import.meta) // {url: 'file:///xxx/xx/x'} // nodejs 环境
- 浏览器环境
http
协议(启动http
服务)
- 浏览器中配合
URL
使用
const url = new URL(import.meta.url)
配合 URL
构造器能直接解析为一个 URL
对象,方便直接使用 URL
对象属性方法
- 在
Node.js
中配合url
模块使用
在 Node.js
中,常用是实现 ES Module
下的 __dirname
和 __filename
两个变量
import { dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
Node.js
环境带有 ES Module
运行 TS
文件
- ts-node
- tsx/esno
{
"scripts": {
"dev::tsnode": "ts-node src/index.ts",
"dev::tsnode::esm": "ts-node-esm src/index.ts",
"dev::tsx": "tsx src/index.ts",
"dev::esno": "esno src/index.ts"
},
}
ts-node 区分 ES Module 和 非 ES Module
非 ES Module
ts-node
默认是运行 commonjs
模块,如果在默认情况下使用 import.meta
等抛出错误要在 ES Module
条件下使用
ts-node
运行js
文件错误提示:
ts-node
运行ts
文件提示:
ES Module
{
"scripts": {
"dev": "ts-node src/index.ts"
},
}
错误如下:
解决:打开 node_modules
找到 package.json
文件,查看 bin
属性, 支持多种不同的环境的运行时:
使用 ts-node-esm
来运行 ts
文件
ts-node
以指定 --loader
等等参数的方式运行
{
"scripts": {
"dev": "node --loader ts-node/esm --inspect ./index.ts src/index.ts"
},
}
ts-node
指定 NODE_OPTIONS
和 loader
的方式运行
{
"scripts": {
"dev": "NODE_OPTIONS=\"--loader ts-node/esm\" node src/index.ts"
},
}
ts-node
+ ES Module
中导入模块需要 .js
后缀
在 ts-node
+ ES Module
的运行方式中, 从其他文件导入模块 .js
是不可忽略的,同时也不能改为 .ts
import aa from './abd.js'
否则会出现如下错误提示:
ts-node
使用 swc
形式运行
- 依赖包
npm i -D @swc/core @swc/helpers regenerator-runtime
{
"scripts": {
"dev": "ts-node --swc src/index.ts"
},
}
不挑剔的 esno/tsx
esno
和 tsx
本质基于 esbuild
, 原生支持 ES Module
, 所以无需指定环境, 甚至 package.json
中无需指定 type: "module"
:
{
"scripts": {
"dev::tsx": "tsx src/index.ts",
"dev::esno": "esno src/index.ts",
},
}
小结
得益于 go
/rust
的发展,前端基础层面也搭上了顺风车,使得前端在运行时更加快速。
- 如果编写库类推荐使用
rollup
+
typescript
编译出不同js
版本, 提供给自己或第三方运行。 ts-node
之处不同的环境,ES Module
环境需要严格配置package.json
和tsconfig.json
,路径必须完整,写后缀必须是.js
。ts-node
支持使用功能swc
。tsx
/esno
由于esbuild
的加持,使得运行ts
/tsx
运行更加灵活快速,方便快捷。- 如果仅仅是运行时,并且对性能没有过高要求或者仅仅使用在开发环境下工作,使用
esno
/tsx
是很好的选择。
推荐文章
参考
- Node.js ES Module nodejs.org/api/esm.htm…
- ts-node npm www.npmjs.com/package/ts-…
- tsx www.npmjs.com/package/tsx
- esno www.npmjs.com/package/esn…
转载自:https://juejin.cn/post/7163685872750034981