IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> TypeScript生成ES6的JS -> 正文阅读

[JavaScript知识库]TypeScript生成ES6的JS

TypeScript生成ES6的JS

我在使用TypeScript过程中有一个疑问,编写的是现代化的js可以用上:在TSconfig.json中

{
  "compilerOptions": {
    "target": "ES6",
    "module": "ES6", 
  }
}

TS代码

// main.ts
import {add, sub} from './mod1';

let a = 10;
const b= 20;
let c = add(a, b);
console.log(c)

let d = sub(b, a);
console.log(d)

// mod1.ts
const sub = function(a:number, b:number):number {
  return a - b;
}

const add = function(a:number, b:number):number {
  return a+b;
}
export { sub ,add };

生成出的ES6的JS是

// main.js
import { add, sub } from './mod1';
let a = 10;
const b = 20;
let c = add(a, b);
console.log(c);
let d = sub(b, a);
console.log(d);

// mod1.js
const sub = function (a, b) {
    return a - b;
};
const add = function (a, b) {
    return a + b;
};
export { sub, add };

可以看出两者几乎是一样的。此时我们执行tsc && node ./dist/main.js时会发现无法执行,提示如下错误:

node:internal/errors:484
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/xxxx/dist/mod1' imported from /Users/pengxu/Work/Code/hello/hello/dist/main.js
    at new NodeError (node:internal/errors:393:5)
    at finalizeResolution (node:internal/modules/esm/resolve:305:11)
    at moduleResolve (node:internal/modules/esm/resolve:866:10)
    at defaultResolve (node:internal/modules/esm/resolve:1074:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:838:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:425:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

这是什么原因呢?经过研究发现,typescript的import与js的import是不同的:

ts的import不需要完整的文件名:import {add, sub} from ‘./mod1’;

es6的js的需要完整的文件名:import { add, sub } from ‘./mod1.js’;

经过修改后可以运行了。

但是tsc生成的文件不可能一个个的去修改吧。那怎么办呢?又经过研究发现,node有一个选项是允许不带后缀名import的:

node --experimental-specifier-resolution=node ./dist/main.js

其中–experimental-specifier-resolution=node是node的一个实验性选项,开启后执行时会提示一个警告

(node:51193) ExperimentalWarning: The Node.js specifier resolution flag is experimental. It could change or be removed at any time.

吐槽:也许后面的nodejs版本就会不再显示这个警告了;也许后面的nodejs版本不允许这么干了,鬼知道。我想这就是为什么都node18代了,网上的教程还是在教怎么写require,用es5的方式写代码。nodejs本身对module的加载方式太乱了。兼容性太差,坑太多。

加上了这个选项后再执行,发现报这个错误:

(node:51193) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
import { add, sub } from './mod1';
^^^^^^
SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1048:15)
    at Module._compile (node:internal/modules/cjs/loader:1083:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
    at Module.load (node:internal/modules/cjs/loader:997:32)
    at Module._load (node:internal/modules/cjs/loader:838:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:170:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:527:24)

这个问题的原因是一直以来NODEJS都是用CommonJS的方式(就是require(‘xxxx’)和module.expores={})这种方式导入导出模块。这种方式是同步的,顺序执行的。而es6里的import的区别就大了(根本就是两套逻辑)import是异步的,预加载的。在nodejs进化的历史长河中,花了很多很多年,都没有统一这两种加载方式,历史包袱太重。(后来就有了Deno,这是另一个话题)导致了一代代教程教出来的的程序员前赴后继的写了require。(import可以使用require)。但是就在这个问题还没有搞定的时候,typescript又降维打入进来,我看到很多前端或全栈小哥,在三套标准(commonjs ,es6, ts)之前迷离。写着或机械的,或玄学代码。

扯远了,说回来以上错误的处理方法很简单,在package.json里把type设为module,这是nodejs的配置,如果不加这个时在nodejs遇到.js.cjs文件时会使用CommonJS方式,如果遇到.mjs时用ES6 import加载。(这样就需要在文件扩展名层面上确定是哪种,貌似没有哪个语言是这样的,历史的坑)。还有一种方便的方法就是在package.json中使用type来指定用commonjs还是module方式来处理所有的js文件。

改造后的package.json如下:

// package.json
{
  "main": "./dist/main.js",
  "type": "module",
  "scripts": {
    "dev": "tsc && node --experimental-specifier-resolution=node .",
  }
}

此时就可以正常执行了。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:47:38  更:2022-09-24 20:51:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:25:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码