1. yushimatenjin

    Posted

    yushimatenjin
Changes in title
+Gulpのプラグインを書いたらPlayCanvasでの開発がめちゃくちゃ便利になった。
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,147 @@
+@yushimatenjinです。[PlayCanvas](https://playcanvas.jp/)というゲームエンジンがあるのですが、そのソフトウェアのコードエディターに付属されているリンターが、JSHintという古いものでなおかつカスタマイズができなかったので、`gulp-playcanvas` `playcanvas-node` `playcanvas-cli`と3つのライブラリを作りました。gulpのpluginを作ったのでその知見の共有をさせていただきます。
+
+## 問題
+PlayCanvasを使う上で気になった点が付属のコードエディターのLintが古いということでした。
+
+![Image 37](https://user-images.githubusercontent.com/39250588/59757101-8a91ff00-927a-11e9-988f-1f1cd07c3a42.jpg)
+具体的には
+- constを使うと黄色くなる
+- セミコロンを入れないと、赤くエラーが出る
+この状況だったので自分のエディターを使って開発をしたい欲が出てきました。
+
+## 作ったプラグイン
+[gulp-playcanvas](https://github.com/yushimatenjin/gulp-playcanvas)
+
+
+npmのパッケージとして公開いたしましたので下記のコマンドでインストールできます。
+```bash
+yarn add gulp-playcanvas
+```
+
+ローカル側のgulpfile.jsは`watch`をして、トランスパイルしたものをPlayCanvasにREST APIを使用してアップロードしています。
+
+[examples - hot-reload](https://github.com/yushimatenjin/gulp-playcanvas/tree/master/examples/hot-reload)
+
+#### gulpfile.jsファイル
+```javascript
+const gulp = require("gulp");
+const playcanvas = require("gulp-playcanvas");
+const pcOptions = require("./playcanvas.json");
+const pug = require("gulp-pug");
+const sass = require("gulp-sass");
+
+gulp.task("pug", () => {
+ return gulp
+ .src(["src/**/*.pug", "!src/**/_*.pug"])
+ .pipe(pug())
+ .pipe(gulp.dest("dist/"))
+ .pipe(playcanvas(pcOptions));
+});
+
+gulp.task("js", () => {
+ return gulp
+ .src(["src/**/*.js", "!src/**/_*.js"])
+ .pipe(gulp.dest("dist/"))
+ .pipe(playcanvas(pcOptions));
+});
+
+gulp.task("sass", () => {
+ return gulp
+ .src("src/**/*.+(scss|sass)")
+ .pipe(sass())
+ .pipe(gulp.dest("dist/"))
+ .pipe(playcanvas(pcOptions));
+});
+
+gulp.task("watch", function() {
+ gulp.watch(["src/**/*.pug", "!src/**/_*.pug"], gulp.task("pug"));
+ gulp.watch(["src/**/*.js", "!src/**/_*.js"], gulp.task("js"));
+ gulp.watch("src/**/*.+(scss|sass)", gulp.task("sass"));
+});
+gulp.task("default", gulp.parallel("watch"));
+```
+
+パッケージのインストール後、`playcanvas.json`という設定ファイルを同じディレクトリに置き、`yarn gulp`コマンドで監視対象を`watch`しておきファイルの中身に変更があった場合に同期をする形で動きます。
+
+```playcanvas.json
+{
+ "accessToken": "",
+ "scenes": [],
+ "projectId": "",
+ "branchId": "",
+ "projectName": "",
+ "remotePath": ""
+}
+```
+
+## 動かした結果
+
+<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">6月に2Dゲームを作るというハンズオンをやるのですが、その資料を触ってたらHMR的な動きができたという動画です。 x4倍 <a href="https://t.co/vMHhrCkHkj">pic.twitter.com/vMHhrCkHkj</a></p>&mdash; はが (@Mxcn3) <a href="https://twitter.com/Mxcn3/status/1134057893286703106?ref_src=twsrc%5Etfw">2019年5月30日</a></blockquote>
+<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
+
+
+
+上の例ではタスクは4つの動きをします。
+
+### 1. 監視
+コードの変更をwatch ソースコードの変更を検知しタスクを実行
+
+```javascript
+gulp.task("watch", function() {
+ gulp.watch(["src/**/*.pug", "!src/**/_*.pug"], gulp.task("pug"));
+ gulp.watch(["src/**/*.js", "!src/**/_*.js"], gulp.task("js"));
+ gulp.watch("src/**/*.+(scss|sass)", gulp.task("sass"));
+});
+```
+この部分ですね、`pug`, `js`, `sass`に変更があった場合にそれぞれのタスクを実行します。
+
+### 2. ビルド & 3. アップロード
+PugやSassなどをHTML, CSSへ変換し、REST APIを使用しビルドしたコードをアップロードします
+
+```javascript
+const pug = require("gulp-pug");
+/*
+gulp.task("pug", () => {
+ return gulp
+ .src(["src/**/*.pug", "!src/**/_*.pug"])
+ .pipe(pug())
+ .pipe(gulp.dest("dist/"))
+------------自作のプラグインを実行------------------
+ .pipe(playcanvas(pcOptions));
+------------自作のプラグインを実行--------------------
+});
+*/
+```
+
+[https://github.com/yushimatenjin/gulp-playcanvas/blob/master/index.js#L1](gulp-playcanvas/index.js)
+Gulpのプラグインの中身はストリームで流れてくるファイルの情報を使用してアップロードしています。
+オプションの渡し方などは、[gulp-ftp](https://github.com/sindresorhus/gulp-ftp)を参考にしました。
+
+```javascript
+const PlayCanvas = require("playcanvas-node").default;
+const through = require("through2");
+const gutil = require("gulp-util");
+const path = require("path");
+
+module.exports = options =>
+ through.obj(function(file, enc, callback) {
+ if (file.isNull()) {
+ return callback(null, file);
+ }
+
+ if (file.isStream()) {
+ return cb(
+ new gutil.PluginError("gulp-playcanvas", "Streaming not supported")
+ );
+ }
+ const playcanvas = new PlayCanvas(options);
+ playcanvas.updateAssets(
+ options.remotePath,
+ path.basename(file.path),
+ file.path
+ );
+
+ return callback(null, file);
+ });
+```
+1行目で事前に`playcanvas-node`という自作のライブラリを読み込んでいるのですが、APIとのやり取りを書かなくなったのでシンプルに書くことができました。