見出し画像

TypeScript+PixiJSの準備する

不思議だねえ
博奕打ちってのは楽して大金を稼ごうって人種だろ
でもそのわりにはやけに勤勉じゃない

哲也-雀聖と呼ばれた男

※このページを読んで得をするか、あるいは時間を無駄にするかは結構な賭けです。

参考


VSCodeおよびNode.jsとnpmの準備は済んでるものとする。

htmlから

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>    
  </head>
  <body>
    <script>    

    //ここがjavascript
    document.write("Hello world");

    </script>
  </body>
</html>

ファイルを割る

game.js

document.write("Hello world");

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>    
  </head>
  <body> 

    <!-- ここでJavaScriptファイルを読み込む--> 
    <script src="game.js"></script>

  </body>
</html>

<head>でも読み込める
ただし位置によって読み込みうんたらの挙動の差がある

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>    

    <!-- ここでJavaScriptファイルを読み込む--> 
    <script src="game.js"></script>

  </head>
  <body>

  </body>
</html>

ファイルのパスは./が付けられたりもする。

<script src="./game.js"></script>


PixiJSをダウンロードするかCDNするかnpmでインストールする

公式サイトから手でダウンロードした場合

公式からpixi.jsやpixi.min.jsをもらってくる。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>  
       
  </head>
  <body>
	<script src="pixi.js"></script>
	<script>
        const app = new PIXI.Application({
            width: 800,
            height: 600,
            backgroundColor: 0x1099bb,
        });        
        document.body.appendChild(app.view); 
	</script>
  </body>
</html>

モジュールをブラウザに直接インポート

mjsをダウンロードした場合
mjsは直書きが効く。

app.mjs

import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';

const app = new Application();
document.body.appendChild(app.view);
const texture = await Assets.load('image.png');
const bunny = new Sprite(texture);
app.stage.addChild(bunny);

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>  
  </head>
  <body>
    <script type="module" src="./app.mjs"></script>
  </body>
</html>

できるやり方

    <script type="module">
      import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';

      const app = new Application();
      document.body.appendChild(app.view);
      const texture = await Assets.load('image.png');
      const bunny = new Sprite(texture);
      app.stage.addChild(bunny);
    </script>
    <script type="module">
      import * as  PIXI  from './pixi.mjs';

      const app = new PIXI.Application();
      document.body.appendChild(app.view);
      const texture = await PIXI.Assets.load('image.png');
      const bunny = new PIXI.Sprite(texture);
      app.stage.addChild(bunny);
    </script>
    <script type="module">
      import * as  PIXI  from './pixi.mjs';

      const app = new PIXI.Application({
          width: 800,
          height: 600,
          backgroundColor: 0x1099bb,
      });        
      document.body.appendChild(app.view);
      const texture = await PIXI.Assets.load('image.png');
      const bunny = new PIXI.Sprite(texture);
      app.stage.addChild(bunny);
    </script>

できないやり方

src="pixi.mjs"はpixi.jsとは違う例。

    <script type="module" src="pixi.mjs"></script>
    <script>
      const app = new PIXI.Application({
          width: 800,
          height: 600,
          backgroundColor: 0x1099bb,
      });        
      document.body.appendChild(app.view); 
      const img = PIXI.Sprite.from('image.png');
      app.stage.addChild(img)
    </script>

import * as PIXI from './pixi.mjs';
あるいは
import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';
してない例。

    <script type="module">
          const app = new PIXI.Application({
              width: 800,
              height: 600,
              backgroundColor: 0x1099bb,
          });        
          document.body.appendChild(app.view); 
          const img = PIXI.Sprite.from('image.png');
          app.stage.addChild(img)
    </script>

import使用区間にtype="module"がない例。

    <script>
      import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';
      const app = new Application();
      document.body.appendChild(app.view);
      const texture = await Assets.load('image.png');
      const sprite = new Sprite(texture);
      app.stage.addChild(sprite);
    </script>

以下は動く。
<script type="module" src="pixi.mjs"></script>自体は無駄であるが、重複したら動かないというものでもない。

    <script type="module" src="pixi.mjs"></script>
    <script type="module">
      import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';

      const app = new Application();
      document.body.appendChild(app.view);
      const texture = await Assets.load('image.png');
      const sprite = new Sprite(texture);
      app.stage.addChild(sprite);
  
    </script>

pixi.jsでも動く。無駄ではあるが影響もしてないと思われる。繰り返すが無駄である。

    <script type="module" src="pixi.js"></script>
    <script type="module">
      import { Application, Assets, Sprite, SCALE_MODES } from './pixi.mjs';

      const app = new Application();
      document.body.appendChild(app.view);
      const texture = await Assets.load('image.png');
      const sprite = new Sprite(texture);
      app.stage.addChild(sprite);
  
    </script>

以下は動かない。
パスに./が無い。
html領域のsrc=""とJavaScript領域のimportではパスの扱いが異なる。
正直こんなもんはそのうちできるようになる可能性すらある。

    <script type="module">
      import { Application, Assets, Sprite, SCALE_MODES } from 'pixi.mjs';

      const app = new Application();
      document.body.appendChild(app.view);
      const texture = await Assets.load('image.png');
      const sprite = new Sprite(texture);
      app.stage.addChild(sprite);
  
    </script>
    <script type="module">
          import * as PIXI from 'pixi.mjs';
          const app = new PIXI.Application({
              width: 800,
              height: 600,
              backgroundColor: 0x1099bb,
          });        
          document.body.appendChild(app.view); 
          const img = PIXI.Sprite.from('image.png');
          app.stage.addChild(img)
    </script>


CDNの場合

CDN(content delivery network)

npmでインストールした場合

あるいはコード内でimportを用いる場合、

<script type="module"></script>

を用いればできそうな気がするが、そのままではできない。
PixiJSはおそらくwebpackが前提。
それでもimportしたいならpixi.jsではなくpixi.mjsを用いる。
モジュールをブラウザに直接インポートの項を参照。

できそうだができないの図。

      <script type="module">
        import { Application, Assets, Sprite } from './pixi.js';
        const app = new Application();
        document.body.appendChild(app.view);
        const texture = await Assets.load('image.png');
        const bunny = new Sprite(texture);
        app.stage.addChild(bunny);
      </script>
    <script type="module">
      import * as PIXI from './pixi.js';
      const app = new PIXI.Application({
          width: 800,
          height: 600,
          backgroundColor: 0x1099bb,
      });
      document.body.appendChild(app.view);
      const img = PIXI.Sprite.from('image.png');
      app.stage.addChild(img);
    </script>
    <script type="module">
      import * as PIXI from './pixi.js';
      const app = new PIXI.Application({
          width: 800,
          height: 600,
          backgroundColor: 0x1099bb,
      });
      document.body.appendChild(app.view);
      const img = PIXI.Sprite.from('image.png');
      app.stage.addChild(img);
    </script>

    <script type="module" src="pixi.js"></script>

ローカルインストールならパスの可能性もあるが、あれやこれやいじくっても駄目。pixi.jsでなくpixi.mjsを使用しなければならない。
JavaScript領域だと、パスに関して./の抜けやバックスラッシュも許されない。

これはいける。
モジュールをブラウザに直接インポートの項を参照。

    <script type="module">
      import * as PIXI from './node_modules/pixi.js/dist/pixi.mjs';
      const app = new PIXI.Application({
          width: 800,
          height: 600,
          backgroundColor: 0x1099bb,
      });
      document.body.appendChild(app.view);
      const img = PIXI.Sprite.from('image.png');
      app.stage.addChild(img);
    </script>


この辺でやれそう

"type": "module"

package.jsonにこの記述を追加するとパッケージ全体がES Moduleをサポートします。

{  "name": "YYTS",  "version": "1.0.0",  "main": "index.js",  "type": "module",  "license": "Apache-2.0"}コピー

このようにすることで拡張子を.mjsに変更しなくてもそのまま.jsでES Moduleを使えるようになります。なお"type": "module"の省略時は"type": "commonjs"と指定されたとみなされます。これは今までとおりのNode.jsです。


ローカルサーバー

我々はブラウザで気楽にプログラムを動かしたい。
しかしブラウザは安全上の仕組みから、自分のパソコンから画像データを読み込むという挙動にすら制限を掛けてくる(多分same origin policyというやつ)。
その制限を回避する手段は、安全装置を完全に無視するか、ローカルサーバーでバウンドさせるかである。

つまりブラウザに、『あ、こいつhtmlをダブルクリックしたな』と思わせたらエラーになるので『あ、こいついつもみたいにネットサーフィンしてるな』と勘違いさせるのがローカルサーバー。

image.png

以下のPixiJSを利用しようとするJavaScriptを記述したhtmlは、
htmlファイルをダブルクリックしただけでは画像のロードに失敗する。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>  
       
  </head>
  <body>
	<script src="pixi.js"></script>
	<script>
        const app = new PIXI.Application({
            width: 800,
            height: 600,
            backgroundColor: 0x1099bb,
        });        
        document.body.appendChild(app.view); 
	const img = PIXI.Sprite.from('image.png');
	app.stage.addChild(img)

	</script>
  </body>
</html>


ロードに失敗。

VSCode+Live Server

VSCodeとLive Serverならば、インストールして右下のGo Liveボタンを押すだけでブラウザが立ち上がる。
ただしindex.htmlを読み込みにかかる。

ロードできた。


同手順でpixi.mjsを用いても失敗する。

<script src="pixi.mjs"></script>

基本的にソースを書き換えてセーブすればブラウザ側にも反映される。

npmからのローカルインストールの場合
以下のパスは失敗。

  <script src="./node_modules/.bin/pixi.js"></script>

以下のパスは実際にファイルが置いてあるため成功。

<script src="./node_modules/pixi.js/dist/pixi.js"></script>

mjsはやはり失敗。

<script src="./node_modules/pixi.js/dist/pixi.mjs"></script>

html領域ではスラッシュでなくバックスラッシュでもいける。
なんなら混在でもいける。

<script src="node_modules\pixi.js\dist\pixi.js"></script>
    <script src="node_modules/pixi.js\dist/pixi.js"></script>


npm+http-server

http-serverの場合、npmでインストール。
プロンプトなりターミナルなりで、index.htmlファイルを格納するフォルダまでcdして実行。跳ね返ってきたアドレスにブラウザからアクセスする。

export/import


importの挙動例。

game.js

export function func(){
    //document.write("Hello world!");//これは動かない
    alert('Hello');
}

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScriptPixiJS</title>      
  </head>
  <body>
    
    <script type="module">
      import {func} from './game.js';
      func();
    </script>

  </body>
</html>


exportでdocument.writeを使った場合のエラー

Failed to execute 'write' on 'Document':
It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

TypeScript

TypeScriptは.tsファイルである。
typescript compilerであるtscを用いると、.tsファイルは.jsファイルに変換される。単純なプログラムなら、その時点で.jsファイルは実行可能である。ゆえにブラウザで読み込んだり、Node.js系の実行環境に放り込めば遊ぶことができる。

PixiJSの場合、さらにwebpackを挟む必要がある。
これは.jsファイルから.jsファイルへの変換である。

具体的にはwebpackは

import * as PIXI from 'pixi.js'

を解決する。

npm

npmの場合

インストールには3種類ある。
グローバルインストール、
ローカルインストール、
開発環境である。

インストール状況に合わせてうまいことtscコマンドを実行する。
以下ではTypeScriptを例にとってnpmのインストールを見る。

他のパッケージでもやることは一緒である。
最終的に我々が獲得したいパッケージは
pixi.js
typescript
webpack
webpack-cli
ts-loader
である。

npm CLI Commands

(VSCode + npm)ローカルインストール

npm-install

プロンプトまたはターミナルで

npm install typescript

あるいは

npm i typescript
npm add typescript

完了するとpackage.jsonに以下の項が追加される。

  "dependencies": {
    "typescript": "^4.9.5",
  }

アンインストールはnpm-uninstall

npm uninstall typescript

またはremove, rm, r, un, unlink

ローカルインストールしているパッケージの確認はlist, ls

npm list
npm ls

npx

ローカルインストールしたものはnode_modules下位のどっかに格納されるため、例えばTypeScriptが.tsファイルをJavaScriptの.jsファイルに変換するためのコマンドtscを実行するには、コマンドラインなりターミナルなりでtscファイルが置いてあるところまでのパスを通さねばならない。

TypeScriptのtscの場合、

node_modules\.bin\tscないし
node_modules\typescript\binやらにある。

グローバルインストールした場合は

tsc

だけで実行できる。
成功すると.tsファイルから.jsファイルが作成される。
簡単なプログラムであれば、
htmlファイルはこの.jsファイルを読み込めば良い。

また、

package.jsonに

  "scripts": { 
    "tsc" : "node_modules\.bin\tsc" 
  },

と記述すればパスやらコマンドを記述する手間を省略できる。また、npxコマンド

npx tsc

を用いると勝手に探してきて実行してくれる。

グローバルインストール

各コマンド(install,uninstall,list)に、
-g ないし --globalオプションをつける。

開発環境

各コマンドに-Dないし--save-devオプションをつける。
モジュールをインストールした場合はローカルにインストールされ、package.jsonのdevDependencies項にインストールしたモジュール名が記述される。

devDependencies項にあるモジュールはインストール時に--productionオプションをつけると無視される。

tsc

.tsから.jsへの変換を受け持つ。
例えば以下のようなTypeScriptで記述されたファイルがあったとする。

app.ts

import * as PIXI from 'pixi.js'
const app = new PIXI.Application({
  width: 800,
  height: 600,
  backgroundColor: 0x1099bb,
});

document.body.appendChild(app.view as any);   

TypeScriptなのでJavaScript異なり、any型をつけている
document.body.appendChild(app.view as any);

また、PixiJSおよびTypeScriptを共にローカルインストールした場合、
import * as PIXI from 'pixi.js'
以外のパスは失敗する。./pixi.js, ./pixi.mjs, pixi.mjs, などは失敗する。
ローカルインストールした場合、と書いたが、他の条件は試していない。

app.tsをtscした結果生成されるapp.jsファイル。

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const PIXI = __importStar(require("pixi.js"));
const app = new PIXI.Application({
    width: 800,
    height: 600,
    backgroundColor: 0x1099bb,
});
document.body.appendChild(app.view);

しかしこれを受けての以下は失敗する。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>My PixiJS App</title>    
  </head>
  <body>
    <script src="app.js"></script>

  </body>
</html>

PixiJSの場合、モジュールをブラウザに直接インポート形式でないならば、
間にwebpackを挟まなければならない。

tsconfig.json

tscオプション

webpack

webpackとwebpack-cliをインストール。
また、TypeScript用のローダーをインストール。

npm install webpack webpack-cli ts-loader

webpack.config.jsを設定する。

const path = require("node:path");

module.exports = {

  entry: './src/index.ts',

  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },

  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
      },
    ],
  },
};

tsc->webpack

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>My PixiJS App</title>    
  </head>
  <body>
    <script src="dist/main.js"></script>
  </body>
</html>

index.ts

TypeScript領域。
importのパスはpixi.jsであり、app.viewはanyである。

import * as PIXI from 'pixi.js'
const app = new PIXI.Application({
  width: 800,
  height: 600,
  backgroundColor: 0x1099bb,
});

document.body.appendChild(app.view as any); 

webpackをデフォルトでやる場合
まずtscでtsファイルからjsファイルを作成。

npx tsc

これでindex.tsからindex.jsが作成される。

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const PIXI = __importStar(require("pixi.js"));
const app = new PIXI.Application({
    width: 800,
    height: 600,
    backgroundColor: 0x1099bb,
});
document.body.appendChild(app.view);

webpack実行

npx webpack

あるいは

npx webpack-cli

これでmain.jsが作成される。

webpackのデフォルトは
entryが./src/index.js
outputが./dist/main.jsである。

tscを挟まずにローダーに任せる場合、index.tsではなくindex.jsを
探しに行ってしまうのでwebpack.configの設定が必須である。
index.tsしか存在せず、tscを実行していないのであればwebpackはindex.jsを見つけられないからエラーとなる。
srcフォルダは必須だがdistは無ければ作ってくれる。
当然、index.htmlはwebpack出力のjsファイルを読みにいかなければならない。

webpack(ts-loader)

tscを挟まずにローダーに任せる場合のwebpack.config.js


module.exports = {
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
      },
    ],
  },
};

この場合、entryとなる
./src/index.ts
およびローダーの設定が必須である。

npx webpack

すれば、index.jsは生成されずに
デフォルト出力であるdist/main.jsが生成される。

ここまで

グローバルなりローカルなりに以下のパッケージがあり、

pixi.js
typescript
webpack
webpack-cli
ts-loader

package.json
tsconfig.json
webpack.config.js

などの設定項目がある。


この記事が気に入ったらサポートをしてみませんか?