1. 開発環境の構築

JavaScript 開発環境を構築するためには、以下の手順を実行してください。

1.1. バージョンマネージャー

バージョンマネージャーを使用することで、異なるバージョンの Node.js を簡単に切り替えることができます。以下の手順でバージョンマネージャーをセットアップしてください。

1.1.1. バージョンマネージャーのセットアップ

  1. NVM をインストールします。NVM は、Node.js のバージョンを管理するためのツールです。以下のコマンドを実行して、NVM をインストールしてください。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
  1. npm をインストールします。npm は、Node.js のパッケージマネージャーです。以下のコマンドを実行して、npm をインストールしてください。

nvm list
nvm install 16.10.1
npm -v
  1. yarn をインストールします。yarn は、npm の代替となるパッケージマネージャーです。以下のコマンドを実行して、yarn をインストールしてください。

npm install -g yarn
yarn -v
  1. ターミナルを再起動します。

1.1.2. トランスパイラ

トランスパイラを使用することで、ES6 以降の構文を ES5 に変換することができます。以下の手順でトランスパイラをセットアップしてください。

1.1.3. トランスパイラのセットアップ

  1. package.json ファイルを作成します。以下のコマンドを実行して、package.json ファイルを作成してください。

npm init -y

-y オプションを指定することで、package.json ファイルの内容をデフォルト値で作成することができます。

  1. Babel をインストールします。Babel は、トランスパイラの一つです。以下のコマンドを実行して、Babel をインストールしてください。

npm install --save-dev @babel/core @babel/cli @babel/preset-env

--save-dev オプションを指定することで、package.json ファイルの devDependencies にパッケージを追加することができます。

  1. .babelrc ファイルを作成します。以下のコマンドを実行して、.babelrc ファイルを作成してください。

touch .babelrc
  1. .babelrc ファイルに以下の内容を記述してください。

{
  "presets": ["@babel/preset-env"]
}

1.1.4. トランスパイラの設定

  1. package.json ファイルを開き、以下の内容を追加してください。

{
  "scripts": {
    "build": "babel src -d dist"
  }
}

scripts には、npm コマンドを登録することができます。今回は、build コマンドを登録しています。build コマンドは、src ディレクトリの JavaScript ファイルをトランスパイルして、dist ディレクトリに出力するコマンドです。

1.1.5. トランスパイラの実行

  1. src ディレクトリを作成して、index.js ファイルを作成します。

// テンプレートリテラル
const name = 'John Doe';
const message = `Hello, ${name}!`;

// アロー関数
const add = (x, y) => x + y;

// デフォルトパラメーター
function greet(name = 'World') {
  console.log(`Hello, ${name}!`);
}

// 分割代入
const person = {
  firstName: 'John',
  lastName: 'Doe'
};

const { firstName, lastName } = person;

// スプレッド演算子
const arr = [1, 2, 3];
const arrCopy = [...arr];

// クラス
class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}
  1. 以下のコマンドを実行して、トランスパイルを実行してください。

npm run build
  1. ES6 以降の構文が ES5 に変換されていることを確認してください。

"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
// テンプレートリテラル
var name = 'John Doe';
var message = "Hello, ".concat(name, "!");

// アロー関数
var add = function add(x, y) {
  return x + y;
};

// デフォルトパラメーター
function greet() {
  var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'World';
  console.log("Hello, ".concat(name, "!"));
}

// 分割代入
var person = {
  firstName: 'John',
  lastName: 'Doe'
};
var firstName = person.firstName,
  lastName = person.lastName;

// スプレッド演算子
var arr = [1, 2, 3];
var arrCopy = [].concat(arr);

// クラス
var Person = /*#__PURE__*/function () {
  function Person(firstName, lastName) {
    _classCallCheck(this, Person);
    this.firstName = firstName;
    this.lastName = lastName;
  }
  _createClass(Person, [{
    key: "getFullName",
    value: function getFullName() {
      return "".concat(this.firstName, " ").concat(this.lastName);
    }
  }]);
  return Person;
}();

1.2. モジュールバンドラー

モジュールバンドラーを使用することで、複数の JavaScript ファイルを一つのファイルにまとめることができます。以下の手順でモジュールバンドラーをセットアップしてください。

1.2.1. モジュールバンドラーのセットアップ

  1. Webpack をインストールします。Webpack は、モジュールバンドラーの一つです。以下のコマンドを実行して、Webpack をインストールしてください。

npm install --save-dev webpack webpack-cli
npx webpack --version

npx コマンドは、npm パッケージを実行するためのコマンドです。npx コマンドを使用することで、ローカルにインストールされている npm パッケージを実行することができます。

  1. webpack.config.js ファイルを作成します。以下のコマンドを実行して、webpack.config.js ファイルを作成してください。

touch webpack.config.js
  1. webpack.config.js ファイルに以下の内容を記述してください。

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js',
  },
};
  1. package.json ファイルに以下の内容に変更してください。

{
  "scripts": {
    "build": "webpack"
  }
}

1.2.2. モジュールバンドラーの実行

  1. ./src/sample_es5.js ファイルを作成してください。

function greeting(name) {
  return 'Hello ' + name;
}

module.exports = greeting;
  1. ./src/index.js ファイルを変更してください。

var greeting = require('./sample_es5');

console.log(greeting('ES5'));
  1. 以下のコマンドを実行して、モジュールバンドラーを実行してください。

npm run build
  1. ./dist/bundle.js ファイルが作成されていることを確認してください。

  2. ./dist/bundle.js ファイルを実行してください。

node ./dist/bundle.js

1.2.3. モジュールバンドラーの設定

  1. ./src/sample_es6.js ファイルを作成してください。

class Greeting {
  constructor(name) {
    this.name = name;
  }
  say() {
    console.log(`Hello ${this.name}`);
  }
}

export default Greeting;
  1. ./src/index.js ファイルを変更してください。

var greeting = require('./sample_es5');
console.log(greeting('ES5'));

var greet = require('./sample_es6');
var g = new greet.default('ES6');
g.say();
  1. 以下のコマンドを実行して、モジュールバンドラーを実行してください。

npm run build
  1. ./dist/bundle.js ファイルが作成されていることを確認してください。

  2. ./dist/bundle.js ファイルを実行してください。

node ./dist/bundle.js
  1. 現状では ES6 のコードをそのまま出力しています。ES5 に変換するためには、babel-loader を使用します。 パッケージをインストールして webpack.config.js に以下のコードを変更してください。

npm install --save-dev babel-loader
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
            },
          },
        ],
      },
    ],
  },
  target: ['web', 'es5'],
};
  1. 以下のコマンドを実行して、モジュールバンドラーを実行してください。

npm run build
  1. ./dist/bundle.js ファイルが作成されていることを確認してください。

  2. ./dist/bundle.js ファイルを実行してください。

node ./dist/bundle.js

1.3. TypeScript

TypeScript を使用することで、JavaScript に型を導入することができます。以下の手順で TypeScript をセットアップしてください。

1.3.1. TypeScript のセットアップ

  1. TypeScript をインストールします。以下のコマンドを実行して、TypeScript をインストールしてください。

npm install --save-dev typescript
  1. tsconfig.json ファイルを作成します。以下のコマンドを実行して、tsconfig.json ファイルを作成してください。

npx tsc --init

1.3.2. トランスパイラの設定

  1. 必要なパッケージをインストールします。

npm install --save-dev @babel/preset-typescript @babel/plugin-proposal-class-properties typescript
  1. .babelrc ファイルを変更します。

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript"
  ],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

1.3.3. トランスパイラの実行

  1. ./src/sample.ts ファイルを作成してください。

class Greeting {
  constructor(public name: string) {}
  say() {
    console.log(`Hello ${this.name}`);
  }
}
  1. ./src/index.ts ファイルを変更してください。

import { Greeting } from "./sample";

const greeting = new Greeting("TypeScript");
greeting.say();
  1. 以下のコマンドを実行して、トランスパイルを実行してください。

npx babel src --extensions '.ts,.tsx' --out-dir dist
  1. ./dist/sample.js ファイルが作成されていることを確認してください。

  2. ./dist/sample.js ファイルを実行してください。

node ./dist/index.js

1.3.4. モジュールバンドラーの設定

  1. 必要なパッケージをインストールします。

npm install --save-dev ts-loader
  1. webpack.config.js ファイルを開き、以下の内容を追加してください。

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js',
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
            },
          },
        ],
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
      },
    ],
  },
  target: ['web', 'es5'],
};
  1. 以下のコマンドを実行して、モジュールバンドラーを実行してください。

npm run build
  1. ./dist/bundle.js ファイルが作成されていることを確認してください。

  2. ./dist/bundle.js ファイルを実行してください。

node ./dist/bundle.js

TypeScript ファイルをそのまま実行したい場合は、ts-node を使用します。

npm install --save-dev ts-node

動かし方は以下の通りです。

npx ts-node src/index.ts

1.4. webpack-dev-server のセットアップ

webpack-dev-server を使用することで、開発中に自動的にビルドを実行し、ブラウザをリロードすることができます。以下の手順で webpack-dev-server をセットアップしてください。

1.4.1. webpack-dev-server のインストール

  1. 以下のコマンドを実行して、webpack-dev-server をインストールしてください。

npm install --save-dev webpack-dev-server

1.4.2. webpack-dev-server の設定

  1. webpack.config.js ファイルを開き、以下の内容を追加してください。

const path = require('path');

module.exports = {
  //...
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    compress: true,
    port: 9000,
  },
};

1.4.3. webpack-dev-server の実行

  1. 以下のコマンドを実行して、webpack-dev-server を実行してください。

npx webpack serve

終了する場合は、Ctrl + C を押してください。

  1. HTMLWebpackPlugin プラグインを使用して js ファイルに自動的にバンドルされた script タグを生成し、index.html に挿入できるようにします。

npm install --save-dev html-webpack-plugin
  1. プロジェクト直下に index.html を作成してください。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>App</title>
  </head>
  <body>
    <h1>アプリケーション</h1>
  </body>
</html>
  1. webpack.config.js ファイルを開き、以下の内容を追加してください。

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // ...他のWebpack設定

  plugins: [
    new HtmlWebpackPlugin({
      template: 'index.html',
    }),
  ],
};
  1. package.json ファイルを開き、以下の内容を追加してください。

{
  // ...他の設定
  "scripts": {
    "start": "webpack server --config ./webpack.config.js --open"
  }
}
  1. 以下のコマンドを実行して、webpack-dev-server を実行してください。

npm start
  1. ソースマップを有効にすることで、開発中にエラーが発生した場合に、エラーが発生したファイル名と行数を表示することができます。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const env = process.env.NODE_ENV || "development";
const isDevelopment = env === "development";

module.exports = {
  mode: env,
  devtool: isDevelopment ? "source-map" : false,
  1. TypeScript の型チェックを実行するために、tsconfig.json に以下の設定を追加してください。

{
  "compilerOptions": {
    "sourceMap": true
  }
}

1.5. テスティングフレームワークのセットアップ

テストを自動化することで、開発中に問題を早期に発見し、品質を向上させることができます。以下の手順でテスティングフレームワークをセットアップしてください。

1.5.1. Jest とは

Jest は、JavaScript のテスティングフレームワークです。以下の手順で Jest をセットアップしてください。

1.5.2. Jest のインストール

  1. 以下のコマンドを実行して、Jest をインストールしてください。

npm install --save-dev jest

1.5.3. Jest の設定

  1. package.json ファイルを開き、以下の内容を追加してください。

{
  "scripts": {
    "test": "jest"
  }
}
  1. ES Modules を私用している場合はテストが失敗するので以下の設定を package.json に追加する

...
  "jest": {
    "moduleFileExtensions": [
      "js",
      "ts"
    ],
    "testMatch": [
      "**/**/*.test.js",
      "**/**/*.test.ts"
    ]
  }
}

1.5.4. TypeScript 対応

  1. 以下のコマンドを実行して、必要なパッケージをインストールしてください。

npm install --save-dev @types/jest ts-jest
  1. tsconfig.json ファイルを開き、以下の内容を追加してください。

"module": "es2020",

1.5.5. テストの作成

  1. テストファイルを作成してください。

src/app.js

export function sum(a, b) {
  return a + b;
}

src/app.test.js

import { sum } from './app.js';

test('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);
  expect(result).toBe(3);
});

src/app.ts

export function sum(a: number, b: number): number {
  return a + b;
}

src/app.test.ts

import { sum } from './app';

test('adds 1 + 2 to equal 3', () => {
  const result = sum(1, 2);
  expect(result).toBe(3);
});

1.5.6. テストの実行

  1. 以下のコマンドを実行して、テストを実行してください。

npm test
  1. テストカバレッジを計測することで、テストがどの程度の範囲をカバーしているかを確認することができます。

    "test": "jest --coverage"

1.6. フォーマッタのセットアップ

フォーマッタを使用することで、コードのスタイルを統一し、読みやすくすることができます。以下の手順でフォーマッタをセットアップしてください。

1.6.1. Prettier とは

Prettier は、コードのフォーマットを自動化するツールです。以下の手順で Prettier をセットアップしてください。

1.6.2. パッケージのインストール

  1. 以下のコマンドを実行して、Prettier をインストールしてください。

npm install --save-dev prettier

1.6.3. パッケージの設定

  1. .prettierrc ファイルを作成し、以下の内容を記述してください。

{
  "semi": true,
  "trailingComma": "all",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2
}

1.6.4. フォーマッタの実行

  1. 以下のコマンドを実行して、フォーマッタを実行してください。

npx prettier --write .
  1. package.json ファイルを開き、以下の内容を追加してください。

{
  "scripts": {
    "format": "prettier --write ."
  }
}

1.7. 開発ツールのセットアップ

開発ツールを使用することで、開発効率を向上させることができます。以下の手順で開発ツールをセットアップしてください。

1.7.1. パッケージのインストール

  1. 以下のコマンドを実行して、開発ツールをインストールしてください。

npm install --save-dev @k2works/full-stack-lab

./index.html を以下の内容に変更します。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>App</title>
  </head>
  <body>
    <h1>アプリケーション</h1>
    <div id="app"></div>
    <div id="app-dev"></div>
  </body>
</html>

./src/app.js を以下の内容に変更します。

console.log('app.js: loaded');
export class App {
  constructor() {
    console.log('App initialized');
  }
}

export function sum(a, b) {
  return a + b;
}

./src/index.js をルート直下に移動して以下の内容変更します。

import { App } from './src/app.js';
const app = new App();

import { render } from '@k2works/full-stack-lab';
const contents = `
## 機能名
## 仕様
## TODOリスト
`;

const uml = `
abstract class AbstractList
abstract AbstractCollection
interface List
interface Collection
List <|-- AbstractList
Collection <|-- AbstractCollection
Collection <|- List
AbstractCollection <|- AbstractList
AbstractList <|-- ArrayList
class ArrayList {
  Object[] elementData
  size()
}
enum TimeUnit {
  DAYS
  HOURS
  MINUTES
}
annotation SuppressWarnings
`;

const erd = `
' hide the spot
hide circle
' avoid problems with angled crows feet
skinparam linetype ortho
entity "Entity01" as e01 {
  *e1_id : number <<generated>>
  --
  *name : text
  description : text
}
entity "Entity02" as e02 {
  *e2_id : number <<generated>>
  --
  *e1_id : number <<FK>>
  other_details : text
}
entity "Entity03" as e03 {
  *e3_id : number <<generated>>
  --
  e1_id : number <<FK>>
  other_details : text
}
e01 ||..o{ e02
e01 |o..o{ e03
`;
render({ contents, uml, erd });
  1. TypScript も同様に変更してください。

  2. 最後に不要なファイルを削除します。

1.7.2. 開発ツールの設定

  1. webpack.config.js を以下の内容に変更します。

...
  entry: './index.js',
...

1.7.3. 開発ツールの実行

  1. 以下のコマンドを実行して、開発ツールを実行してください。

npm start