NodeJs-Modules CommonJS modules、ECMAScript modules、node:module、Packages、TypeScript

 后端   小卒子   2024-09-04 21:36   245
  nodejs

Node.js 的模块系统为开发者提供了强大的工具,用于组织代码、管理依赖,并支持不同的模块标准。这包括 CommonJS 模块ECMAScript 模块(ESM)node:module 模块PackagesTypeScript 集成。本文将详细介绍这些模块系统的属性、方法、使用方法及相关内容。

1. CommonJS 模块

1.1 模块导入与导出

CommonJS 是 Node.js 默认的模块系统。每个文件都是一个模块,可以导出函数、对象或原始值。模块通过 module.exports 导出,并通过 require() 导入。

导出

// myModule.js
const myFunction = () => {
  console.log('Hello from myFunction');
};

module.exports = myFunction;

导入

// app.js
const myFunction = require('./myModule');
myFunction(); // 输出: "Hello from myFunction"

1.2 require 函数

require() 是 CommonJS 中用于加载模块的函数。它会同步读取并执行指定的模块文件,并返回 module.exports 的内容。

使用

const fs = require('fs'); // 导入核心模块
const myModule = require('./myModule'); // 导入自定义模块

缓存机制

模块只会在首次加载时执行一次,之后的加载会直接从缓存中返回结果。这可以避免重复执行相同模块。

// 第一次加载
const module1 = require('./myModule');

// 再次加载,直接从缓存中返回
const module2 = require('./myModule');

console.log(module1 === module2); // 输出: true

1.3 module 对象

每个模块都拥有一个 module 对象,代表当前模块。

  • module.exports: 模块的导出对象,其他模块通过 require 导入的内容即为 module.exports 的值。

示例

// myModule.js
console.log(module); // 输出当前模块的信息

1.4 exports 对象

exportsmodule.exports 的快捷方式,两者指向同一个对象。可以使用 exports 导出多个属性。

示例

// myModule.js
exports.hello = () => {
  console.log('Hello');
};

exports.goodbye = () => {
  console.log('Goodbye');
};

2. ECMAScript 模块(ESM)

Node.js 也支持 ECMAScript 模块(ESM),这是一种现代的模块系统,最初在浏览器中引入,并在 ECMAScript 规范中标准化。ESM 的特性包括静态解析、异步加载等。

2.1 import 语句

import 语句用于从其他模块中导入绑定。

导入默认导出

import myFunction from './myModule.js';
myFunction();

导入命名导出

import { myFunction, myVariable } from './myModule.js';

动态导入

ESM 允许动态导入模块,返回一个 Promise,可用于按需加载模块。

const module = await import('./myModule.js');
module.myFunction();

2.2 export 语句

export 语句用于从模块中导出绑定,可以是函数、变量、类等。

导出默认值

export default function() {
  console.log('Hello from default export');
}

导出多个值

export const myVariable = 42;

export function myFunction() {
  console.log('Hello from myFunction');
}

2.3 package.json 配置

为了使用 ESM,package.json 文件中需要设置 "type": "module"。这会将 .js 文件视为 ESM 模块。

{
  "type": "module"
}

3. node:module 模块

node:module 模块提供了与 Node.js 模块系统交互的功能,例如动态加载模块、创建自定义的 require 函数等。

3.1 require()import()

require() 用于 CommonJS 模块,而 import() 用于 ESM。两者之间不能混用,但 import() 可以用于动态导入 CommonJS 模块。

3.2 createRequire()

createRequire() 创建一个新的 require 函数,用于在 ESM 中导入 CommonJS 模块。

示例

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

const fs = require('fs');

3.3 createRequireFromPath()

createRequireFromPath() 已被废弃。推荐使用 createRequire() 代替。

4. Packages

Node.js 的包管理系统允许使用 npm 发布、安装和管理包。package.json 是包的配置文件,包含了包的元数据和依赖信息。

4.1 package.json 中的模块类型

package.json 中的 "type" 字段决定了文件的模块类型:

  • "type": "commonjs": 将 .js 文件视为 CommonJS 模块。
  • "type": "module": 将 .js 文件视为 ESM 模块。

4.2 包的解析和加载

Node.js 根据 require()import 语句解析和加载模块。加载顺序如下:

  1. 核心模块(如 fshttp 等)
  2. 本地模块(绝对路径或相对路径)
  3. node_modules 目录中的包

4.3 exports 字段

exports 字段用于定义包的入口点,支持定义不同的导出路径和模块类型。

示例

{
  "exports": {
    ".": "./main.js",
    "./feature": "./feature.js"
  }
}

5. TypeScript 和 Node.js

TypeScript 提供了静态类型检查和现代 JavaScript 特性,并与 Node.js 无缝集成。

5.1 TypeScript 配置

通过 tsconfig.json 文件配置 TypeScript 编译选项。

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "outDir": "./dist"
  }
}

5.2 TypeScript 中的模块

TypeScript 支持 CommonJS 和 ESM 模块系统,可以根据需要选择配置。

示例

// 使用 CommonJS 模块
import fs = require('fs');

// 使用 ESM 模块
import { readFile } from 'fs/promises';

5.3 TypeScript 和 ESM

要在 TypeScript 中使用 ESM,必须在 tsconfig.json 中设置 moduleESNextES6

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


  }
}

6. 示例代码

CommonJS 示例

// myModule.js
exports.hello = () => {
  console.log('Hello');
};

// app.js
const myModule = require('./myModule');
myModule.hello();

ESM 示例

// myModule.js
export function hello() {
  console.log('Hello');
}

// app.js
import { hello } from './myModule.js';
hello();

TypeScript 示例

// myModule.ts
export const greet = (name: string): string => {
  return `Hello, ${name}`;
};

// app.ts
import { greet } from './myModule';

console.log(greet('World'));

7. 总结

Node.js 提供了多种模块系统,支持 CommonJS、ECMAScript 模块、TypeScript 等。开发者可以根据项目需求选择适合的模块系统,并通过配置 package.json 文件和 TypeScript 配置文件,优化项目的模块管理和构建流程。随着 ESM 的普及,未来的 Node.js 项目将更趋向于使用 ESM 进行模块管理。