npm+p5.js, Tone.js and kd-tree-javascript

これはどちらかというとプロの方向けnoteというより自分が理解するためのメモであるからしてあまり気にしないでください。

大きな流れ

  1. npmなどのインストール

  2. プロジェクトディレクトリの作成と初期化

  3. webpack, webpack-cli and webpack-dev-serverのローカル環境へのインストール

  4. Babelのローカル環境へのインストール

  5. p5.js, Tone.jsのローカル環境へのインストール

  6. kd-tree-javascriptのローカル環境へのインストール

  7. webpack.config.jsの作成

  8. src/index.jsの作成

  9. dist/index.htmlの作成

  10. package.jsonの編集

  11. 起動 npm start

作業の意味

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>p5.js</title>
</head>
<body>
    <script src="bundle.js"></script>
</body>
</html>

index.htmlを見ると、通常のps.jsのindex.htmlとは異なる。

下記コードはごく普通にp5.jsを使ったhtmlだが、ここではscriptタグでp5と記述したコードを別々に読み込んでいる。

  <head>
    <meta charset="UTF-8">
    <title>p5.js</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
    <script src="sketch.js"></script>
  </head>

しかし、webpackを使った環境だとbundle.jsのみを読み込んでいる。

webpack.config.jsを見てみる。確かにfilename: 'bundle.js'と書かれている。これが出力されるJavaScriptファイルの名前だと分かる。

const path = require('path');

module.exports = {
  entry: './src/index.js', // エントリーポイント
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    static: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

webpackはJavaScriptをバンドルしているからだ。

bundle.jsがエントリーポイントとして定義されているが、エントリーポイントというのは、Webpackがモジュール依存関係の解析を始める起点だ。

エントリーファイル内でインポートされているJavaScriptファイルやその他のアセット(CSS、画像など)も再帰的に解析され、最終的に一つまたは複数のバンドルファイルとして出力される。これがbundle.jsである。

Webpackはなにより、Babelのようなトランスパイラーと統合されることで、最新のJavaScript機能(ES6/ESNextなど)を使用して書かれたコードを、古いブラウザでも動作するJavaScriptに変換できる。これが目的である。

他にもコードの圧縮とか、不要コードの除去とか、画像の最適化などの多くの最適化手法を提供している。

index.jsを見てみる

import p5 from 'p5';
import * as Tone from 'tone';
import kdTree from '../lib/kdTree.js';

new p5((sketch) => {
  sketch.setup = () => {
    sketch.createCanvas(400, 400);
  };

  sketch.draw = () => {
    sketch.background(220);
      sketch.ellipse(sketch.width / 2, sketch.height / 3, 150, 250);
  };
});

index.js内部にすべてのJavaScriptのコードが記述されていることが分かる。

他には、

  • webpack-cliはwebpackのコマンドラインインタフェース

  • webpack-dev-serverはホットリロード(ファイル変更時の自動リロード)などの機能を利用できる開発用ローカルのウェブサーバである

  • Babelは新しいES6のJavaScriptをトランスパイルしてブラウザなどで動作できるようにするため

等の意味がある。

手順

npmなどのインストール

nvm、nodeなどと一緒にインストール。詳細は省く。色々載ってるし


プロジェクトディレクトリの作成と初期化

mkdir myProject
cd myProject
npm init -y


webpack, webpack-cli and webpack-dev-serverのローカル環境へのインストール

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


Babelのローカル環境へのインストール

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


p5.js, Tone.jsのインストール

npm install p5 tone

ここで注目すべきなのは --save-devのオプションがないことだ。
--save-devオプションは実行環境ではなく、開発環境のみに必要なパッケージをインストールする際に指定されるオプションである。p5.jsとtoneは実行時に必要なパッケージ(ライブラリ)である。
npmにはdevDependenciesという開発時に必要な依存関係と、dependenciesという実行時に必要な依存関係を分けて考えることだ。
しかしnpmでのインストールはあくまでプロジェクトレベルのインストールであることに注意しなくてはいけない。


kd-tree-javascriptのローカル環境へのインストール

p5.jsとTone.jsはnpmレジストリに登録されているのでnpmコマンドを通じてインストールできるのに対し、ubilabs/kd-tree-javascriptは登録されていないため、GitHubからのダウンロードが必要となる。

SSH経由の場合:

git clone git@github.com:ubilabs/kd-tree-javascript.git lib/kd-tree-javascript

HTTPS経由の場合:

git clone https://github.com/ubilabs/kd-tree-javascript.git lib/kd-tree-javascript

gitがインストールされていな場合は,github.com/ubilabsからzipファイルをダウンロードできるだろう


webpack.config.jsの作成

プロジェクトディレクトのトップにwebpack.config.jsファイルを以下のように作成

const path = require('path');

module.exports = {
  entry: './src/index.js', // エントリーポイント
  output: {
    filename: 'bundle.js', //html内部ではこのjsを呼び出すようにする
    path: path.resolve(__dirname, 'dist'),  // distにhtmlを作る
  },
  devServer: {
    static: path.join(__dirname, 'dist'),  // distにhtmlを作る
    compress: true,
      port: 9000,
      hot: true,
      open: true,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};


src/index.jsの作成

プロジェクトディレクトリ配下にsrcディレクトリを作ってindex.jsを作成。kdTreeをインポートする行については実際にlibディレクトリにどんなjsが展開されていて、何をインポートするのかを確認が必要。

// p5.js、Tone.js、kd-treeをimportします(kd-treeのimportパスは適宜調整)
import p5 from 'p5';
import * as Tone from 'tone';
import kdTree from '../lib/kd-tree-javascript/kdTree.js';

// ここにp5.js、Tone.js、kd-treeを使用したアプリケーションのコードを記述

new p5((sketch) => {
  sketch.setup = () => {
    sketch.createCanvas(400, 400);
  };

  sketch.draw = () => {
    sketch.background(220);
      sketch.ellipse(sketch.width / 2, sketch.height / 3, 150, 250);
  };
});

git コマンドでインストール先のディレクトリを指定しているのでこういうディレクトリの構造になることを理解する必要がある。


dist/index.htmlの作成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My p5.js Project</title>
</head>
<body>
    <script src="bundle.js"></script>
</body>
</html>

package.jsonの編集

{
    "name": "field",
    "version": "1.0.0",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "webpack serve --mode development",
        "build": "webpack --mode production"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "dependencies": {
        "p5": "^1.9.2",
        "tone": "^14.7.77"
    },
    "devDependencies": {
        "@babel/core": "^7.24.4",
        "@babel/preset-env": "^7.24.4",
        "babel-loader": "^9.1.3",
        "webpack": "^5.91.0",
        "webpack-cli": "^5.1.4",
        "webpack-dev-server": "^5.0.4"
    }
}


npm start

これで開発用web server上でindex.html, index.jsの内容を見ることができる。ブラウザーを起動して、http://localhost:9000/ のURLで自マシンにおける9000ボートで待っている開発サーバにアクセスするということになる。

掲載したサンプルのコードだとこんなのが描かれる。

これじゃ楽しくない

ちゅうい

マニュアルでエディットした部分があるので、このままで動かなければ聞いてください。AIにでも。