Node.js基礎 - Node.jsの学習2

バージョン管理

nvm

# インストールできるバージョンの確認
nvm ls-remote

# 指定バージョンのインストール
nvm i v15.11.0
nvm i v20

# 使用バージョンの指定
nvm use v20

# 現在設定しているバージョン
nvm current

コードの実行

node [jsファイルのパス]

ディレクトリとファイルの操作

// ディレクトリとファイルを操作するモジュール
const fs = require("fs")

console.log(__dirname) // 実行したJSファイルのディレクトリ
console.log(__filename) // 実行したJSファイルの格納場所

// ファイルへの書き込み
// fs.writeFileSync([出力先], [出力内容])
fs.writeFileSync(`${__dirname}/test.txt`, "hello node.js")

パスの取り扱い

// パスの取り扱いを行ってくれるモジュール
const path = require("path")

// resolveを使うとWindowsの\(バックスラッシュ)にも応じて出力してくれる
const distPath = path.resolve(__dirname, "..", "/dist/test.txt")
console.log(distPath)

ES ModulesとCommonJSについて

モジュールとは

ソースコードを機能ごとに分割した一つの単位

→ 代表的なものにES ModulesCommonJSが存在する。

各環境ごとのモジュール管理システム

最初、モジュール管理システムはなかったのでNode.jsではCommonJSが定義された。

ES Modulesが定義されたので、近年はこちらに移行している。

基本的にはES Modulesの記述を推奨。

CommonJSの特徴

  • ブラウザでは使用できない
  • require / module.exports / exports を使用
  • ES Modules時と一部使える機能が異なる

ES Modulesの特徴

  • ECMAScriptの標準
  • ブラウザで使用可能
  • import / export を使用
  • Node.jsでは明示的な指定が必要

CommonJSのモジュールの取り扱い

calc.js

function plus(a, b) {
  return a + b
}
function minus(a, b) {
  return a - b
}

// 一つの関数をエクスポートしたい場合
// module.exports = plus

// 複数の関数をエクポートしたい場合
module.exports = {
  plus: plus,
  minus: minus,
}

example.js

// requireの場合は、実行ファイルからの相対パス
// ".js"は省略できる

// 一つの関数をエクスポートしたい場合
// const plus = require("./calc")

// const result = plus(1, 2)
// console.log(result) // -> 3

const calc = require("./calc")
console.log(calc)
// -> { plus: [Function: plus], minus: [Function: minus] }

// 分割代入で特定のプロパティのみ取得することも可能
const { plus } = require("./calc")
const result = calc.plus(1, 2)
console.log(result) // -> 3

ES Modulesのモジュールの取り扱い

JSONファイルとオブジェクトの書き方の違う点

  • プロパティ名も”(ダブルクォーテーション)で囲む必要がある
  • 一番最後のフィールドに,(カンマ)があると、エラーになる

モジュールの拡張子

  • CommonJSの場合 → *.cjs
  • ES modulesの場合 → *.mjs

package.json

{
    "type": "module"
}

calc.mjs

export function plus(a, b) {
  return a + b
}

// export default -> 一つのファイルに一つ定義することができる
export default function minus(a, b) {
  return a - b
}

exmple.mjs

// ES modulesの場合は、拡張子まで記述する
// default exportの場合は波括弧なしてimportできる
import minus, { plus } from "./calc.js"

const result = plus(1, 2)
console.log(result) // -> 3

const result2 = minus(1, 2)
console.log(result) // -> -1

exmple2.mjs

// asを設定した場合、オブジェクトでimportされる
import minus, * as calc from "./calc.js"

console.log(calc)
// -> [Module] { default: [Function: minus], plus: [Function: plus] }

CommonJSとES Modulesが混在する場合

  • OK: ES Modules から CommonJS を読み込む
  • NG: CommonJS から ES Modules を読み込む

example.mjs

// ES Modules から CommonJS を読み込む場合
import calc from "./calc.cjs"
// 一部関数のimportもできる
// import {plus} from './calc.cjs'

console.log(calc)

const result = calc.plus(1, 2)
console.log(result)

ES Modulesの挙動の違い

  • No require, exports, or module.exports
  • No "__filename" or "__dirname"
  • require で JSON が読み込めない

test.mjs

// ES Modulesでファイル名とディレクトリ名を取り出す例

import { fileURLToPath } from "url"
import { dirname } from "path"

console.log(import.meta.url)
// -> "file://"から始まるURLの形式でパスが記載される
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
// console.log(__filename)
// console.log(__dirname)

// or

// new URL -> オブジェクトに変換されて、パスのみを取り出すことできる
console.log(new URL(".", import.meta.url))
// new URLに'.'を引数に渡すとパスを追加しないという意味になる
const __dirname2 = fileURLToPath(new URL(".", import.meta.url))
console.log(__dirname2)

test2.mjs

// ES ModulesでJSONファイルをオブジェクト形式で読み込む例

// createRequire
// -> CommonJSでモジュールを読み込むrequireを作成することができる
import { createRequire } from "module"

const require = createRequire(import.meta.url)
const jsonObj = require("./sample.json")
console.log(jsonObj)

test2.cjs

// Common JSでJSONファイルをオブジェクト形式で読み込む方法
const jsonObj = require("./sample.json")
console.log(jsonObj)

ブラウザ環境とNode.js環境の違い

  • モジュール管理の仕組みが異なる
    ブラウザ → ES Modules
    Node.js → CommonJS、ES Modules

  • 使える機能が異なる
    ブラウザ → document(DOM API)、alert など
    Node.js → require、fs モジュール、path モジュールなど

  • グローバルオブジェクトが異なる
    (グローバルオブジェクト → グローバルスコープ上に常時存在するオブジェクト)
    ブラウザ → window
    Node.js → global
    globalThis:適宜グローバルオブジェクトを返却するキーワード

クロスプラットフォームで動くコードは、 Universal(Isomorphic) JavaScript と呼ばれる 例)React の CSR(Client Side Rendering) / SSR(Server Side Rendering) など

デバッグの方法

VSCodeで[実行とデバッグ]のタブに切り替えると[Run Current File]ボタンを押すことで、デバッグを実行できる。

  • ブレークポイント
    → 実行中のプログラムを開発者が意図的に任意の場所で停止させる際に、指定されたソースコード上の場所。VSCodeの場合、コードの左端にブレークポイントを指定できる。

  • ステップイン
    デバッグ中に停止させた場所の処理を、ステップごとに確認できる

  • ステップアウト
    デバッグ中に停止させた場所の処理を、完了した後の場所に移る

calc.js

const { plus } = require('./calc');
const result = plus(1, 2);
console.log(result);

example.js

const { plus } = require('./calc');
const result = plus(1, 2);
console.log(result);

VSCodeデバッグ時に、設定ファイルを予め用意する場合