好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用 ESModule 和 TypeScript 构建 Node.js 环境

介绍

由于我经常使用 React,所以我在前端接触过 Node.js,但我从未接触过后端。
正常搭建环境的时候,不能使用import语句,变成了require语句,很不方便。
我认为有各种各样的错误,所以如果你能指出它们,我将不胜感激。

执行环境

macOS 蒙特雷 ver12.5.1
MacBook Air(M1,2020)

安装包

首先确保您安装了 Node.js。
如果你想用 Docker 搭建环境,进入容器并执行命令。

终端

 node -v
v16.10.0
 

初始化项目。
你会被问到很多问题,但目前一切都很好。

终端

 npm init
 

确保它看起来像这样:

包.json

  {  
    "name"  :     "test"  ,  
    "version"  :     "1.0.0"  ,  
    "description"  :     ""  ,  
    "main"  :     "index.js"  ,  
    "scripts"  :     {  
      "test"  :     "echo   \"  Error: no test specified  \"   && exit 1"  
    },  
    "author"  :     ""  ,  
    "license"  :     "ISC"  
  }  
  

安装软件包。
这次我会用 yarn ,不过 npm 也可以。
首先,安装 typescript 。
您只需要一个开发环境,所以将其添加到 devDependencies 。

终端

 yarn add -D typescript
or
npm install --save-dev typescript
 

接下来,安装 Node.js 类型定义。
有一个开发环境也很好。
由于 Node.js 主体中没有类型定义,因此除非包含它,否则不会发生类型推断。

终端

 yarn add -D @types/node
or
npm install --save-dev @types/node
 

然后安装 ts-node 。
默认情况下,Node.js 只能运行 JavaScript,不能运行 TypeScript。
通过使用 ts-node ,您可以直接运行 TypeScript。
查看官方存储库,它是 node 命令和 tsc 命令的包装器吗?

终端

 yarn add -D ts-node
or
npm install --save-dev ts-node
 

如果您已经完成了这一步, package.json 应该如下所示:

包.json

  {  
    "name"  :     "test"  ,  
    "version"  :     "1.0.0"  ,  
    "description"  :     ""  ,  
    "main"  :     "index.js"  ,  
    "scripts"  :     {  
      "test"  :     "echo   \"  Error: no test specified  \"   && exit 1"  
    },  
    "devDependencies"  :     {  
      "@types/node"  :     "^18.7.14"  ,  
      "ts-node"  :     "^10.9.1"  ,  
      "typescript"  :     "^4.8.2"  
    },  
    "author"  :     ""  ,  
    "license"  :     "ISC"  
  }  
  

试着移动

我将编写一个脚本来设置一个简单的服务器。
访问 http://localhost:8080 时返回 hello world 的服务器。
创建 index.ts 并编写以下代码。

索引.ts

  import   http   from   "  http  "  ; 

 const   server   =   http  .  createServer  ((  req  ,   res  )   =>   { 
   res  .  writeHead  (  200  ); 
   res  .  end  (  "  hello world  "  ); 
 }); 

 server  .  listen  (  8080  ); 

 

我想让你在这里检查的是类型推断是否有效,因为你已经安装了 @types/node 。
下图是您将鼠标悬停在 http.createServer 上时的样子。

让我们运行它。
ts-node 安装在本地,不在全局路径中,所以我们使用运行本地包的 npx 。
yarn 好像也有类似的功能,但是好像用的不多。我一直无法找到关于这个地区的太多信息。

终端

 npx ts-node index.ts
 

让我们在浏览器中打开它。显示出来了。

让我们做一个从另一个 ts 文件导入并执行它的测试。
首先,创建 sum.ts 并编写以下代码。

sum.ts

  const   sum   =   (  a  :   number  ,   b  :   number  )   =>   { 
   return   a   +   b  ; 
 }; 

 console  .  log  (  sum  (  1  ,   2  )); 
 

让我们在导入之前运行它。
我认为它正在工作。

终端

 npx ts-node sum.ts
3
 

让我们导入它并使用它。

索引.ts

  import   http   from   "  http  "  ; 
 import   {   sum   }   from   "  ./sum  "  ; 

 const   server   =   http  .  createServer  ((  req  ,   res  )   =>   { 
   const   three   =   sum  (  1  ,   2  ); 
   res  .  writeHead  (  200  ); 
   res  .  end  (  three  .  toString  ()); 
 }); 

 server  .  listen  (  8080  ); 
 

终端

 npx ts-node index.ts
 

如果您在浏览器中查看它,您应该能够看到它。

ESModule 整个项目

正如您目前所看到的,您可以使用 import 语句,所以我认为没有问题。
我从这里猜测,但似乎 ts-node 在执行之前将 ESModule 格式转换为 CommonJS 格式并执行它。
用下面文章的话来说,我们目前使用的是伪 ESModule。

当前状态的问题是无法读取以 ESModule 为前提制作的包。请参阅下面的参考文章。

因此,我想对整个项目进行 ESModule。
我们将参考 TypeScript Docs。

首先创建 tsconfig.json 。

终端

 npx tsc -init
 

根据公式进行设置。

tsconfig.json

  {  
      "compilerOptions"  :     {  
          "module"  :     "nodenext"  ,  
      }  
  }  
  

包.json

  {  
    "name"  :     "test"  ,  
    "version"  :     "1.0.0"  ,  
    "description"  :     ""  ,  
    "main"  :     "index.js"  ,  
    "scripts"  :     {  
      "test"  :     "echo   \"  Error: no test specified  \"   && exit 1"  
    },  
    "author"  :     ""  ,  
    "license"  :     "ISC"  ,  
    "devDependencies"  :     {  
      "@types/node"  :     "^18.7.18"  ,  
      "ts-node"  :     "^10.9.1"  ,  
      "typescript"  :     "^4.8.3"  
    },  
    "type"  :     "module"  
  }  
  

对了,在输入 package.json 的 type 的时候,VSCode里出来了下面的补充。
这是笨拙和意译,但它是这样的。
换句话说,我觉得它直到现在都是作为 CommonJS 执行的。

将 type 值设置为 module 将导致包将所有 js 文件视为 ESModules。
如果省略type值或者commonjs,则所有的js文件都被认为是CommonJS。

此外,TypeScript Docs 指出:

相对导入路径必须有一个完整的扩展名(例如 import "./foo.js" 应该写而不是 import "./foo")。

当我去查看 index.ts 时,我收到这样的错误。
需要注意的是,要导入的文件的扩展名必须指定为js。

js修复了错误。

我想到目前为止我组织它时可能会是这样。

Node.js 通过将 package.json 设置为 type: module 来原生支持 ESM。

但是Node.js不能直接运行typescript,所以我在tsconfig.json中设置编译成ESModule。

让我们检查一下操作。

终端

 npx ts-node index.ts
 

我有一个错误。 ts-node 似乎无法读取 ESModule 格式。

终端

 TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for 〜以下省略〜
 

参考ts-node公式,改成这样。

终端

 node --loader ts-node/esm ./index.ts
 

我能够在浏览器中确认操作。

但是,正如下面的官方描述所述,它是一个实验性功能,似乎在产品版本中已被弃用。
也许你应该运行 tsc && node index.js 或类似的东西。

Node 的 ESM 加载器挂钩是实验性的,可能会发生变化。 ts-node 的 ESM 支持尽可能稳定,但依赖于可能会在较新版本的节点中中断的 API。因此,不建议用于生产。

综上所述

我只想要前端熟悉的导入和类型推断,但是花了很多时间和精力。
Node.js 的创建者正在开发一个名为 Deno 的 JS 运行时,它似乎在本地支持 TypeScript 和 ESModule,利用了从 Node.js 中吸取的教训。
不过,考虑到各种库的支持,Node.js 的霸主地位似乎还要持续一段时间。

参考

纱线添加文档 ts 节点存储库 “什么是 npx?” “TypeScript 4.7 和本机 Node.js ESM” “TypeScript 4.5 之后 ESM 支持会发生什么变化? 』 “我沉迷于 TypeScript 的 ESM” “Node.js 中的 ECMAScript 模块” Node.js esm 文档


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308626538.html

查看更多关于使用 ESModule 和 TypeScript 构建 Node.js 环境的详细内容...

  阅读:66次