【完走賞ゲット-7】p5.js Web Editor で JavaScript のモジュール（ES Modules）を扱う： simplex-noise.js の最新版（4.x）を CDN から import する

## はじめに
こちらは、[完走賞ゲットのため小ネタを毎日投稿しようとチャレンジする Advent Calendar 2022](https://qiita.com/advent-calendar/2022/youtoy) の 7日目の記事です。

今回の記事では、p5.js と JavaScript のモジュール「ES Modules」に関する内容を扱います。HTML＋JavaScript で扱う場合、 `<script type="module" src="。。。"></script>` といった書き方をしつつ import文で扱ったりするやつの話です。

## 参照した情報など
今回の記事を書くにあたり、参照した情報や関連するページを記載します。

- 参照した情報など（実装や説明書き関連で）
   - [JavaScript モジュール - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules)
   - [How to use export & import in p5.js - p5.js / Coding Questions - Processing Foundation](https://discourse.processing.org/t/how-to-use-export-import-in-p5-js/31724/4)
   - [Script type="module" Draw and Setup Not Working - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/24662/script-type-module-draw-and-setup-not-working.html)
- simplex-noise.js関連
   - [jwagner/simplex-noise.js: A fast simplex noise implementation in Javascript / Typescript.](https://github.com/jwagner/simplex-noise.js)
   - [simplex-noise CDN by jsDelivr - A CDN for npm and GitHub](https://www.jsdelivr.com/package/npm/simplex-noise?path=dist%2Fcjs)

## p5.js で JavaScript のモジュールを使ってみる
### 実装する環境
それでは、p5.js を使ったプログラムを書く中で、JavaScript のモジュールを使ってみます。実装環境については、自分が Qiitaの記事を書いたり p5.js の試作をする際にもよく使っている、オンラインの環境「p5.js Web Editor」を使います。 

### simplex-noise.js関連の情報
実装していく前に、今回利用する「[simplex-noise.js](https://github.com/jwagner/simplex-noise.js)」についてなど、情報を軽く確認しておきます。
![simplex-noise.js](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/dc7e3e59-e23b-9e43-4cdf-b0512049752f.png)

simplex-noise.js について、公式ページでは「A fast simplex noise implementation in Javascript / Typescript.」と説明されています。

#### simplex noise
説明文の中で「simplex noise」という言葉が出てきますが、そもそもこれは何か、という話が...
それについて、Wikipedia の「パーリンノイズ（Perlin noise）」の日本語ページで知ることができます。（※ ちなみに、パーリンノイズは、[p5.js の noise](https://p5js.org/reference/#/p5/noise) で実装されているノイズです）

●パーリンノイズ - Wikipedia
　https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%83%AA%E3%83%B3%E3%83%8E%E3%82%A4%E3%82%BA
![パーリンノイズ - Wikipedia](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a44f5412-aee8-f17a-7578-c6a740767332.png)

上記のとおり、パーリンノイズの「n次元対応版」で、「計算部分が改善されたもの」となるようです。日本語のページはないですが、以下の Wikipedia のページもあったりするようです。

●Simplex noise - Wikipedia
　https://en.wikipedia.org/wiki/Simplex_noise

#### simplex-noise.js の扱い方
この simplex-noise.js は、以下のツイートをしていたころに初めて利用しました。
その時は、最新版の 4系ではなく、古いバージョンの 2系を使っていました。

https://twitter.com/youtoy/status/1441249487624699909

その理由は、当時は 4系を使う場合の対処法、つまり p5.js で JavaScript のモジュール（ES Modules）を扱うための対処法がすぐに分からなかったためです。これを 2系にしてやれば、 `<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>` で読み込んで、あとは JavaScript のプログラムで　`new SimplexNoise();` を呼べばよいだけ、となります（※ 通常のスクリプトになる）。

これを 4系で扱うためには、以下に書かれた使い方を用いる必要があります。
![4系で扱う](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9d264a77-63fb-4fd4-5f7e-3be2661c6b16.png)

#### 単純に import文を使ってみる
まずは、単純に import文を使ってみます。import文で読み込む対象は、CDN上の最新版の simplex-noise.js とします。

import文を使うために、p5.js Web Editor の index.html で以下の書きかえを行います。差分は、 `type="module` を付け加えた部分のみです。

```html:書きかえ前
<script src="sketch.js"></script>
```

```html:書きかえ後
<script src="sketch.js" type="module"></script>
```

次に、sketch.js を作っていきます。JavaScript のプログラムは、単純に 2D のノイズをログ出力するというもので試そうとしてみました。しかし、このプログラムだと動いてくれません。

```javascript
import { createNoise2D } from "https://cdn.jsdelivr.net/npm/simplex-noise@4.0.1/dist/esm/simplex-noise.js";

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);

  const noise2D = createNoise2D();
  console.log(noise2D(10, 20));
}
```

#### 単純な import文の利用で動かない原因
単純な import文の利用が p5.js で行えない理由は、以下の [MDN のページの記載](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules#%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AE%E9%80%9A%E5%B8%B8%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E9%96%93%E3%81%AE%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E9%81%95%E3%81%84)を見て分かりました。
![モジュールと通常のスクリプトの違い](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0886435c-52c7-161d-c26c-55c1823eee90.png)

p5.js は関数がグローバルに追加されますが（※ [Instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) ではなく、Global mode の場合という話になりますが）、上記の import文を扱うための対処を行うと、sketch.js のスコープが限定的になってしまうため、うまく動かなくなるようです。

#### スコープが限定された中で p5.js の関数を扱う
p5.js の関数がグローバルスコープにあり、それが読めなくなったため、上記の状況が発生した形です。

そこで、この対処法を調べてみて、その 1つの方法が分かりました（※ 上の「参照した情報など」の部分で書いたサイトの情報などから）。具体的には、「[windowオブジェクト](https://developer.mozilla.org/ja/docs/Web/API/Window/window)」を利用する、という対応です。以下で、上記でうまく動かなかったプログラムの書きかえ後のプログラムを掲載してみます。

```javascript
import { createNoise2D } from "https://cdn.jsdelivr.net/npm/simplex-noise@4.0.1/dist/esm/simplex-noise.js";

window.setup = () => {
  createCanvas(500, 400);
};

window.draw = () => {
  background(0);

  const noise2D = createNoise2D();
  console.log(noise2D(10, 20));
};
```

「window.setup」や「window.draw」と記載することで、グローバルスコープの関数を呼び出すことができ、無事に import文で読み込んだ simplex-noise.js の 4系を利用することができました。
![simplex-noise.js の 4系が使えた状態](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/57766058-7da4-1035-f463-d9aa73510fa1.png)

## 【追記】 別のやり方
その後、「ダイナミックインポート」を使うという別のやり方も試しました。

●p5.js Web Editor で JavaScript のモジュール（ES Modules）を扱う【その2】： simplex-noise.js の CDN からの import でダイナミックインポートを使う - Qiita
　https://qiita.com/youtoy/items/838dce76d5be0d44fa14