← Node / Backend Course

NODE / BACKEND CORE · 102

Modules / Files / Path:Source dependency 跟 Filesystem path 是兩回事

Backend 專案會同時碰到 import path、working directory、filesystem path、config file。它們看起來都是「路徑」,但 failure layer 完全不同。

Learning outcomes

1. Module:source code dependency

// grade.js
export function isPassed(
  score
) {
  return score >= 60;
}

// server.js
import {
  isPassed
} from "./grade.js";

這裡解決的是 source module relationship,不是在 runtime 幫你打開某個資料檔。

2. Filesystem path

import {
  readFile
} from "node:fs/promises";

const text =
  await readFile(
    "./data/courses.json",
    "utf8"
  );

./data/courses.json 常依 process working directory 解析。

3. cwd ≠ module directory

console.log(
  process.cwd()
);

console.log(
  import.meta.url
);

你可以從不同 directory 啟動同一份程式,因此相對 filesystem path 可能突然找不到。

4. 使用 URL / path 工具明確建構 module-relative path

const fileUrl =
  new URL(
    "./data/courses.json",
    import.meta.url
  );

const raw =
  await readFile(
    fileUrl,
    "utf8"
  );

5. Async vs sync I/O

// async
await readFile(
  fileUrl,
  "utf8"
);
// sync
readFileSync(
  fileUrl,
  "utf8"
);

啟動階段偶爾使用 sync API 可能可以接受,但 request path 裡長時間 blocking I/O 會阻塞同一個 Node process 處理其他工作。

6. External file data 仍要 parse / validate

const raw =
  await readFile(
    fileUrl,
    "utf8"
  );

const parsed =
  JSON.parse(raw);

if (!Array.isArray(parsed)) {
  throw new Error(
    "Invalid course data"
  );
}

檔案存在不等於內容合法。

Project checkpoint:Course API v2

// course-store.js
export async function
loadCourses() {
  const fileUrl =
    new URL(
      "./data/courses.json",
      import.meta.url
    );

  const raw =
    await readFile(
      fileUrl,
      "utf8"
    );

  const value =
    JSON.parse(raw);

  if (!Array.isArray(value)) {
    throw new Error(
      "courses.json must be array"
    );
  }

  return value;
}

資料來源先用 file 模擬,後面 106 再換成 database repository。

Debug evidence

Knowledge check

  1. import path 與 filesystem path 差在哪?
  2. 為什麼 cwd 改變可能讓 ./data.json 壞掉?
  3. 把 Course API 資料讀取改成 module-relative URL。
  4. 說明 sync I/O 在 server request path 的風險。