Chuyển đến nội dung chính

第 3 課:模組系統與套件管理

CommonJS vs ES Modules,模組解析演算法。 Package.json欄位匯出,條件匯出。 npm、pnpm 工作區。 Node.js 內建測試運行器、權限模型。

💻 程式設計 — 第 3 課 第 3 課:模組系統與套件管理

Node.js 核心:從基礎到高級

第 1 部分:Node.js 內部結構

亞洲開發網

1. CommonJS 與 ES 模組

特點CommonJS (CJS)ES 模組 (ESM)
文法require() / module.exports進口/出口
載入中同步非同步
頂級等待否是的
__目錄名是的import.meta.dirname(節點 21+)
JSON導入需要('./data.json')使用 { type: 'json' } 從 './data.json' 匯入數據
搖樹否是(靜態分析)
// ESM — recommended
import { readFile } from 'node:fs/promises'
import path from 'node:path'

// Dynamic import
const module = await import('./utils.js')

// import.meta
console.log(import.meta.url)      // file:///path/to/file.js
console.log(import.meta.dirname)  // /path/to (Node.js 21+)
console.log(import.meta.filename) // /path/to/file.js

2.Package.json導出Field

{
  "name": "my-lib",
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    },
    "./utils": {
      "import": "./dist/utils.mjs",
      "require": "./dist/utils.cjs"
    }
  },
  "files": ["dist"],
  "engines": {
    "node": ">=22"
  }
}

3.pnpm 工作區

# pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'
# Thêm dependency cho workspace
pnpm add lodash --filter @myorg/server
pnpm add @myorg/shared --filter @myorg/server --workspace

# Chạy script cho tất cả packages
pnpm -r run build
pnpm -r --parallel run dev

4. 權限模型(Node.js 22+)

# Chạy với permission giới hạn
node --experimental-permission \
  --allow-fs-read=/app/data \
  --allow-fs-write=/app/logs \
  --allow-child-process \
  app.js

# Kiểm tra permission trong code
if (process.permission.has('fs.read', '/etc/passwd')) {
  console.log('Has read permission')
}

5. 內建測試運行器

import { describe, it, before, after, mock } from 'node:test'
import assert from 'node:assert/strict'

describe('Calculator', () => {
  it('adds two numbers', () => {
    assert.strictEqual(1 + 2, 3)
  })

  it('handles async', async () => {
    const result = await Promise.resolve(42)
    assert.strictEqual(result, 42)
  })

  it('supports mocking', () => {
    const fn = mock.fn((a: number, b: number) => a + b)
    fn(1, 2)
    assert.strictEqual(fn.mock.calls.length, 1)
    assert.deepStrictEqual(fn.mock.calls[0].arguments, [1, 2])
  })
})
node --test --test-reporter spec

下一篇: TypeScript 和現代 JavaScript — tsx、ts-node、型別剝離。