JSでObject Poolを頻繁に利用するのでまとめた

はじめに

私はフロントエンジニアですが、無限カルーセル(*1)や大量のパーティクルなどの見た目部分を作ることが少なくありません。
言うまでもなく、無限カルーセルやパーティクルのオブジェクトを無限にnewしていたのでは、メモリに負荷をかけて、ユーザーに不快な思いを与えてしまいます。

Object Pool

そこで大量に作る予定のものは、あらかじめ作っておき使い回す、
Object Pool(オブジェクトプール)という仕組みを作っておきます。

イメージとしては、
箱(プール)の中にあらかじめ利用するものを入れておき、
使う時になったら箱から取り出し、
使い終わったら箱に戻してあげる
そんなシンプルな機構です。

Javascript

Object PoolをJavascriptで書いてみました。

export class ObjectPool {
    
    constructor(onRequire, onDestroy, initCount, progressCount) {
        this.onRequire = onRequire;
        this.onDestroy = onDestroy;
        this.initCount = initCount;
        this.progressCount = progressCount;
        this.index = 0;
        this.items = [];

        this.init();
    }

    init() {
        for (let i = 0; i < this.initCount; i += 1) {
            this.items.push(this.onRequire());
        }
        this.index = this.initCount;
    }

    clear() {
        for (let i = 0; i < this.items.length; i += 1) {
            this.onDestroy(this.items.shift());
        }
        this.items = [];
    }

    getItem() {
        if (this.index > 0) {
            return this.items[--this.index];
        }
        else {
            for (let i = 0; i < this.progressCount; i += 1) {
                this.items.unshift(this.onRequire());
            }
            this.index = this.progressCount;
            return this.getItem();
        }
    }

    returnItem(item) {
        this.items[this.index++] = item;
    }

    destroy() {
        this.onRequire = null;
        this.onDestroy = null;
        this.index = 0;
        this.items = null;
    }

    reduce() {
        for (let i = 0; i < this.index; i += 1) {
            this.onDestroy(this.items.shift());
        }
        this.index = 0;
    }
}

onRequireでは、箱(プール)に入れるアイテムをインスタンス化する処理を、 onDestroyでは、箱(プール)に戻すアイテムにする初期化処理のコールバック関数を渡します。
こうしておくことで、プールで利用するクラスに依存しないので汎用性が高まります。

initCountは最初に箱に入れるアイテムの数を、
progressCountは箱が空になった際に生み出すアイテムの数を指定します。
indexは利用できるアイテムのインデックスを位置を表していています。

*Typescriptだったらジェネリクス使えるんでもっといい感じに書ける

利用例

下記サイトの右から左に流れる無限カルーセル(1*)では、
あらかじめ箱のオブジェクトは、箱の数だけ生成しておき(initCount)、 もっとも左にある箱が画面から消えたらプールにアイテムを返し(ObjectPool.returnItem)、 もっとも右にある箱が箱一個分画面の内側に入ったらプールにアイテムをもらう(ObjectPool.getItem) といった仕組みでできています。 bodoge.blue-puddle.com

余談

意外にもこういった無限カルーセル(*1)は、 keyframesアニメーションで背景画像をリピートさせたり、 リピートできる位置に到達したら位置をリセットするといった仕組みでできているものが多いようでした。

私も最初のうちはそれでも良かったのですが、スピードを減速させたり、タッチスクロールに対応させなければいけないケースなどでは、
Object Poolを利用するものが汎用性が高く良いという結論に達しました。(というか教わりました)

おわり

大量に生成する系のUIや表現(テーブルビューやパーティクル)などに出会ったら、
迷うことなく利用するお便利クラスの紹介というか振り返りでした。

*1 無限カルーセルと私が呼んでいるものは、下記サイトで箱が動いている部分のUIを指しています。 bodoge.blue-puddle.com

ReactにデビューしてSPAアプリケーション作った感想みたいなもの

*こんなタイトルにしておいてなんですが、 アプリケーション自体はクライアントの社内秘企画でお見せできません。 難易度はTODOアプリ+α+αぐらいのものです。

昨今仮想Domいけいけの時代ですが、
そもそも利用する機会がなかったので、ノータッチでした。
しかし、最近の案件で利用したので学んだポイントや苦労した点をまとめておこうと思います。

感想

Reactはビューだけやってくれるライブラリだから理解するのに時間はかからない。 けどそれ以外のことはほとんど全て自分で頑張らなきゃいけない。。 UIKitの恩恵に預かってiPhoneアプリ作ってた僕にとって、 全てを自分で作らなければいけないのは中々骨が折れる作業でした。 UINavigationControllerやUITableViewっていいな・・・と。

実装期間が2週間とちょっとぐらいしかなかったので、
学習コストを考えるとかなり厳しかった。

React

たくさんの人が語ってくれているので参考文献はたくさんあって助かる。 Typescriptで書くと、エラーをいっぱい吐かれるので序盤ちょっと泣きそうになった。

JSX

いい感じに書けます

Redux

複数ページ+通信処理ありでViewのStateが肥大化することも目に見えていたので、 最初っからReact+Reduxで行くことにしました。 この記事はわかりやすかったです。 https://qiita.com/kiita312/items/49a1f03445b19cf407b7

React-thunk

reduxで非同期処理したいがために利用しました(redux-sagaは大袈裟だったのでパス)。 下の記事に影響を受けて、非同期処理のためだけのmiddleware不要じゃね?と思って途中で書き直した。 https://qiita.com/uryyyyyyy/items/d8bae6a7fca1c4732696

axios

Fetch API利用しようかと思ったけどメジャーそうなaxios(アクシオス)を利用。 とくに不満もなく利用できました。

CSS

スタイリングにはよさげな、Styled-Componentsを利用しました。 書き方に癖があるので慣れるのには時間を要しましたが、終盤はスムーズにかけるようになりました。

序盤に以下のエラーで怒られてハマってしまった。

It looks like you’ve wrapped styled() around your React component (Component), but the className prop is not being passed down to a child. No styles will be rendered unless className is composed within your React component.

このページの「Styling normal React components」の項を参考にすれば解決します。
classNameの付与がポイント。
https://www.styled-components.com/docs/advanced#styling-normal-react-components

Atomic Design

多くの人が悩んでる「Atoms?Molecules?どっちなの?」問題に関しては、
僕一人の実装だったのでスルー。
確かに複数人数だと線引きが難しいように思える。

今後

アニメーションなどはノータッチだったので実装できるようになりたい。
vuejsも触って、来年一月までにはSSRするサイト一個ぐらいつくりたい。

【読書】読んだら忘れない読書術

<この本を読む目的>

読書が行動に結びつかない・読んでも身に入ってこないという現状を変えるため

<心に残ったワード>

  • 本は汚く読め
  • 読書はスキマ時間にする
  • 寝る前の読書が効果的
  • 人間の脳は、「自分の能力よりも少し難しい課題」に取り組んでいるときに活性化する。
  • 面白そうと思って買った本はすぐ読め
  • 自分のステージに合った本を読む。殆どの人は上級者本を読んで挫折する
  • 自分が好きな分野から読み進めて読む癖をつける。そこから分野を広げていく
  • 投資の世界と同じように、短期・中期・長期のバランスで読書をする
  • 知識は最高の貯蓄である

<行動に移すこと>

  • 本を読んだらブログに感想を書く、もしくはアマゾンにレビューする
  • 寝る前に読書する習慣をもつ
  • マーカー・ボールペン片手に汚く読書する
  • ビジネス書籍に疲れたら、好きな分野で読書習慣をキープする
  • 購入する本のレベルは背伸びせず、自分のステージを意識して購入する

さくらのVPSはじめてみた(PHPとMariaDBのインストール)

Wordpressを最終的には動かしたいので、phpとdbをインストールします。 参考: https://knowledge.sakura.ad.jp/9006/

1.remi用の設定パッケージをインストール

PHP7.1はCentOSの公式リポジトリには含まれていないらしいので、
どこかのバーチャルアイドルみたいな名前の remi(レミ)というリポジトリから取得する必要があります。

su
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

これでremiリポジトリが使えるようになったそうです。実感はない。

2. PHP7.1をインストール

yum install --enablerepo=remi,remi-php71 php php-devel php-mbstring php-mysqlnd php-pdo php-gd

終わったらhttpdを再起動すると、phpが有効になる。

service restart httpd

3. php.iniを編集

ファイルアップロード上限が設定されているらしいので、
今後Wordpressの編集に影響が出ないように修正しておく

cd /etc
copy php.ini php.ini.old
vim php.ini

post_max_size = 128M
upload_max_filesize = 128M

systemctl restart httpd

4.MariaDBをインストール

お恥ずかしい話でMariaDBなんて初めて聞いた。
MySQLから派生したプロジェクトでMySQLとの互換性があるらしい。
その程度の理解しかしてないけど、今はWordpressが動くなら正直なんでも良い。

yum install mariadb-server

systemctl enable mariadb
systemctl start mariadb

5.初期設定

mysql_secure_installation

パスワードは、ユーザーパスワードと異なるものに設定する。 後はすべて y(Yes)で問題ない。

さくらのVPSはじめてみた(Apacheインストール)

前回でCentOS7をインストールしたので、今回はApacheをインストールしてみる https://knowledge.sakura.ad.jp/8541/

1. yumの更新

まずOSを更新する上で、

yum update -y 

とする

2. apacheのインストール

yum install httpd

3. http/httpsプロトコルの許可

CentOS7のデフォルト状態では、ファイアウォールが有効になっているので http/httpsでの通信が遮断されているらしい。へー。再起動も忘れずに。

firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --add-service=https --zone=public --permanent
systemctl restart firewalld

4. サーバー起動時にApacheも起動するように設定する

systemctl enable httpd

5. SFTPを使ってドキュメントルートにファイルをアップロードする

ドキュメントルートといえば「var/www/html」がデフォルトで設定されているらしい。
ここに簡素なファイルを、Transmitを使ってアップロードを試みるが、当然のごとくアップロード出来ない。
このフォルダに対して書き込み権限がないかららしい。

drwxr-xr-x 2 root root 6  421 03:11 html

どうやら現在のユーザーでは、「読み込みと実行」の権限しか与えられていないらしい。つれない。 今後インストール予定のWordpressからこのディレクトリに書き込みがあるので、 apacheユーザーをこのディレクトリの所有者に設定する。 グループには前回作ったwheelを設定したけど、これで良いのかしら・・・。

cd var/www/html
chown apache:wheel
chmod 755

drwxr-xr-x 2 apache wheel 6  421 03:11 html

無事アップロードできました。サイトも見れました。

さくらのVPSはじめてみた(OSインストール)

今更ながら、初めてさくらのVPSを借りてみた(というか借りてもらった)。
以下は参考サイトを見ながら進めた自分の所感をまとめただけなので、
詳細を知りたい方は以下のURLをご覧になることをオススメします。
参考: https://vps-news.sakura.ad.jp/tutorials/centos7-initial-settings/

1. OSのインストール

借りただけでは、まだでかい空っぽのPC借りているのと同じなので
当然OSをインストールする必要があります。
「各種設定 > OSインストール」を選択し、任意のOSをインストールします。(今回はCentOS7)

2. sshでログイン

OSにログインしてみる。
ssh root@<IPアドレス> と入力します。
OSをインストールするときに設定したパスワードもここで入力

3. ユーザーを作成

rootは全権限をもつアカウントなので危険なため、 rootでのログインは禁止して別途アカウントを作成する

useradd $userName
passwd $userName

不適切な(特定されやすい)パスワードは、この設定時点ではじかれるらしいです。 設定後、exitでrootアカウントをログアウトしてから、 作ったアカウントでログインします。

ssh userName@<IPアドレス> 

4. 公開鍵認証を使ったログイン設定

ssh 接続用の鍵のペア(秘密鍵id_rsaと公開鍵id_rsa.pub)を作成します すでに作ってある鍵がある場合は、作りなおさなくても良い。 scpコマンドでサーバーにアップする。そして、.sshフォルダの権限を変更しておこう。 scp ~/.ssh/id_rsa.pub root@aaa.bbb.ccc.ddd:/home/"サーバー側のユーザ名"/.ssh/id_rsa.pub

~/.ssh/authorized_keys に公開鍵を記述することで認証をする仕組みらしいので以下のようにする。 authorized_keysをディレクトリと勘違いして、ここで手が止まったのは恥ずかしい。

ssh username@aaa.bbb.ccc.ddd
chmod 700 .ssh
mv id_rsa.pub authorized_keys
chmod 600 authorized_keys 

ここまでやれば、パスワードは必要なしにログイン出来るはず。

ssh  username@aaa.bbb.ccc.ddd

5. sudo設定の有効化

さっき作成したユーザーを、wheelグループに追加する。 wheelグループとは、sudoコマンドでroot権限を実行するための特別なグループのこと。 rootでログインしてからusermodコマンドで変更する

ssh root@aaa.bbb.ccc.ddd
usermod -G wheel username

6.rootアカウントでのログインを許可しない&パスワードでのログインを許可しない

vim /etc/ssh/sshd_config

PermitRootLogin no
PasswordAuthentication no

7. .ssh/configに記述する

公開鍵認証にしていちいちパスワードを書かなくなったと言っても、毎回 ssh user@aaa.bbb.cc.dd
と打つのは億劫だ。

vi ~/.ssh/config 


Host uma
  port 22
  HostName aaa.bbb.cc.dd
  IdentityFile ~/.ssh/id_rsa
  User hoge
  IdentitiesOnly yes

これで、 ssh uma で入れて私はハッピーになれる。

複数スクロールコンテンツがあるときの、ユーザーによるスクロールの制御

タイトルがものすごいわかりづらいですね。 要は面白法人カヤックのサイトのこのページ(https://www.kayac.com/news)。

「タグ」をホバーしてスクロールすると分かるのですが、 下のメインコンテンツのスクロールは止まっていますね。 このような細かいところに気を使えているとイケてるサイトだなと思います(身内をほめているようでこそばゆい)

これは、bodyにoverflow:hiddenをかけてあげるだけで、実現できるようです(実証しました)。 簡単なのでコードは書きません。