前端模块化标准:ES6、commonJS、amd、umd、system、esnext
模块化
相关配置
| 配置名称 | 含义 |
|---|---|
| module | 设置编译结果中使用的模块化标准 |
| moduleResolution | 设置解析模块的模式 |
| noImplicitUserStrict | 编译结果中不包含"use strict" |
| removeComments | 编译结果移除注释 |
| noEmitOnError | 错误时不生成编译结果 |
| esModuleInterop | 启用es模块交互 |
本文主要解决两个问题
TS中如何书写模块化语句
编译结果
TS中如何让书写模块化语句
TS中,导入和导出模块,统一使用ES6的模块化标准。
简单例子
export function sum(a: number, b: number) {
return a + b;
}
export const a: number = 1;
export default function getTime() {
console.log(Date.now());
}
import getTime, { sum, a } from './myModule';
console.log(sum(1, 2));
console.log(a);
console.log(getTime());
和我们正常书写ES6模块化代码一样,有几个需要注意的点
- 模块化文件不要使用默认导出,默认导出不能享受到TS的模块导入智能提示。
- 引入模块化文件时,不要加后缀名
.ts,会报错,编译结果中不存在ts文件。
编译结果中的模块化
可以在配置文件中进行配置模块化标准
TS中的模块化在编译结果中:
-
如果编译结果的模块化标准是ES6:没有区别
配置文件中模块化配置为:
"module": "ES6",编译结果和ts代码相同//模块化文件 export function sum(a, b) { return a + b; } export const a = 1; export default function getTime() { console.log(Date.now()); } //引用模块化文件 import getTime, { sum, a } from './myModule'; console.log(sum(1, 2)); console.log(a); console.log(getTime()); -
如果编译结果中的模块化标准是commomjs:导出的声明会变成exports的属性,默认的导出会变成exports的default属性。
配置文件中模块化配置为:
"module": "CommonJS",编译结果//模块化文件 "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.a = exports.sum = void 0; function sum(a, b) { return a + b; } exports.sum = sum; exports.a = 1; function getTime() { console.log(Date.now()); } exports.default = getTime; //引用模块化文件 "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const myModule_1 = require("./myModule"); console.log((0, myModule_1.sum)(1, 2)); console.log(myModule_1.a); console.log((0, myModule_1.default)());可以使用
"noImplicitUseStrict": false去掉编译结果中的"use strict",ts本身就很严格了。很奇怪的是,模块化文件编译结果中的
void 0和console.log((0, myModule_1.sum)(1, 2))void是一元表达式,void 运算符对给定的表达式进行求值,然后返回undefinedvoid 0 === void(0) === undefined为什么这样写,简单来说就是
undefined是全局对象window的属性,低版本浏览器中可以被修改逗号运算符是二元运算符,它能够先执行运算符左侧的操作数,然后再执行右侧的操作数,最后返回右侧操作数的值,
console.log((0, myModule_1.sum)(1, 2))实际上就是console.log(myModule_1.sum)(1, 2))
解决默认导入的错误
在ts中想要使用fs模块,正常写法应该是这样
import fs from 'fs'; //报错,fs没有默认导出
fs.readFileSync('./');
fs模块是module.exports = {}导出的,前面的例子说明ts中使用ES6默认导出,编辑结果中是exports.default,所以导致报错
解决办法
-
使用
import { readFileSync } from 'fs'; -
使用
import * as fs from 'fs'; -
配置参数
"esModuleInterop": true引用模块的编译结果为
var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); fs_1.default.readFileSync('./');
如何在typescript中书写CommonJS(不建议使用)
导出:export = xxx,才会具有类型检查,会有智能提示
导入:import xxx = require("xxx")或import xxx from "xxx"
不建议使用commonJS模块化代码,除非有不可描述的原因。
模块解析
模块解析:应该从什么位置寻找模块
TS中,有两种模块解析策略
- classic:经典(老版本)
- node:node解析策略(唯一的变化,是将js替换为ts)
-
相对路径
require("./xxx")先找当前目录有没有该文件,如果没有,再找package.json文件中是否配置
"main": "xxx",如果有则在当前目录下找该文件,如果没有,则找当前目录下有有没有index.ts文件 -
非相对路径
require("xxx")在当前目录找
node_modules目录,没有则继续在上级找,直到找到
-