20190811のNode.jsに関する記事は11件です。

MacBook AirにNode.jsをインストールしてみる。

目標

まっさらな MacBook AirにNode.jsをインストールしてみる。

Linux初心者です。諸般の事情によりMacを使うことになったので、とにかくVisual Studio Codeを動かす事のみに目標を定めて見たけれど、公式サイトからDownloadしてインストールしてみたらあっさりインストールできたので、目標をNode.jsのインストールに変更 (2019/08/11時点)

参考にさせて頂いたページ

macOSのターミナル(bash)のプロンプトを変えました。
【2019年5月版】Mac+nvm環境で brew install yarn
nvm + Node.js + npmのインストール
nvmを使ったNode.jsのインストール&バージョンアップ手順
touchコマンドについて詳しくまとめました 【Linuxコマンド集】

準備

  • OSのバージョン

    • macOS Mojave v10.14.6
  • Macメモ
     - Deleteボタンがないので、前方削除は fn+⇦(バックスペース)キー

NVMのインストール

まず、ダイレクトにNode.jsをインストールする事はオススメではないらしい
Node.jsの違ったバージョンをインストールしたり切り替えたりするツールを使うのが普通のようです
で、有名なのが以下
- NVM(Node Version Manager)
- Ndenv(Node.js environment)
- nodebrew
- Nodist(Windows専用)

この中でNVMを使う事にしました。
理由は、GitHubで最終更新日が一番今日に近かったから。

  • ターミナルを起動
    • Macなので画面下のアイコンの中からLanchpadをクリック
    • 「その他」というグループをクリック
    • "ターミナル"発見。クリック
    • ターミナル画面の初期表示は「(PC名)MacBook-Air:~ (ユーザー名)$」になっており、現在地がホームという事らしい
    • ここに戻りたい場合は「cd #」で戻ってこれる
  • 何も考えずにGitHubの公式にあるコマンドを実行
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
  • "curl"というのは、ファイルを送受信してくれるコマンドらしいので、"https://・・・"の場所から、NVMのバージョン0.34.0の場所にあるインストールコマンドが書かれている「install.sh」というシェルを持ってきて、bashで実行してね。。。 という意味だろう。たぶん。
  • 途中で"Command Line Tool for Xcode"のインストールを求められ(た気がする)るので、素直にインストール
  • これでNVMがインストールできているはずなので、以下のコマンドでバージョン確認
$ nvm --version
nvm: command not found
  • バージョンが表示されません。知らないコマンドだって言われます
  • Macの場合はひとひねり必要なようです。
  • Macのターミナルを起動した際には、自動で「/bin/bash」が起動するらしい
  • 本当は「.bashrc」というものも一緒に起動してほしいけどMacの場合は起動してないらしい
  • で、「.bashrc」は「.bash_profile」に読み込み設定をする事で自動で「/bin/bash」と一緒に起動してくれるらしい
  • 公式の説明を読んでいくと、「Note:On OS X 」の記述があります
  • お前のOSには「.bash_profile」ってファイルが無いはずだ。だから、俺の言うコマンドを実行してもう一度インストールコマンドを実行しな。。。という事みたい
  • てか、そもそも「/bin/bash」ってどこよ?
    • 探します
    • 私の知る数少ないコマンドの中のWindowsで言うところの「dir」
$ ls -al
  • ありません
  • これはあれだ、rootの方だきっと
  • 登ります
$ cd ../..
$ pwd
/
  • rootに来ました
$ ls -al
...
drwxr-xr-x@ 37 root       wheel    1184  8  8 01:33 bin
...
  • 「bin」発見。移動します
$ cd bin
$ ls -al
...
-r-xr-xr-x   1 root  wheel   618416  5 25 15:25 bash
...
  • 「bash」発見。移動します
$ cd bash
-bash: cd: bash: Not a directory
  • 「bash」はディレクトリじゃないと怒られました
  • という事は本体です。。。きっと
  • つまり
(ルート)/bin/bash
-r-xr-xr-x   1 root  wheel   618416  5 25 15:25 bash
  • 続いて、てか、そもそも「.bashrc」ってどこよ?
  • 上記『参考にさせて頂いたページ』の最初の記事で場所を教えてくれてました

macOSのターミナル(bash)のプロンプトを変えました。

  • 「/etc」。。。きっとルートの下です
  • ここに来てルートへの移動方法を覚えました
$ cd /
  • 便利です
$ cd etc
$ ls -al
  • いました。「.bashrc」発見です
(ルート)/etc/bashrc
-r--r--r--   1 root  wheel     265  2 23 12:03 bashrc
  • ん? んんんん? 先頭に「.」無いよ。。。
  • 。。。見なかった事にします
  • 確かにこれまで見た場所には「.bash_profile」ってファイルはなかったです
  • なので公式の記述にしたがって作ります
  • ちょっと待って、今私どこにいる?
    • (ルート)/etc にいます
  • 怖いのでホームに戻ります
$ cd #

$ touch ~/.bash_profile
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
  • 曰く「touchはファイルのタイムスタンプを変更するコマンドだ。 また、存在しないファイル名を指定することで、内容の入っていないファイルを新規作成する機能も持っている。」
  • 「.bash_profile」っていう空ファイルを作ってインストールしなおすと、自動で中身を書いてくれる。。。という事のようです
  • 中身書かれてるし
$ cat .bash_profile

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
  • そしてNVMのバージョン確認
$ nvm --version

nvm: command not found
  • orz.......
  • あれだ。再起動。ターミナルを再起動
$ nvm --version
0.34.0
  • NVMインストール完了です

Node.jsインストール

  • Node.jsをインストールします。
  • LTS(Long Term Support)という長期サポートがあり推奨とれているバージョンを入れます

https://nodejs.org/ja/download/

$  nvm install --lts
...
...
Now using node v10.16.2 (npm v6.9.0)
Creating default alias: default -> lts/* (-> v10.16.2)
  • バージョン10.16.2がインストールされたようです。
  • デフォルト設定もしてくれてます。
  • 念の為バージョン確認
$ node --version
v10.16.2

おわりに

Node.jsをインストールのはずが、NVMインストールの方が万倍大変でした。

Windowsユーザーのみなさんの参考になればと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LINE Thingsで歩数計Botを作ろう

はじめに

どこかでハンズオンをするために書いた記事です。内容は以下のような感じです。

  1. m5stackで歩数計を作る
  2. LINE Thingsの自動通信を使って歩数計とLINEをBluetooth通信させる
  3. 一定歩数ごとにLINE通知するシステムを構築

図で表すとこんな感じです。各番号が上記で説明した内容に対応しています。

歩数計.jpg

このハンズオンで用いる開発ツール・環境は以下です

それぞれのツールについての解説は今回は省略します。説明は操作手順にのみ重点を置きます。
また、今回用いるソースコードはgithubで公開されています。以下のコマンドで入手してください。

git clone https://github.com/ufoo68/linethings-pedometer-hands-on.git

参考にした記事

M5Stackで歩数計を作る

M5StackはM5Stackという会社が開発したマイコンボードです。中にはespressifという会社のESP32というWiFi/Bluetooth搭載のチップが内蔵されています。M5Stackのいいところはハンダ付けなしでモジュールを拡張することができるところです。その名前の通り、モジュールを下に積み重ねる(スタックする)ことでデバイスを拡張させてきます。今回はM5Stack grayに予め搭載されているMPU9250という9軸(加速度・ジャイロ・地磁気)のモーションセンサーを用います。

まずは環境のセットアップ

M5Stackのソフトウェアを開発する方法は何通りかありますが、ここではArduino IDEを使います。ここのリンク先からダウンロードを行ってください。
インストールが完了したら次にESP32のボード開発用のライブラリをインストールしていきます。まずは下の一行をコピーしてください。
https://dl.espressif.com/dl/package_esp32_index.json
コピーしたらCtrl + ,で環境設定(Preference)を開いて下図のような赤枠に囲ってあるところにペーストしてください。
2019-08-11 (2).png
そしたらそのままOKを押して戻ります。次にメニューバーからツール->ボード->ボードマネージャーの順番で選択していき下図のような画面を開きます。そのとき上の入力欄にESP32と打ったら一つだけヒットするものが出てくるのでインストールしてしまいます。
2019-08-11 (3).png
インストールが完了したら次にM5Stack用のライブラリをインストールします。Ctrl + Shift + iで下図のような画面を起動します。同様に入力欄をM5Stackでソートして赤枠で囲っているところを探してインストールしてください。
2019-08-11 (4).png
これでM5Stack開発用の環境のセットアップは完了です。また、M5Stackにコード(Arduinoではスケッチという)を書き込むときは下のような感じでボードの設定をしてください。多分細かいパラメーターの設定はデフォルトで問題ないと思います。
2019-08-11 (7).png
また、Arduinoの開発はもちろんこのArduino IDEで行ってもいいとは思いますが、vscodeで開発を行うためのExtensionsがあります。恐らく上記のどこかでリンク先を示してあります。方法はこちらの記事などを参考にしてください。

歩数計のライブラリを使えるようにする

次にM5Stackで歩数計を作ります。まず、歩数を図る方法は主に2つの方式に大別されます1
1. 電気スイッチが開閉し振動回数を記録する振り子方式
2. 加速度センサー方式

前者の1.が所謂昔の万歩計に使われているような方式ですが、この方法では万歩計をただ上下に降るだけでも「歩き」認識してしまいます(多分昔ポケットピカチュウを持っていた方ならよく知っているはず)。「歩き」にはそれ特有のモーションが存在し、それをモーションセンサーで検出する方法を用いることでより正確に「歩き」を検出することができます。この場合は後者の2.の方式になります。M5Stackには折角9軸のモーションセンサーが搭載されているのでそれを使わない手はありません。

上記でも述べましたが、M5StackにはMPU9250が搭載されています。MPU9250用のライブラリは先程インストールしたM5Stack用のライブラリに含まれていますが、センサーからの生データから「歩き」のモーションを計算するアルゴリズムをゼロから考えるのは面倒なのでSparkFunのMPU9250用ライブラリを使って歩行検出のライブラリ(Pedometer)を使おうと思います。直接ソースコードをArduinoのライブラリに追加する方法として、まずは先程のgithubのレポジトリをZipでダウンロードします。
2019-08-11 (8).png
次にArduino IDEのメニューバーからスケッチ->ライブラリをインクルード->.ZIP形式のライブラリをインストールを選びます。そして先程インストールした.zipフォルダを選択します。
2019-08-11 (9).png
ここでセットアップは完了。と言いたいところですが、このライブラリはM5Stack専用に作られていないので少し中のファイルをイジる必要があります。先程インストールされたライブラリはArduino/libralies/SparkFun_MPU-9250-DMP_Arduino_Library-masterに格納されていると思うので一旦そこまでフォルダを移動します。ArduinoというフォルダはArduino IDEをインストールしたときに自動的にDocumentsに作られていると思います。
まず、library.propertiesを開いて以下のように書きかえます(といっても一番下の行をarchitectures=*に変えただけです。)。

library.properties
name=SparkFun MPU-9250 Digital Motion Processing (DMP) Arduino Library
version=1.0.0
author=SparkFun Electronics
maintainer=SparkFun Electronics <TechSupport@SparkFun.com>
sentence=Driver for InvenSense's MPU-9250 9-DOF IMU (3-axis gyroscope, 3-axis accelerometer & 3-axis magnetometer)
paragraph=The <a href="https://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/">MPU-9250</a> is a system-in-package featuring acceleration full-scales of ±2 / ±4 / ±8 / ±16 (g), rotational full-scales of ±250 / ±500 / ±1000 / ±2000 (°/sec) and a magnetic field full scale of ±4800 µT. The MPU-9250 includes an I<sup>2</sup>C serial bus interface that supports speeds up to 400 kHz.
category=Sensors
url=https://github.com/sparkfun/MPU-9250_Breakout
architectures=*

次に/src/util/inv_mpu.cを開いて以下のように書き換えます(#define min(X,Y) ((X) < (Y) ? (X) : (Y))を#defineとかしているところに追加)。

/src/util/inv_mpu.c(39-49行目)
#include <Arduino.h>
+ #define min(X,Y) ((X) < (Y) ? (X) : (Y))
#define MPU9250
#include "arduino_mpu9250_i2c.h"
#include "arduino_mpu9250_clk.h"
#define i2c_write(a, b, c, d) arduino_i2c_write(a, b, c, d)
#define i2c_read(a, b, c, d)  arduino_i2c_read(a, b, c, d)
#define delay_ms  arduino_delay_ms
#define get_ms    arduino_get_clock_ms
#define log_i     _MLPrintLog
#define log_e     _MLPrintLog 

これでライブラリのセットアップは完了です。

スケッチを書き込む

M5Stack用のスケッチはハンズオン用のサンプルコードのm5stack-linethings/m5stack-linethings.ionに入っています。このスケッチの内容をこのまま書き込んでしまえば歩数がM5Stackの画面に表示されるシステムが一旦完成します。この歩数計に関係する部分のスケッチは以下です。

m5stack-linethings.ino(74-82行目)
stepCount = imu.dmpGetPedometerSteps();
stepTime = imu.dmpGetPedometerTime();
if (stepCount != lastStepCount) {
  lastStepCount = stepCount;
  M5.lcd.clear();
  M5.Lcd.setCursor(0,0);
  M5.lcd.print("Walked " + String(stepCount) + " steps");
  M5.lcd.print(" (" + String((float)stepTime / 1000.0) + " s)");
  ...
}

ここでは、歩数が増える度に表示するステップ数を変更しています。

LINE Thingsと連携する

LINE Thingsを利用するためには専用のLINE Botを作成する必要があります。まずはLINE Developersにログインします。ログインが完了したら、右上のアイコンをクリックして「プロバイダー新規作成」を選択します。
2019-08-11 (10).png
次にチャンネルを新規作成します。Messaging APIを選択します。
2019-08-15.png
とりあえず適当な名前をつけたらLIFFのタブを選択して「追加」します。このとき、重要となるのは「オプション」のBLE featureです。「ON」を選択してください。
2019-08-15 (1).png
これでLINE Thingsと連携ができるLINE Botができました。また、アクセストークンチャンネルシークレットという2つのキーが今後必要になります。チャンネル基本設定のタブから「Channel Secret」と「アクセストークン(ロングターム)」を探してください。アクセストークンは最初何も発行されていないと思うので「再発行」をしてください。

シナリオを登録する

今回はLINE Thingsの自動通信機能を用います。この機能を用いることでデバイス -> INE Botへの通信が可能になります。要はデバイスを用いたPush Messageができるということです2
自動通信を有効にするにはAPIを用いてシナリオを登録する必要があります。CURLやPostmanでAPIを直接叩く方法でも構いませんが、ここは楽をするために@n0bisukeさんの専用ツールを用いて開発をシナリオの登録を行いましょう。
まずはリンク先←にアクセスします。そしたら「Setting」のタブを選択して「アクセストークン」の入力欄にそのままキー値をペーストして「保存」をクリックします。
2019-08-15 (2).png
次に「Create Product」のタブを選択してLIFFアプリを選択します。登録したLIFF名を選んでください。そしたら適当な「トライアルプロダクトの名前」を入力して「作成」をクリックします。そのとき下に表示された「サービスUUID」をどこかにメモしておきます。
2019-08-17 (1).png
最後に「Create Senario」のタブに移動して先程作成したトライアルプロダクトの名前を選択します。設定は下図のような感じで「シナリオセットの登録/更新」をクリックします。
2019-08-17 (2).png
これでシナリオの登録は完了です。そしたら先程メモしたサービスUUIDを使います。M5Stackのスケッチに戻って12行目あたりのdefineの文字列をサービスUUIDに変更して再び書き込みます。

m5stack-linethings.ino(12行目)
#define USER_SERVICE_UUID "Change your service uuid"

また、LINEアプリにLINE Thingsを有効化させるためには以下のQRコードを読む必要があります。
qr_code-311f3503.png

LINE Botをつくる

LINE Thingsの自動通信との連携のためのLINE Botを作成します。以下のコマンドを実行してください。

cd linethings-pedometer-hands-on
npm i

次に同じlinethings-pedometer-hands-onディレクトリ内に.envというファイルを作成します。

.env
CHANNEL_SECRET="チャンネルシークレット"
ACCESS_TOKEN="アクセストークン"
PORT=3000

CHANNEL_SECRETACCESS_TOKENには前回の項目でメモしたチャンネルシークレットアクセストークンを入力します。

これでサンプルコードを実行するための環境構築は完了しました。しかしMessaging API用のサーバを立てるためにはhttpsで始まるURLが必要になります。今回はngrokというツールを用いてhttpsのURLを取得します。まずは以下のコマンドを実行してngrokをインストールします。

npm i -g ngrok

インストールしたら同じカレントディレクトリのターミナルをもう一つ立ち上げて以下のコマンドを実行します。

ngrok http 3000

そしたら以下のように画面表示されるので、以下のhttps://で始まっているURLをコピーします。

ngrok by @inconshreveable                                                                                                                    (Ctrl+C to quit)
Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.3.34
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://xxxx.ngrok.io -> http://localhost:3000
Forwarding                    https://xxxx.ngrok.io -> http://localhost:3000

そしたらもう一方のターミナルで以下のコマンドを実行してサーバーを立ち上げます。

node index

後は先程コピーしたURLを「Webhook URL」に登録します。前回の項目で作成したLINE Bot用のチャンネル基本設定に戻ります。
「Webhook送信」を「利用する」に選択して、「Webhook URL」にコピーしたURL+/webhookを登録します。
2019-08-17 (3).png

ペアリングしよう

LINE Thingsを有効にすると以下のような項目がLINEアプリの「設定」ページに追加されています。
iOS の画像 (7).png
「LINE Things」のページは以下のようになっています。先程登録したデバイスが「連携可能なデバイス」として表示されるのでタップしてペアリングを開始してください。LINE Things登録から連携までには少し時間がかかる場合があります。なかなか現れない場合はスマホの再起動を試すのも一つの手です。
iOS の画像 (6).png
あとは実際にポケットにM5Stackを入れた状態で歩いてみて動作を確かめてみてください。しかしUSBケーブルで給電した状態で試すのは難しいと思うのでM5Stack用電池モジュールを買うことをオススメします。

さいごに

今回はM5Stackで試しましたが、最近はM5StickCが出たみたいなのでそちらの実装バージョンも別途記事を書こうと思います。こちらの方はまたモーションセンサーのICが異なるみたいなのでスケッチも書き換える必要があるようですね。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

socket.ioでランダムマッチングチャットサービスを作ってみた

こんばんは、個人開発者の @ryuuga_hです。
今までLAMPでの開発ばかりしてきましたが、(去年はunity+photonでネトゲを作った)今回はnode.jsを使ったサービスを作ってみました。
実際は2年前に原型は完成していたのですが、知名度が0で誰ともマッチできないことが分かっていましたので、お蔵入りしていました。
node.jsとsocket.ioの知識が得られていたので満足していましたが、最近ツイッターを開始したので何かフォロワーさんに見せれるものを思い、思い出したかのようにdropboxから探し出し、一ヶ月程度修繕しリリースしました。
誰かに確実に見てもらえると分かっていると気合が入りますね。

今回は折角なので、プログラム(サーバー構築を含む)のハマったところと、デザインについて書いておきたいと思います。

作ったもの

チャットガチャ
https://chatgacha.com/

SS 2.png

匿名でランダムな人とマッチングしてチャットができるサービスです。
シンプルに作ることとシンプル過ぎないことに注意しました。
既存のランダムチャットサービスにはない機能として、ブラックリスト機能があります。
これを実装するのが結構骨がありハマりやすかったです。

技術編 使っているもの

  • nginx
  • node.js
  • express
  • socket.io
  • pug
  • Letsencrypt
  • さくらVPS
  • vsftpd

Let's Encrypt(SSL/https化)

強いて言えば 、サーバー構築をする前に一番ネックになりそうだなと思っていたことは「Letsencrypt」でのSSL化でした。
普段は、VPSを使わずにレンタルサーバーを使ってクリック1つで実装してきたので、ちょっとビビっていましたが、さくらVPSにはスタートアップスクリプトというものがあり、クリックするだけで実装することができました。
https://vps-news.sakura.ad.jp/tutorials/vps-letsencrypt/

同時にnginxもインストールされたのでかなり楽ができました。

vsftpdもついでに暗号化

FTPでファイルを送受信するためにvsftpdを使っています。
「vsftpd 暗号化」で雑に検索していたのですが、検索している間に「Let's Encrypt」が流用できるのではないかと思って、
「vsftpd Let's Encrypt」で検索することによって簡単に暗号化することに成功しました。
何で検索するかによって作業時間が大幅に減ったりするのが面白いところですね。
※セキュリティをガチでやっている方は真似しないほうがいいかもしれません。

node.jsのポート番号を隠すためにnginxを使う

ローカルで開発していたとき、スマホの実機で確認するために「192.168.x.x:3000」的な感じで開発をしていました。
実働サーバーではポート番号を隠したいので、自然とnginxを使うことにしました。
また、ここでもSSL化の話になるのですが、node.js側でSSLの対応はしなくて良いということがわかりました。
さくらVPSのスタートアップポイントスクリプトでSSL化した際にnginxをインストールしているので、nginxの設定はサクサク進みました。

IPアドレスの取得で大きくハマる

ローカルでnginxを使わずに開発していました。
実際nginxを使うことになり、IPアドレス取得問題にぶち当たって時間を取られました。
結論のコードだけを書いておきます。

javascript.js
//動く ○
io.on('connection', function(socket){
    var ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress;
}

socket.ioでIPを取得したいのに関わらず、node.js側で(?)IPを取得しようと思って検索していたことが問題でした。

javascript.js
//こういうので頑張っていた ☓
var os = require('os');
console.log(os.networkInterfaces());

また、nginx側の設定でもクライアントのIPアドレスをnode.jsに送るようにしなければなりません。
こっちは記事が多いので割合します。

pugはそこそこ便利

if文が使える。
これはTOPページのコード。TOPのときだけタイトルだけにしたかった。
分からないとタイトルは 「ホーム / チャットガチャ」になっていたと思います。

_header.pug
if `${page.url}` !== ''
  title= `${page.pagetitle} / ${title}`
else
  title= `${title}`

デザインについて

デザインについては素人。個人開発者としては一番ネックかもしれない。
いつもはBootstrapを使って騙し騙し作っていたが今回は使わなかった。
基本的には、サルカワさんを参考にした。https://saruwakakun.com/
また、背景には、subtlepatternsの画像を使った。 https://www.toptal.com/designers/subtlepatterns/
背景やフォントを変更するだけでかなり見栄えがよくなったので、拘るといいかもしれない。
細かいアイコンを使おうと思っていたが、その割には重たくなるので途中で使うのをやめた。

チャットサービスなので、優しい感じにしたかった。
色は青か緑がいいかと思った。基本、角丸のデザインにした。

main.css
.box{
   box-shadow: 0 0 8px gray;
}

こんな感じで中央のdivに影をつけてみたら、とても良くなっていったと思います。

普段からよく使うツール

PNG圧縮: https://compresspng.com/ja/
今の時代表示速度に注目が集まっている。少しでも画像を軽くしたい。ということで使っています。
TOPページの表示速度をディベロッパーツールで調べたところ「213sm」でした。結構表示速度は拘っています。
さくらVPSも気休めですが、東京のデータセンターを選択しています。

アイコン一式をつくる: https://iconifier.net/
ペイントツールなどでアイコンを作ったあといろいろなアイコンのサイズを生成してくれます。
いつも使っています。

感想 まとめ

2年前に作ったサービスなのであまり覚えていませんが、印象に残っていることはデータベースを使わずにランダムマッチングができるということです。
普段からLAMPでサービスを作ってきましたのでいろいろ刺激がありました。
localstorageは結構便利で、ブラックリストの保存やマイページの情報保存に使っています。
また、お問い合わせはツイッターのみにすることによってメールサーバーも立てていません。
個人開発としては楽ができるところはトコトンしたほうがいいでしょうね。

herokuで公開する予定だったんですが、VPSが使えるのでこっちにしました。
今では満足しています。

純粋に知らない人と話すというのは刺激が強い方だと思っていますので、是非使って見てください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

チャットガチャを作ってみた

こんばんは、個人開発者の @ryuuga_hです。
今までLAMPでの開発ばかりしてきましたが、(去年はunity+photonでネトゲを作った)今回はnode.jsを使ったサービスを作ってみました。
実際は2年前に原型は完成していたのですが、知名度が0で誰ともマッチできないことが分かっていましたので、お蔵入りしていました。
node.jsとsocket.ioの知識が得られていたので満足していましたが、最近ツイッターを開始したので何かフォロワーさんに見せれるものを思い、思い出したかのようにdropboxから探し出し、一ヶ月程度修繕しリリースしました。
誰かに確実に見てもらえると分かっていると気合が入りますね。

今回は折角なので、プログラム(サーバー構築を含む)のハマったところと、デザインについて書いておきたいと思います。

作ったもの

チャットガチャ
https://chatgacha.com/

SS 2.png

匿名でランダムな人とマッチングしてチャットができるサービスです。
シンプルに作ることとシンプル過ぎないことに注意しました。
既存のランダムチャットサービスにはない機能として、ブラックリスト機能があります。
これを実装するのが結構骨がありハマりやすかったです。

技術編 使っているもの

  • nginx
  • node.js
  • express
  • socket.io
  • pug
  • Letsencrypt
  • さくらVPS
  • vsftpd

Let's Encrypt(SSL/https化)

強いて言えば 、サーバー構築をする前に一番ネックになりそうだなと思っていたことは「Letsencrypt」でのSSL化でした。
普段は、VPSを使わずにレンタルサーバーを使ってクリック1つで実装してきたので、ちょっとビビっていましたが、さくらVPSにはスタートアップスクリプトというものがあり、クリックするだけで実装することができました。
https://vps-news.sakura.ad.jp/tutorials/vps-letsencrypt/

同時にnginxもインストールされたのでかなり楽ができました。

vsftpdもついでに暗号化

FTPでファイルを送受信するためにvsftpdを使っています。
「vsftpd 暗号化」で雑に検索していたのですが、検索している間に「Let's Encrypt」が流用できるのではないかと思って、
「vsftpd Let's Encrypt」で検索することによって簡単に暗号化することに成功しました。
何で検索するかによって作業時間が大幅に減ったりするのが面白いところですね。
※セキュリティをガチでやっている方は真似しないほうがいいかもしれません。

node.jsのポート番号を隠すためにnginxを使う

ローカルで開発していたとき、スマホの実機で確認するために「192.168.x.x:3000」的な感じで開発をしていました。
実働サーバーではポート番号を隠したいので、自然とnginxを使うことにしました。
また、ここでもSSL化の話になるのですが、node.js側でSSLの対応はしなくて良いということがわかりました。
さくらVPSのスタートアップポイントスクリプトでSSL化した際にnginxをインストールしているので、nginxの設定はサクサク進みました。

IPアドレスの取得で大きくハマる

ローカルでnginxを使わずに開発していました。
実際nginxを使うことになり、IPアドレス取得問題にぶち当たって時間を取られました。
結論のコードだけを書いておきます。

javascript.js
//動く ○
io.on('connection', function(socket){
    var ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress;
}

socket.ioでIPを取得したいのに関わらず、node.js側で(?)IPを取得しようと思って検索していたことが問題でした。

javascript.js
//こういうので頑張っていた ☓
var os = require('os');
console.log(os.networkInterfaces());

また、nginx側の設定でもクライアントのIPアドレスをnode.jsに送るようにしなければなりません。
こっちは記事が多いので割合します。

pugはそこそこ便利

if文が使える。
これはTOPページのコード。TOPのときだけタイトルだけにしたかった。
分からないとタイトルは 「ホーム / チャットガチャ」になっていたと思います。

_header.pug
if `${page.url}` !== ''
  title= `${page.pagetitle} / ${title}`
else
  title= `${title}`

デザインについて

デザインについては素人。個人開発者としては一番ネックかもしれない。
いつもはBootstrapを使って騙し騙し作っていたが今回は使わなかった。
基本的には、サルカワさんを参考にした。https://saruwakakun.com/
また、背景には、subtlepatternsの画像を使った。 https://www.toptal.com/designers/subtlepatterns/
背景やフォントを変更するだけでかなり見栄えがよくなったので、拘るといいかもしれない。
細かいアイコンを使おうと思っていたが、その割には重たくなるので途中で使うのをやめた。

チャットサービスなので、優しい感じにしたかった。
色は青か緑がいいかと思った。基本、角丸のデザインにした。

main.css
.box{
   box-shadow: 0 0 8px gray;
}

こんな感じで中央のdivに影をつけてみたら、とても良くなっていったと思います。

普段からよく使うツール

PNG圧縮: https://compresspng.com/ja/
今の時代表示速度に注目が集まっている。少しでも画像を軽くしたい。ということで使っています。
TOPページの表示速度をディベロッパーツールで調べたところ「213sm」でした。結構表示速度は拘っています。
さくらVPSも気休めですが、東京のデータセンターを選択しています。

アイコン一式をつくる: https://iconifier.net/
ペイントツールなどでアイコンを作ったあといろいろなアイコンのサイズを生成してくれます。
いつも使っています。

感想 まとめ

2年前に作ったサービスなのであまり覚えていませんが、印象に残っていることはデータベースを使わずにランダムマッチングができるということです。
普段からLAMPでサービスを作ってきましたのでいろいろ刺激がありました。
localstorageは結構便利で、ブラックリストの保存やマイページの情報保存に使っています。
また、お問い合わせはツイッターのみにすることによってメールサーバーも立てていません。
個人開発としては楽ができるところはトコトンしたほうがいいでしょうね。

herokuで公開する予定だったんですが、VPSが使えるのでこっちにしました。
今では満足しています。

純粋に知らない人と話すというのは刺激が強い方だと思っていますので、是非使って見てください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

チャットガチャの技術側の話

今回はnode.jsを使ったサービスを作ってみました。
実際は2年前に原型は完成していたのですが、知名度が0で誰ともマッチできないことが分かっていましたので、お蔵入りしていました。
node.jsとsocket.ioの知識が得られていたので満足していましたが、最近ツイッターを開始したので何かフォロワーさんに見せれるものを思い、思い出したかのようにdropboxから探し出し、一ヶ月程度修繕しリリースしました。

作ったもの

チャットガチャ
https://chatgacha.com/

SS 2.png

匿名でランダムな人とマッチングしてチャットができるサービスです。
シンプルに作ることとシンプル過ぎないことに注意しました。
既存のランダムチャットサービスにはない機能として、ブラックリスト機能があります。
これを実装するのが結構骨がありハマりやすかったです。

技術編 使っているもの

  • nginx
  • node.js
  • express
  • socket.io
  • pug
  • Letsencrypt
  • さくらVPS
  • vsftpd

Let's Encrypt(SSL/https化)

強いて言えば 、サーバー構築をする前に一番ネックになりそうだなと思っていたことは「Letsencrypt」でのSSL化でした。
普段は、VPSを使わずにレンタルサーバーを使ってクリック1つで実装してきたので、ちょっとビビっていましたが、さくらVPSにはスタートアップスクリプトというものがあり、クリックするだけで実装することができました。
https://vps-news.sakura.ad.jp/tutorials/vps-letsencrypt/

同時にnginxもインストールされたのでかなり楽ができました。

vsftpdもついでに暗号化

FTPでファイルを送受信するためにvsftpdを使っています。
「vsftpd 暗号化」で雑に検索していたのですが、検索している間に「Let's Encrypt」が流用できるのではないかと思って、
「vsftpd Let's Encrypt」で検索することによって簡単に暗号化することに成功しました。
何で検索するかによって作業時間が大幅に減ったりするのが面白いところですね。
※セキュリティをガチでやっている方は真似しないほうがいいかもしれません。

node.jsのポート番号を隠すためにnginxを使う

ローカルで開発していたとき、スマホの実機で確認するために「192.168.x.x:3000」的な感じで開発をしていました。
実働サーバーではポート番号を隠したいので、自然とnginxを使うことにしました。
また、ここでもSSL化の話になるのですが、node.js側でSSLの対応はしなくて良いということがわかりました。
さくらVPSのスタートアップポイントスクリプトでSSL化した際にnginxをインストールしているので、nginxの設定はサクサク進みました。

IPアドレスの取得で大きくハマる

ローカルでnginxを使わずに開発していました。
実際nginxを使うことになり、IPアドレス取得問題にぶち当たって時間を取られました。
結論のコードだけを書いておきます。

javascript.js
//動く ○
io.on('connection', function(socket){
    var ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress;
}

socket.ioでIPを取得したいのに関わらず、node.js側で(?)IPを取得しようと思って検索していたことが問題でした。

javascript.js
//こういうので頑張っていた ☓
var os = require('os');
console.log(os.networkInterfaces());

また、nginx側の設定でもクライアントのIPアドレスをnode.jsに送るようにしなければなりません。
こっちは記事が多いので割合します。

pugはそこそこ便利

if文が使える。
これはTOPページのコード。TOPのときだけタイトルだけにしたかった。
分からないとタイトルは 「ホーム / チャットガチャ」になっていたと思います。

_header.pug
if `${page.url}` !== ''
  title= `${page.pagetitle} / ${title}`
else
  title= `${title}`

デザインについて

デザインについては素人。個人開発者としては一番ネックかもしれない。
いつもはBootstrapを使って騙し騙し作っていたが今回は使わなかった。
基本的には、サルカワさんを参考にした。https://saruwakakun.com/
また、背景には、subtlepatternsの画像を使った。 https://www.toptal.com/designers/subtlepatterns/
背景やフォントを変更するだけでかなり見栄えがよくなったので、拘るといいかもしれない。
細かいアイコンを使おうと思っていたが、その割には重たくなるので途中で使うのをやめた。

チャットサービスなので、優しい感じにしたかった。
色は青か緑がいいかと思った。基本、角丸のデザインにした。

main.css
.box{
   box-shadow: 0 0 8px gray;
}

こんな感じで中央のdivに影をつけてみたら、とても良くなっていったと思います。

普段からよく使うツール

PNG圧縮: https://compresspng.com/ja/
今の時代表示速度に注目が集まっている。少しでも画像を軽くしたい。ということで使っています。
TOPページの表示速度をディベロッパーツールで調べたところ「213sm」でした。結構表示速度は拘っています。
さくらVPSも気休めですが、東京のデータセンターを選択しています。

アイコン一式をつくる: https://iconifier.net/
ペイントツールなどでアイコンを作ったあといろいろなアイコンのサイズを生成してくれます。
いつも使っています。

感想 まとめ

技術以外の話 https://crieit.net/posts/dd9cbaa9f9828546dc1b3c1c0c0989e1

2年前に作ったサービスなのであまり覚えていませんが、印象に残っていることはデータベースを使わずにランダムマッチングができるということです。
普段からLAMPでサービスを作ってきましたのでいろいろ刺激がありました。
localstorageは結構便利で、ブラックリストの保存やマイページの情報保存に使っています。
また、お問い合わせはツイッターのみにすることによってメールサーバーも立てていません。
個人開発としては楽ができるところはトコトンしたほうがいいでしょうね。

herokuで公開する予定だったんですが、VPSが使えるのでこっちにしました。
今では満足しています。

純粋に知らない人と話すというのは刺激が強い方だと思っていますので、是非使って見てください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.gitignoreでgitにコミットしないディレクトリを管理する【node_modules】

node_modulesなどはgitにcommit、pushする必要はない

node.jsの開発において、

npm install --save [library name]

でインストールしたバッケージは、package.jsonのdependenciesにて依存関係が定義されている。

{
  "name": "project-name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cheerio": "^1.0.0-rc.3",
    "puppeteer": "^1.19.0",
    "request": "^2.88.0",
    "request-promise": "^4.2.4"
  }
}

npm installを実行すれば、package.jsonの依存関係を参照して必要なライブラリがダウンロードされる。
したがって、ライブラリの実体が保存されているnode_modulesを含める必要がない。
プロジェクトの容量が無駄に大きくなってしまうので、.gitignoreファイルでcommit対象から外して管理するのがいい。

.gitignoreファイルの作成

.gitignoreの作成は、通常のファイル作成と同様に

touch .gitignore

で作られる。
ファイルは、ワーキングディレクトリ直下(プロジェクトの最上位のディレクトリ)に作成する。
.gitディレクトリに置くと読み込まれないので注意。

.gitignoreの記述方法

下記のように記述できる。

# ディレクトリを指定する場合
node_modules/

# ファイルのパターン一致でコンパイルなどで生成したファイルを指定する場合
*.com
*.class
*.dll
*.exe
*.o
*.so

ディレクトリの場合はディレクトリ/で指定でき、
ファイルの場合は正規表現で指定できる。

設定後、実際にcommitしてみて確認

.gitignoreを設定後、commitすると

$ git add *
The following paths are ignored by one of your .gitignore files:
node_modules

のように除外されたパスが表示される。
意図通り除外されているか確認出来る。

参考書籍

GitHub実践入門
弊社での新卒エンジニア向け課題図書になった。
必要なコマンドを随時調べるのも良いけど、最初に一通り理解して置くとスムーズにいく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】ビルドとは何か〜webpackを使ってビルドする

この辺が曖昧だったので、書き残しておきます。

  • ビルドとは何か
  • なぜビルドが必要か
  • ビルドでは何を行なっているのか
  • ビルドしたらどうなるのか

Node.jsの特徴

  • JavaScriptをサーバーサイドで動かすための実行環境。
  • モジュール機能(他ファイルの読み込み)
  • ノンブロッキングI/Oで処理を効率化

参考記事

ノンブロッキングI/O (non-blocking I/O)
ノンブロッキングI/Oと非同期I/Oの違いを理解する
Node.js を5分で大雑把に理解する
Node.jsについて調べてみた
JavaScriptが辿った変遷
npm とか bower とか一体何なんだよ!Javascript 界隈の文脈を理解しよう

ビルドツール

Node.jsスタイルのコードは、そのままの状態ではブラウザで動きません。ソースコードを元にして、実際に動くプログラム(実行可能ファイル)を作ってあげる必要があります。
その作成処理のことをビルドと言います。

ビルドを実行するためには、ビルドツールを使用します。

概要

以下、10年遅れたJavaScriptの知識をざっくり10分でアップデートしようより引用。

最近のWebアプリケーションは、開発時のコードと実際の製品に使われるコードが異なります。開発者はブラウザーにサポートされていない可能性がある最新バージョンのJavaScriptでコードを書いたり、node_modulesフォルダー内のサードパーティ製パッケージとその依存オブジェクトを多用したり、静的解析ツールや圧縮ツール(Minifier)などを使ったりして開発します。これらをすべて変換、効果的にデプロイして、大半のWebブラウザーが理解できる形にするのがビルドツールです。

何を行うのか

以下、キャッチアップJavaScriptビルドより引用。

  • モジュール管理(依存性解決)
  • テンプレート管理
  • UT/操作テスト
  • 構文チェック
  • 圧縮/難読化
  • CSSプリプロセッサー
  • ES2015コンパイル
  • altJSコンパイル

簡単に補足します。

  • CSSプリプロセッサーとは、独自の構文でCSSを生成するプログラムのこと。コンパイルにより、純粋なCSSより可読性や保守性が高くなります。
  • ES2015(ES6)はJavaScriptの新基準ですが、古いブラウザでは対応していない場合があります。そのため、コンパイルで互換性のあるES5に変換します。(トランスパイル)
  • altJSとは、コンパイルによりJavaScriptに変換されるプログラミング言語のこと(代替JavaScript)。従来のJavaScriptより可読性と保守性が高く、コーディングの負担を減らします。

テンプレート管理が何を意味しているのか、よくわからなかったです。
文字列の組み込みのことでしょうか・・・?

タスクランナーとは

ビルドツールで行われている処理(タスク)を自動化してくれるツールのこと。
grupやGruntが挙げられます。

ネットで調べた限り、ビルドツールとタスクランナーの区分は曖昧でした。
webpackの立ち位置が微妙なところです。

npmとは

Node.jsのパッケージ管理ツール。
Node.jsと同時にインストールされます。

各種ビルドツールは、npmを使ってインストールすることができます。
今回は、webpackを使ってみます。

参考記事

CSS プリプロセッサー
CSSプリプロセッサ(CSSメタ言語)のお勉強
最近のビルドツールって何なの?
タスクランナー(Gulp)の入門の入門
【保存版】gulp, webpack, parcel...増え続けるタスクランナーの特徴を理解して最適なものを選択しよう
JavaScriptをやっているとnpm/yarn/gulp/grunt/webpackなど、たくさんのツールがあって混乱したので、それぞれの役割と違いをざっくりとまとめた
プログラミングが便利に!2018年に取り入れたいオススメのタスクランナー5選
Webpackってどんなもの?

実演

初期化

テスト用ディレクトリを作成し、移動します。

$ mkdir js_test
$ cd js_test

初期化します。
いくつか質問がありますが、全てEnterで大丈夫です。

$ npm init

初期化後、ディレクトリ内にpackage.jsonが生成されます。

webpackのインストール

webpackをローカルインストールします。

$ npm install webpack --save-dev

ディレクトリ直下にpackage-lock.jsonnode_modulesディレクトリが生成されます。

webpackのバージョンを確認します。

$ npx webpack -v
4.39.1

このバージョンでは、webpack-cliというライブラリも必要になります。
webpackと同じく、ローカルインストールします。

$ npm install --save-dev webpack-cli

インストール後、package.jsonのdevDependenciesに追記されました。

package.json
{
  "name": "js_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.39.1",
    "webpack-cli": "^3.3.6"
  }
}

webpackの設定

ビルドするためには、元のソースコードの場所とビルド後に生成される実行ファイル(bundleファイル)についての情報が必要です。
元のソースコードで一番最初に読み込まれるファイルは、エントリ-ポイントと呼ばれます。

ディレクトリ直下に設定ファイルwebpack.config.jsを作成します。

$ touch webpack.config.js

次のように設定します。

webpack.config.js
const path = require('path');

module.exports = {
    // エントリーポイントの設定
    entry: './src/my-main.js',
    // ビルド後、'./dist/my-bundle.js'というbundleファイルを生成する
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-bundle.js'
    }
};

テストファイルの作成

テストファイルを作成します。
文字列を返すメソッドを記述し、それをモジュールとして別ファイルで読み込んで出力します。

$ touch my-index.html
$ mkdir src
$ mkdir dist
my-index.html
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="dist/my-bundle.js" charset="utf-8"></script>
</body>
</html>
$ cd src
$ touch my-main.js
$ touch my-func.js
my-main.js
var func = require('./my-func');

var res = document.createTextNode(func());
document.body.appendChild(res);
my-func.js
module.exports = function () {
    return 'my-test';
};

エイリアスコマンドの設定

webpackコマンドを簡単に実行するために、エイリアスコマンドを設定します。
package.jsonのscriptに以下を記述します。

package.json
"build": "webpack --mode development"

もしくは

package.json
"build": "webpack --mode production"

modeにより、生成されるbundleファイルの内容が異なります。(動作は同じです。)
modeを指定しない場合は、ビルド実行時に警告が発生します。

この設定によりnpm run build でビルドを実行する事が可能になりました。

ビルド実行

エイリアスコマンドを設定したので、早速実行してみます。

$ npm run build

実行後、bundleファイルであるdist/my-bundle.jsが生成されます。
ブラウザで出力した文字列を確認できれば、ビルド成功です。

ビルドせずに動作を確認したい

ビルドせずに動作を確認したい場合は、watchオプションを利用します。
package.jsonのscriptに以下を記述します。

package.json
"watch": "webpack --watch"

npm run watchを実行すると、コードの変更が検知されるようになります。そのため、(画面をリロードすれば)ビルドせずに動作を確認する事ができます。

デベロッパーツール上で元のファイルを確認したい

デベロッパーツールのSourcesタブでは、ビルド元のファイルを確認する事ができません。

それらを表示させたい場合は、webpack.config.jsに以下を記述します。

webpack.config.js
devtool: 'inline-source-map'

これで、デベロッパーツール上でmy-main.jsmy-main.jsの内容を確認する事ができます。

参考記事

package.jsonの中身を理解する
package-lock.jsonについて知りたくても聞けなかったこと
勉強メモ/npmの使い方(node.js=v0.11.16, npm=2.3.0, 2015-03時点)
npm 5.2.0の新機能! 「npx」でローカルパッケージを手軽に実行しよう
webpack.config.jsがわからない
npmとwebpack4でビルド - jQueryからの次のステップ
step by stepで始めるwebpack
新人にドヤ顔で説明できるか、今風フロントエンド開発ハンズオン(Git/Node.js/ES6/webpack4/Babel7)
React.jsでビルドされる前のコードをブラウザで確認する

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初めて JIRA RestAPI を使ったよ

今度は JIRA Server platform REST API を使用することになりました。

とりあえず基本認証をすれば使えるとのことで、英語のドキュメントを読み漁ることに。
Basic authentication

さぁ Google 翻訳さんの出番ですよ!
いつもありがとうございます。m(_ _)m

基本認証に必要なこと

Token 発行したり、色々と必要になるのかと思いきや、JIRA にログインできる ID と PASS があれば API も利用できるそうです。
なんだか敷居が低くてびっくり。
ただ、ID と PASS は : で区切ってくっつけたのち、BASE64 エンコーディングしとかないといけないみたいです。
ex)'JIRA ID' + ':' + 'JIRA PASSWAORD' ← これを BASE64 エンコーディングする

Buffer クラスを利用した BASE64 エンコード

Node.js で BASE64 エンコードするには Buffer クラスを利用します。
標準ライブラリですので、そのまま使用することができます。

const buffer = new Buffer('JIRA ID' + ':' + 'JIRA PASSWAORD');
const string = buffer.toString('base64');

JIRA API のお決まりで、エンコードした文字列の頭に 'Basic 'とつける必要があります。
半角スペースが入るので注意ですね!

あとは header に Authorization パラメータとして乗っければ OK です。

API を Request する

あとは、使いたい API の URL を指定すれば JIRA の API を利用することができます。
今回は課題(issue)を検索する SEARCH API を利用しました。

ex.js
const request = require('request-promise');
const buffer = new Buffer('JIRA ID' + ':' + 'JIRA PASSWAORD');
const string = buffer.toString('base64');
const options = {
    uri: 'https://myhost.com/rest/api/2/issue/search',
    headers: {
        "Content-Type": 'application/json',
        "Authorization": 'Basic ' + string
    },
    method: 'GET',
    json: true
};

request(options).then((data) => {
    console.log("200 OK");
    console.log(data);
}).catch((error) => { console.log(error)});
実行結果
> node .\ex.js

{ expand: 'schema,names',
  startAt: 0,
  maxResults: 50,
  total: 1739,
  issues:
   [ { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',
       id: '512802206',
       self: 'https://myhost.com/rest/api/2/issue/502802206',
       key: 'HOSTENG-5',
       fields: [Object] },
     { expand: 'operations,versionedRepresentations,editmeta,changelog,renderedFields',
       id: '512797809',
       self: 'https://myhost.com/rest/api/2/issue/502797809',
       key: 'HOSTENG-4',
       fields: [Object] }
// 省略

自分のが抱えている課題のリストが表示されます。
ここで id を確認して、課題の詳細を確認したり、追記したりします。

おわりに

ここまでお付き合いいただきありがとうございました。
たぶん、英語がちゃんと読めれば公式ドキュメントを読んですぐわかる内容だったんでしょうが、なんだか凄く苦労しました。
curl のサンプルコードを node.js で再現して response を見ても、どこにもトークンっぽいものがない!('Д')
って頭抱えていましたが、そもそもトークンとか必要ない方式でした。
同じような悩みを抱えている方の助けになれば幸いです。

他にも Cookie-based authentication とかもあるみたいで、なんだかこっちを利用している方も多いみたいなので、今度勉強したいと思います。
ではまた!(^^)/

参考にさせていただきましたm(_ _)m

JIRA Server platform REST API
JIRA Basic authentication

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSLからWindows側のSelenium-Standaloneを起動したい

NodeJSのライブラリ、selenium-standaloneはご存知でしょうか?
NodeJSとJavaを事前にインストールしておく必要はありますが、Windowsでもコマンド一発で、Selenium + インストール済みのブラウザに対応したWebDriverを自動でインストールしてくれるのでとても便利ですね。

さて、Windowsで開発している人の多くはWSL(Windows Subsystem for Linux)を利用しているかと思いますが、Windows側にインストールしたブラウザをselenium-standaloneで自動操作するには、selenium-standaloneもWindows側でインストールしておかないといけません。
とはいえ、わざわざSeleniumを使いたい時だけPowerShellを起動するのも面倒ですし、Linux側から起動できるといいですね。

というわけで、その方法がこちらです。

cmd.exe /c selenium-standalone.cmd install  # SeleniumやWebDriverなどのダウンロード
cmd.exe /c selenium-standalone.cmd start  # Seleniumサーバの開始

上記をbash上で実行すると、Windows側のselenium-standaloneコマンドが実行されます。
PowerShellやコマンドプロンプトで selenium-standalone を実行する場合と同じことになります。

解説

WSLからWindows側のコマンドを実行するには、実行したいコマンドを 拡張子付き で指定する必要があります。
例えば、bash上で下記のように実行すると、Windows側のselenium-standaloneが呼び出されます。

$ selenium-standalone.cmd start

コマンドの拡張子を知りたい場合は、PowerShellでGet-Commandを使うと知ることができます。

PS C:\Users\tsemura > Get-Command selenium-standalone

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     selenium-standalone.cmd                            0.0.0.0    C:\Users\tsemura\AppData\Roaming\npm\sel...

さて、ただの実行ファイル(.exe ファイル)であれば単に拡張子付きで実行すればよいのですが、バッチファイルなどの場合はこのままでは実行できないので、コマンドプロンプト経由で実行する必要があります。
と言っても、Windows側でコマンドプロンプトを起動する必要はありません。bashでcmd.exeを実行し、実行時オプションで実行したいコマンドを渡してあげればOKです。

cmd.exe /c selenium-standalone.cmd start

というわけで、↑が最終的に実行するコマンドになります。
頻繁に使う人はaliasなどに登録しておくとよいでしょう。

参考

https://www.atmarkit.co.jp/ait/articles/1805/31/news052.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Alexa APL, 第9回 タッチ対応 その3(Sequenceと音声応答)

はじめに

Alexaを搭載した画面付きデバイスの画面レイアウトを作成します。
画面の画像、もしくは商品名をタッチすると、その商品名を答えるレイアウトを作成します。
TouchWrapperコンポーネントを使って、スキルにタッチを通知(SendEvent)し、応答する方法を実施します。
第7回の説明では商品は一つでしたが、今回はSequenceを使って、商品を複数準備します。

今回実施する内容

画面の画像、もしくは商品名をタッチすると、その商品名を答えるレイアウトを作成します。
中型デバイス(Echo Show用)
中型レイアウト.jpg

環境

OS:Windows 10 JP
Alexaスキル言語:Node.js
Editor:Visual Studio Code
APLバージョン:1.0, 1.1

参考

Alexa ハローAPL、Alexaスキルの画面への対応
第1回のAlexa APLの記事です。タイトル通り、ハローAPLを表示させるだけのAPLです。

Alexa APL, 第6回 シーケンス(Sequence)を使ったレイアウト
第6回のAlexa APLの記事です。Sequenceを使って画面レイアウトを作成するAPLの紹介です。

Alexa APL, 第7回 タッチ対応 その1(SendEvent)
第7回のAlexa APLの記事です。TouchWrapperとSendEventを使って、画面をタッチすると音声を応答するAPLの紹介です。

APLコマンド
AmazonのAPLドキュメントにあるAPLコマンドの説明です。

標準コマンド
AmazonのAPLドキュメントにあるコマンドの説明です。SendEventやSpeakItemの説明があります。

用語

APL

Alexa Presentation Language
amazonの画面つきのAlexaの画面表示用の言語。
JSONを使用した記載方法です。
インターネットのホームページはHTMLとCSSで作成しますが、AlexaはAPLで作成するということです。

APLオーサリングツール

APL作成を視覚的に見ながらAPLのJSONファイルを作成するツール。
サンプルテンプレートも準備されており、その中から選択していくだけで、だいたいの画面は作成できる。

前提条件

前提条件はとくにないといえばないですが、本まとめを読むにあたり、以下がわかっていることが前提です。
・alexa developer consoleのアカウントがある
・Alexaスキルを開発したことがある
・JSONの記載方法を知っている
・「Alexa ハローAPL、Alexaスキルの画面への対応」、「Alexa APL, 第6回 シーケンス(Sequence)を使ったレイアウト」、および「Alexa APL, 第7回 タッチ対応 その1(SendEvent)」の記事をみている

シーケンス(Sequence)を使用したタッチ対応画面レイアウトの作成

準備

今回の画面レイアウトでは、Sequenceを使って商品をリスト表示するため、4枚の写真とそれにつける商品名を準備します。
3枚の写真までは画面内に表示されて、4枚目は見えない想定です。スクロールさせてタッチできることを確認します。

画像 商品名
coffee_480x480.jpg コーヒー
cappuccino_480x480.jpg カプチーノ
caffellatte_480x480.jpg カフェラテ
espresso_480x480.jpg エスプレッソ

Sequence、TouchWrapperを使って並べてみる

これから作成する「レイアウト画面」はこんな感じです。
layout.jpg

第6回のレイアウトと違うところは、強調で示します。
1. APLオーサリングツールを起動して「最初から作成」を選択する。
2. 「レイアウト画面」の「mainTemplate」を選択し、「Container」を追加する。
3. 「レイアウト画面」で、「Container」を選択し、「Sequence」を追加する。
4. 「レイアウト画面」の「Sequence」を選択し、「詳細設定画面」で、以下をそれぞれ設定する。
・ data:${payload.sample.sampleArray}
・ height:50vh
5. 「レイアウト画面」で、「Sequence」を選択し、「Container」を追加する。
6. 「レイアウト画面」の「Container」を選択し、「TouchWrapper」を追加する。ここのプロパティは後ほど追加する。
7. 「レイアウト画面」の「Container」を選択し、「詳細設定画面」で、以下を設定する。
・ direction:row
8. 「レイアウト画面」で、「Container」を選択し、「Image」を追加する。
9. 「レイアウト画面」の「Image」を選択し、以下をそれぞれ設定する。
・ source:${data.imageURL}
・ width:20vw
・ height:20vh
NOTE: widthとheightの両方を設定するのがガイドのため今回は追加しました。
10. 「レイアウト画面」で、「Container」を選択し、「Text」を追加する。
11. 「レイアウト画面」の「Text」を選択し、「詳細設定画面」で、以下を設定する。
・ text:${data.text}
12. APL JSONの画面を開いて、「TouchWrapper」の記載を以下の通り、onPresstypeargumentsを追加する(詳細設定画面でonPressに値を設定するのと同じことですが、入力ボックスが小さいため、ソースに書き込んだほうがやりやすいです)。

...
"type": "TouchWrapper",
"onPress": {
    "type": "SendEvent",
    "arguments": "${data.text}"
},
...

JSONデータの作成

以下の通り、JSONデータを作成する。

JSONデータ
{
    "sample": {
        "sampleArray": [
            {
                "text": "コーヒー",
                "imageURL": "https://coffee_480x480.jpg"
            },
            {
                "text": "カプチーノ",
                "imageURL": "https://cappuccino_480x480.jpg"
            },
            {
                "text": "カフェラテ",
                "imageURL": "https://latte_480x480.jpg"
            },
            {
                "text": "エスプレッソ",
                "imageURL": "https://espresso_480x480.jpg"
            }
        ]
    }
}

APLソースコード

出来上がったAPLのフルソースコードとデータJSONを載せます。実際にスキルで表示を試す場合は、Alexa ハローAPL、Alexaスキルの画面への対応を参考しに実施します。

APL
{
    "document": {
        "type": "APL",
        "version": "1.1",
        "settings": {},
        "theme": "dark",
        "import": [],
        "resources": [],
        "styles": {},
        "onMount": [],
        "graphics": {},
        "commands": {},
        "layouts": {},
        "mainTemplate": {
            "parameters": [
                "payload"
            ],
            "items": [
                {
                    "type": "Container",
                    "items": [
                        {
                            "type": "Sequence",
                            "height": "50vh",
                            "data": "${payload.sample.sampleArray}",
                            "items": [
                                {
                                    "type": "TouchWrapper",
                                    "onPress": {
                                        "type": "SendEvent",
                                        "arguments": [
                                            "${data.text}"
                                        ]
                                    },
                                    "item": {
                                        "type": "Container",
                                        "direction": "row",
                                        "items": [
                                            {
                                                "type": "Image",
                                                "width": "20vw",
                                                "height": "20vh",
                                                "source": "${data.imageURL}"
                                            },
                                            {
                                                "type": "Text",
                                                "text": "${data.text}"
                                            }
                                        ]
                                    }
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    },
    "datasources": {
        "sample": {
            "sampleArray": [
                {
                    "text": "コーヒー",
                    "imageURL": "https://coffee_480x480.jpg"
                },
                {
                    "text": "カプチーノ",
                    "imageURL": "https://cappuccino_480x480.jpg"
                },
                {
                    "text": "カフェラテ",
                    "imageURL": "https://latte_480x480.jpg"
                },
                {
                    "text": "エスプレッソ",
                    "imageURL": "https://espresso_480x480.jpg"
                }
            ]
        }
    }
}

スキルのソースコード作成

LaunchRequestの時の画面表示については、割愛しますので、必要な場合は、Alexa ハローAPL、Alexaスキルの画面への対応をご覧ください。

ここでは、ユーザーが画面をタッチした場合のスキルでの処理のソースを記載します。説明はAlexa APL, 第7回 タッチ対応 その1(SendEvent)をご覧ください。

index.js
...
const TouchEventHandler = {
  canHandle(handlerInput) {
  return ((handlerInput.requestEnvelope.request.type === 'Alexa.Presentation.APL.UserEvent' &&
      (handlerInput.requestEnvelope.request.source.handler === 'Press' || 
      handlerInput.requestEnvelope.request.source.handler === 'onPress')));
  },
  handle(handlerInput) {
      // TcouhWrapperのargumentsで指定したパラメータを取得する
      const speechText = handlerInput.requestEnvelope.request.arguments[0];

      return handlerInput.responseBuilder
          .speak(speechText)
          .getResponse();            
  }
};

...

exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    TouchEventHandler,
    HelpIntentHandler,
    CancelAndStopIntentHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

おわりに

今回は、SequenceとTouchWrapperを使って、商品リストをタッチすると音声応答するAPLを作成しました。
第6回と第7回のタッチ対応の説明の結合の内容ですが、特に目新しいことはありませんでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Electron】40万件のレコードを鬼のような速度で描画するクライアントアプリケーションの開発

背景

先日、【WPF】仮想化キャンバスを使用したDataGridの描画高速化という記事を投稿しました。
そこで仮想キャンバスによるデータ描画の高速化を行っていたのですが・・。
WPFの描画(主にスクロールパフォーマンス)めっちゃ遅い。

そもそもWPFは柔軟性が高い分、大量データの描画は不得手だったのですが、
許容できないレベルで遅延が発生していたので困り果てていました・・。
そんな時に何気なく「Clusterize.js」という大量データ描画JSを発見

このClusterize.js、描画が鬼のように速い。50万件のレコードもサクサク描画できる。
「あれ?このJSをASP.Net Coreで作成したページに埋め込んでElectronで動かしたら超高速じゃない?」
というわけでやってみました。

まずElectronの導入部分を、Electronの環境構築(for Windows) - Qiita を参考に実施、
その後Clusterize.jsの動作確認まで行った自分用忘備録です。

NodeJS - インストール

Nodejs.org - Downloads にアクセスして下記リンクからインストーラをダウンロード。
image.png

ダブルクリックで実行したら以下の画面が表示される。
しばらくボタンがDisabledだけど、少し待つと次のステップに進みます。
image.png

特に設定を変更する必要はないので、インストーラの誘導通り進めていってください。

image.png

上記画面が表示されたらNodeJSのインストール完了。
念のために完了後は以下のコマンドでバージョン確認を行いましょう。

C:\>node -v
v10.16.0

プロジェクトの作成

てきとうなフォルダを作成します。

image.png

そのフォルダ内でGit Bashを開きます。ないならインストールしてね。
image.png

開いたら npm init でプロジェクトを初期化。
基本的にエンター連打で問題なし。
Is this OK? (yes) の確認が出たら yes を打ち込んで完了。

user_name@machine_name MINGW64 ~/source/repos/magicbullet
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (magicbullet)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\Users\user_name\source\repos\magicbullet\package.json:

{
  "name": "magicbullet",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes) yes

最終イメージ。
ll コマンドでpackage.json ができていることを確認してね。

user_name@machine_name MINGW64 ~/source/repos/magicbullet
$ ll
total 1
-rw-r--r-- 1 owner 1049089 207  8月  9 15:01 package.json
package.json
{
  "name": "magicbullet",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Electron - インストール

続いてElectronをインストールします。以下のコマンドを投入。

npm install electron -g

npm install --save-dev electron

バージョン確認を行ってインストールできていることを確認。

user_name@machine_name MINGW64 ~/source/repos/magicbullet
$ electron -v

v6.0.1

エントリーポイントの作成

package.jsonと同じパスに以下の二つのファイルを配置する。

magicbullet/index.js
"use strct";

// Electronのモジュール
const electron = require("electron");

// アプリケーションをコントロールするモジュール
const app = electron.app;

// ウィンドウを作成するモジュール
const BrowserWindow = electron.BrowserWindow;

// メインウィンドウはGCされないようにグローバル宣言
let mainWindow = null;

// 全てのウィンドウが閉じたら終了
app.on("window-all-closed", () => {
  if (process.platform != "darwin") {
    app.quit();
  }
});


// Electronの初期化完了後に実行
app.on("ready", () => {
  //ウィンドウサイズを1280*720(フレームサイズを含まない)に設定する
  mainWindow = new BrowserWindow({width: 1280, height: 720, useContentSize: true});
  //使用するhtmlファイルを指定する
  mainWindow.loadURL(`file://${__dirname}/index.html`);

  // ウィンドウが閉じられたらアプリも終了
  mainWindow.on("closed", () => {
    mainWindow = null;
  });
});
index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Sample</title>
</head>
<body>
  <p>Hello World</p>
</body>
</html>

完成イメージ。
image.png

Electron - コンパイル

以下のコマンドを投入します。

user_name@machine_name MINGW64 ~/source/repos/magicbullet
$ electron .

image.png

動いた!うれしい!!

Clusterize.js の導入

今回はClusterize.jsのデモページをElectronで試してみます。
まずはgitからデモページのソースを取得。

### 任意のディレクトリで実行
user_name@machine_name MINGW64 ~/source/repos
$ git clone https://github.com/NeXTs/Clusterize.js
Cloning into 'Clusterize.js'...
remote: Enumerating objects: 776, done.
remote: Total 776 (delta 0), reused 0 (delta 0), pack-reused 776
Receiving objects: 100% (776/776), 1.89 MiB | 2.01 MiB/s, done.
Resolving deltas: 100% (416/416), done.

user_name@machine_name MINGW64 ~/source/repos
$ cd Clusterize.js/

user_name@machine_name MINGW64 ~/source/repos
$ git checkout gh-pages
Switched to a new branch 'gh-pages'
Branch 'gh-pages' set up to track remote branch 'gh-pages' from 'origin'.

チェックアウトしたコードをElectron用ディレクトリにコピーします。

こんな感じになります。
image.png

Electronを起動。

user_name@machine_name MINGW64 ~/source/repos/magicbullet
$ electron .

image.png

40万件のデータもサクサクスクロールできる!
いまクライアントアプリケーションでこれだけのデータをストレスなく描画するにはベストな選択なのではないでしょうか?(わかんない)

以降は、実際のシステムに組み込めるか試していきたいと思います。

追記:

えっ!?Electron.Netってものがある!?

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む