- 投稿日:2020-01-16T19:19:25+09:00
Ubuntu18.04 開発環境作成メモ
how to use
cd ~ chmod +x setup.sh ./setup.shsetup.sh
setup.shsudo apt update sudo apt -y upgrade sudo apt -y install vim sudo apt -y install git sudo apt -y install guake sudo apt -y install curl sudo apt-get -y install xsel # pyenv sudo apt -y install build-essential libffi-dev libssl-dev zlib1g-dev liblzma-dev libbz2-dev libreadline-dev libsqlite3-dev git clone https://github.com/pyenv/pyenv.git ~/.pyenv echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init -)"' >> ~/.bashrc source ~/.bashrc pyenv install 3.7.6 pyenv global 3.7.6 # nodebrew curl -L git.io/nodebrew | perl - setup echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc source ~/.bashrc nodebrew install-binary stable nodebrew use stable npm -g install @angular/cli sudo sysctl fs.inotify.max_user_watches=524288 sudo sysctl -p # docker sudo apt install docker.io sudo groupadd docker sudo gpasswd -a $USER docker sudo systemctl restart docker # docker-compose sudo curl -L "https://github.com/docker/compose/releases/download/1.25.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose # ssh keygen ssh-keygen -t rsa cat .ssh/id_rsa.pub | xsel --clipboard --input # english directory LANG=C xdg-user-dirs-gtk-update # sudo reboot -h now
- 投稿日:2020-01-16T15:12:40+09:00
Node.jsを用いた定期ツイートbot作成メモ
すぐ忘れるのでメモ。
もっと無駄の少ないやり方なんて知りません、、、
まずTwitterAPIの取得
申請の際の作文はbotにしか使わないという趣旨を書けばすぐに通るはずです。
API keyとToken keyが得られれば勝ち。
ツイート内容のコードを作る
用意するのは
npm i Twitter
とnpm i node-schedule
ツイート
https://yukimonkey.com/js-application/twitter-bot-2/画像ツイート
https://qiita.com/n0bisuke/items/6b269f61152e9f336c35時間指定はNode-scheduleを使う
Heroku
アカウント作成
タイムゾーンについて、途中で気づいてめんどくさかったのでソースコードの時間を-9hしました。
Herokuへデプロイ
コマンドはこの記事を参考にしました。
https://qiita.com/daiki7nohe/items/035c39c1e538551b1f6c#git%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88
この二つの記事を参考にapp.jsと、起動するためのコマンドをpackage.jsonに記述するか、procfileを作る
https://qiita.com/yfujii01/items/d675f654f1fcce3b9098
https://www.webprofessional.jp/building-facebook-chat-bot-node-heroku/サーバーが寝ないようにする
Heroku Scheduler
https://miyabi-lab.space/blog/23
- 投稿日:2020-01-16T12:19:45+09:00
【文系新卒が】出来立てご飯を食べたかった話【GoogleHome LINE Node-RED】
事の始まり
僕はご飯が大好きな文系新卒君です。
僕はありがたいことに、家に帰るとご飯が毎日用意されています。
しかし学生時代のように出来立てのホカホカご飯を食べれる機会は減ってしまいました。
そう...社会人は学生とは違い帰る時間がバラバラ。
帰る時間を連絡しても、1日中ケータイを触ってるわけじゃないのでご飯の完成にラグが起きてしまう。.....だったら帰宅時間を教えることのできるシステムを作ればいいじゃないか!!
全体図
どうすれば帰宅時間を知らせることができるか考えた結果、
「物理的」に知らせるのが一番じゃないかと考えました。
こんな感じで実装すれば、ラインメッセージと自宅へ音声送信両方が実現ができるはず!
実装
それでは実装していきますよ!!
事前準備は4つ
- Node-REDのインストール
- LINE Developersのアカウント
- Google App Script
- Node-REDと同じLANに接続されたGoogleHome
今回LINEとGoogleHomeを繋げる目的で利用する
Node-RED
ですが
何かと何かを繋ぐ際にGUI上で実行できるWebアプリケーションと思って下さい。参考資料
Node-RED日本ユーザ会
Windowsで実行する : Node-RED日本ユーザ会
LINEのBot開発 超入門(前編) ゼロから応答ができるまで
Google Homeの初期設定をする手順1.Node-REDとGoogleHomeを繋げる
まず初めにNode-REDのページを開き、パレットの管理から
node-red-contrib-cast
を追加します。
これがGoogleHomeへ送ったメッセージを読み上げさせるノードになります。
インストールが完了したら、下図のフローを作成してください。
次にCastノードの設定を行います。
項目 入力内容 IP GooglHomeのIPアドレス language ja Volume 0~100(好みの音量サイズ) 設定後にinjectノードを実行し、設定した言葉がGoogleHomeから聞こえたらOKです!
2.Node-REDをネットワークに公開
このままではNode-REDはローカル外からのアクセスができません。
なので簡単にローカル環境を外部から接続させることのできるngrok
を使いたいと思います。
ngrokをインストールしてNode-REDで設定されているポートをパスワード付きで公開してください。EXAMPLES: ngrok http 80 # secure public URL for port 80 web server ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Version 2.2.4 Region United States (us) Web Interface http://127.0.0.1:1880 Forwarding http://xxxxxxxx.ngrok.io -> localhost:1880 Forwarding https://xxxxxxxx.ngrok.io -> localhost:1880 Connections ttl opn rt1 rt5 p50 p90 6 0 0.05 0.02 23.33 25.98
Forwading
に書かれているURL(https)にアクセスができたらOKです!ngrokの使い方(windows, mac)
少しでも安全にngrokを使用する(Basic認証)3.LINEとNode-REDを繋げる
最後にLINEとNode-REDを繋げたいと思います。
まずはGoogle App Script(GAS)で以下のコードを張り付けて下さい。
※アクセス先の情報は自身で入力してください。function doPost(e) { // アクセス先の情報 var url = "ngrokで作成したHTTPSのURL" + "/line"; var userid = "任意のID"; var password = "任意のパスワード"; // POSTメソッドの投稿データ var event = JSON.parse(e.postData.contents).events[0]; var replyToken = event.replyToken var msg = event.message.text; var msgType = event.message.type; var payload = {"replyToken": replyToken, "message":msg, "type":msgType}; // POSTメソッドのオプション var options = { "method" : "POST", "headers" : {"Authorization" : " Basic " + Utilities.base64Encode(userid + ":" + password)}, "payload" : payload, "muteHttpExceptions" : true } try{ // POSTメソッドのリクエスト var response = UrlFetchApp.fetch(url, options); var content = response.getContentText("UTF-8"); }catch(e){ Logger.log(e.message); } }その後Webアプリケーションとして導入を行うことでWebhook用のURLが表示されるので、
それを忘れないようコピーして置いてください。(Current web app URL
のところです)
LINE DevelopersへアクセスしてWebhook先へ先ほどのURLを貼り付けます。
ついでにチャンネルアクセストークンを使うのでメモしておきましょう。
あとはNode-RED上でLINE+GASからのメッセージとGoogleHomeを繋げてあげれば完了です!
4.LINEのメッセージとGoogleHomeを繋げる
いよいよ最終工程。完成状態はこんな感じになります!
最後に下に記載したJSONデータを読み込ませて、以下の項目を行えば終了です!!
googlehomeノード
を最初に設定したgooglehomeノードに変更。Line Reply API用設定
のBearer "your_channel_access_token"の""中身を
先程メモしたチャンネルアクセストークンに変更。※Line Reply API用設定でLINE Developersからチャンネルアクセストークンは確認できます。
作成したLINE botにメッセージを送信すれば、Googleホームが読み上げてくれます!!!
[{"id":"314b7d3f.2adc62","type":"tab","label":"フロー 1","disabled":false,"info":""},{"id":"72e325a4.cdbacc","type":"comment","z":"314b7d3f.2adc62","name":"line reply msg","info":"","x":310,"y":160,"wires":[]},{"id":"65a3144c.b1371c","type":"http in","z":"314b7d3f.2adc62","name":"","url":"/line","method":"post","upload":false,"swaggerDoc":"","x":170,"y":220,"wires":[["246b9d27.a33942","4ff3caa3.50ed94"]]},{"id":"accdaf77.6e5c9","type":"http response","z":"314b7d3f.2adc62","name":"","statusCode":"","headers":{},"x":850,"y":220,"wires":[]},{"id":"1bc5bba6.3b0244","type":"http request","z":"314b7d3f.2adc62","name":"Line Reply API","method":"POST","ret":"txt","paytoqs":false,"url":"https://api.line.me/v2/bot/message/reply","tls":"","persist":false,"proxy":"","authType":"","x":660,"y":220,"wires":[["accdaf77.6e5c9"]]},{"id":"246b9d27.a33942","type":"change","z":"314b7d3f.2adc62","name":"Line Reply API 用設定","rules":[{"t":"set","p":"headers.Content-Type","pt":"msg","to":"application/json","tot":"str"},{"t":"set","p":"headers.Authorization","pt":"msg","to":"Bearer \"your_channel_access_token\"","tot":"str"},{"t":"set","p":"payload.replyToken","pt":"msg","to":"payload.replyToken","tot":"msg"},{"t":"set","p":"payload.messages[0].type","pt":"msg","to":"text","tot":"str"},{"t":"set","p":"payload.messages[0].text","pt":"msg","to":"送信完了","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":220,"wires":[["1bc5bba6.3b0244"]]},{"id":"894d56ce.436268","type":"cast-to-client","z":"314b7d3f.2adc62","name":"google home","url":"","contentType":"","message":"","language":"ja","ip":"","port":"","volume":"50","x":770,"y":380,"wires":[[]]},{"id":"97eee3ab.2f10f","type":"comment","z":"314b7d3f.2adc62","name":"googlehome","info":"","x":350,"y":340,"wires":[]},{"id":"4ff3caa3.50ed94","type":"change","z":"314b7d3f.2adc62","name":"受信したJSONからメッセージのみ取得","rules":[{"t":"set","p":"message","pt":"msg","to":"payload.message","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":380,"wires":[["894d56ce.436268"]]}]あとがき
これにて我が家のホカホカご飯問題は幕を閉じた。
今日も出来立てご飯と幸せを噛みしめる文系新卒君であった。文系新卒君の挑戦は続く...
- 投稿日:2020-01-16T12:02:23+09:00
LambdaからRedisのデータを取得したい
使用するもの
- Lambda
- Redis
私の環境
Node 12系
DockerでLamdaを用意しています。方法については、以下の記事を参考にしてください。
https://qiita.com/gdtypk/items/78b6a76dc9f212296c89Redisも同様にDockerで起動しています。
redis:4.0困ったこと
Node.jsは非同期で動作するので、そのあたりが苦労した。
コード
const redis = require("redis"); const Promise = require('bluebird'); // 接続情報 const config = { host: 'redis', port: 6379 }; let client = null; let value = ""; const key = "key"; exports.handler = async (event, context) => { try { //Redisに接続 client = await connectRedis(); // データの取得 value = await findValueOfKey(client, key); //Redisとの接続を切断 disconnectRedis(); //レスポンス返却 console.error('レスポンス:' + value); context.succeed({statusCode: 200, body: JSON.stringify(value)}); } catch (error) { console.error('エラー:', error); disconnectRedis(); } }; /** * Redisに接続する処理。 */ function connectRedis() { return new Promise(function (resolve, reject) { const client = redis.createClient(config); client.on('connect', () => { console.log('接続OK'); resolve(client); }); client.on('error', (error) => { console.log(`接続NG`); reject(error); }); }); } /** * Redisとの接続を切断する。 */ function disconnectRedis() { if (client) { console.log("切断します"); client.end(true); } } /** * Keyを使用し、Valueを取得する。 * @param client * @param key */ function findValueOfKey(client, key) { return new Promise(function (resolve) { client.get(key, (err, reply) => { resolve(reply); }); }); }おわり
もっといい書き方があったり、コードがおかしいとかあれば、教えて下さい。
- 投稿日:2020-01-16T10:32:52+09:00
Could not find matching close tag for "<%="のエラーメッセージ
node.jsのエラーコード
Could not find matching close tag for "<%="
意味 “<%=“. に合うタグが見つかりませんでした。
- 投稿日:2020-01-16T09:58:50+09:00
node.jsを10->12に更新したときに起きたエラーと対処内容
表題通りの記事です。
これからnode.jsを10->12に更新する方の助けになれば幸いです。確認環境
- Ubuntu: 18.04.3 LTS
- node.js: 10.16.0、12.14.1
- ビルドツール: gulp (後述しますが4系へのアップデートが必須でした)
やったこと(全体像)
- n をつかってローカル環境のnode.jsを10->12に更新 (参考: nodeとnpmのバージョン更新方法)
npm ci
して、出てきたエラーを潰す
- firebaseの更新
- node-sassの更新
npm run build
して、出てきたエラーを潰す
- gulpを3系->4系へ移行
エラー1 (firebaseの更新により解消)
最初はイージーケースから。
事象
npm ci
したところ、大量(体感3分)のログが出力され、最後に以下のエラーが吐かれました。# これ以前にも大量のエラーログが出る cc1plus: error: unrecognized command line option ‘-Wno-cast-function-type’ [-Werror] cc1plus: all warnings being treated as errors grpc_node.target.mk:188: recipe for target 'Release/obj.target/grpc_node/ext/channel.o' failed make: *** [Release/obj.target/grpc_node/ext/channel.o] Error 1 # 最後の方に出るmakeのログを見ることで、どのパッケージのビルドに失敗したかが分かる # (repository-nameでgrepすると早く見つかる) make: ディレクトリ '/home/user1/repository-name/node_modules/grpc/build' から出ます gyp ERR! build error gyp ERR! stack Error: `make` failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23) gyp ERR! stack at ChildProcess.emit (events.js:223:5) gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12) gyp ERR! System Linux 4.15.0-74-generic gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "build" "--fallback-to-build" "--library=static_library" "--module=/home/user1/repository-name/node_modules/grpc/src/node/extension_binary/node-v72-linux-x64-glibc/grpc_node.node" "--module_name=grpc_node" "--module_path=/home/user1/repository-name/node_modules/grpc/src/node/extension_binary/node-v72-linux-x64-glibc" "--napi_version=5" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=node-v72" gyp ERR! cwd /home/user1/repository-name/node_modules/grpc gyp ERR! node -v v12.14.1 gyp ERR! node-gyp -v v5.0.5 gyp ERR! not ok node-pre-gyp ERR! build error node-pre-gyp ERR! stack Error: Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js build --fallback-to-build --library=static_library --module=/home/user1/repository-name/node_modules/grpc/src/node/extension_binary/node-v72-linux-x64-glibc/grpc_node.node --module_name=grpc_node --module_path=/home/user1/repository-name/node_modules/grpc/src/node/extension_binary/node-v72-linux-x64-glibc --napi_version=5 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v72' (1) node-pre-gyp ERR! stack at ChildProcess.<anonymous> (/home/user1/repository-name/node_modules/grpc/node_modules/node-pre-gyp/lib/util/compile.js:83:29) node-pre-gyp ERR! stack at ChildProcess.emit (events.js:223:5) node-pre-gyp ERR! stack at maybeClose (internal/child_process.js:1021:16) node-pre-gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5) node-pre-gyp ERR! System Linux 4.15.0-74-generic node-pre-gyp ERR! command "/usr/local/bin/node" "/home/user1/repository-name/node_modules/grpc/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build" "--library=static_library" node-pre-gyp ERR! cwd /home/user1/repository-name/node_modules/grpc node-pre-gyp ERR! node -v v12.14.1 node-pre-gyp ERR! node-pre-gyp -v v0.12.0 node-pre-gyp ERR! not ok調べたこと
ログにあるとおり、grpcのビルドに失敗しています。
(最初は大量のログにとまどいました。どのパッケージがインストールできていないか調べるのが第一歩です)更新対象リポジトリのpackage.jsonにはgrpcの記述がなく、
npm ls
で依存パッケージを調べたところ、firebaseがgrpcに依存していました。$ npm ls # 結果を抜粋 ├─┬ firebase@5.5.7 │ ├─┬ @firebase/firestore@0.8.6 │ │ ├─┬ grpc@1.13.1 <- ここでエラー解決策
執筆時点でfirebaseは7系が最新。単純に古いので、アップデートしたところ解決。
(メジャーバージョン更新による影響も今のところなし)$ npm install -D firebase
エラー2 (node-sassの更新により解消)
エラー1をちょっとひねったパターン。
事象
npm ci
したところ、大量(体感3分)のログが出力され、最後に以下のエラーが吐かれました。# これ以前にも大量のエラーログが出る /home/user1/.node-gyp/12.14.1/include/node/v8.h:3039:5: note: candidate expects 2 arguments, 1 provided binding.target.mk:129: recipe for target 'Release/obj.target/binding/src/create_string.o' failed make: *** [Release/obj.target/binding/src/create_string.o] Error 1 # 最後の方に出るmakeのログを見ることで、どのパッケージのビルドに失敗したかが分かる make: ディレクトリ '/home/user1/repository-name/node_modules/node-sass/build' から出ます gyp ERR! build error gyp ERR! stack Error: `make` failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/home/user1/repository-name/node_modules/node-gyp/lib/build.js:262:23) gyp ERR! stack at ChildProcess.emit (events.js:223:5) gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12) gyp ERR! System Linux 4.15.0-74-generic gyp ERR! command "/usr/local/bin/node" "/home/user1/repository-name/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library=" gyp ERR! cwd /home/user1/repository-name/node_modules/node-sass gyp ERR! node -v v12.14.1 gyp ERR! node-gyp -v v3.8.0 gyp ERR! not ok Build failed with error code: 1調べたこと
ログにあるとおり、node-sassのビルドに失敗しています。
とりあえずググったところ、node-sassは4.12.0でnode.jsに12対応したそうです。更新対象リポジトリのpackage.jsonにはnode-sassの記述がなく、
npm ls
で依存パッケージを調べたところ、gulp-sassがnode-sassの4.11に依存していました。$ npm ls # 結果を抜粋 ├─┬ gulp-sass@4.0.2 │ ├─┬ node-sass@4.11.0 ←ここでエラー(4.12以降にする必要がある)私は最初、この段階で「詰んだ」と勘違いしました。
gulp-sassの依存パッケージを変えるには、gulp-sass公式にissueなりPRなりを投げてpackage.jsonを書き換えなければならないと思ったからです。解決策
明示的にnode-sassをインストールしたところ、nodeがよしなにやってくれました。
$ npm install -D node-sass@4.13.0 # 実行時点での最新バージョン $ npm ls # 結果を抜粋 ├─┬ gulp-sass@4.0.2 │ ├── node-sass@4.13.0 deduped <- 明示的に4.13を入れたところ、nodeが重複パッケージをまとめてくれた上記にdeduped(=重複排除)と表示されていますが、
これはnodeが「バージョン違いの同一パッケージを1つに統合した」ことを表しています。
(今回で言うとnode-sassの4.11, 4.13のうち、より新しい4.13に統合された)この仕様は、今回のようなケースのほかに、
セキュリティ上の脆弱性を持つ孫パッケージ(こういう呼び方があるかは不明)のバージョンを更新したいときにも役立ちます。
(参考: https://cloudpack.media/41572)$ npm ls ├─┬ lib-nobody-update@1.1.0 # 更新が止まっているライブラリ │ ├── lib-something@2.2.0 # 2.3.0で脆弱性が修正されたライブラリ $ npm install -D lib-something@2.3.0 $ npm ls ├─┬ lib-nobody-update@1.1.0 │ ├── lib-something@2.3.0 deduped Llib-something@2.3.0今回初めて知りましたが、なかなかに素敵。
エラー3 (gulpを3系->4系へ移行することで解消)
最後はgulpの話です。
事象
npm ci
実行後、npm run build
したところ以下のエラーが発生。[18:21:08] Requiring external module @babel/register fs.js:27 const { Math, Object } = primordials; ^ ReferenceError: primordials is not defined at fs.js:27:26 at req_ (/home/user1/repository-name/node_modules/natives/index.js:143:24) at Object.req [as require] (/home/user1/repository-name/node_modules/natives/index.js:55:10) at Object.<anonymous> (/home/user1/repository-name/node_modules/vinyl-fs/node_modules/graceful-fs/fs.js:1:37) at Module._compile (internal/modules/cjs/loader.js:955:30) at Module._compile (/home/user1/repository-name/node_modules/pirates/lib/index.js:99:24) at Module._extensions..js (internal/modules/cjs/loader.js:991:10) at Object.newLoader [as .js] (/home/user1/repository-name/node_modules/pirates/lib/index.js:104:7) at Module.load (internal/modules/cjs/loader.js:811:32) at Function.Module._load (internal/modules/cjs/loader.js:723:14) npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! my-package-name@0.0.0 build-gulp: `gulp build` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the my-package-name@0.0.0 build-gulp script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /home/user1/.npm/_logs/2020-01-15T09_21_13_322Z-debug.log ERROR: "build-gulp" exited with 1. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! my-package-name@0.0.0 build: `run-p build-gulp build-client-ts` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the my-package-name@0.0.0 build script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /home/user1/.npm/_logs/2020-01-15T09_21_13_421Z-debug.log調べたこと
一見して何のエラーか分かりませんでしたが、とりあえずエラーメッセージでググったところ
gulp3系がnode12に未対応なのが原因だと判明。gulp4系は対応済み。いっそビルド関連をwebpackに置き換えることも考えましたが、
今回は対応速度を重視してgulpを更新する方針にしました。解決策
以下を参考にgulpを更新しました。
(破壊的変更が多く、そこそこ面倒でした)
- 公式ドキュメント: CommonJS(require)での記載例(英語)
- 公式GitHub: ESModule(import)での記載例(英語)
- 概要を把握しやすかった記事(日本語)
- gulp.task()が非推奨であることに言及した記事(日本語)
要点をかいつまむと、以下のようになります。
- gulp.task()は非推奨になった(この点に触れない記事が多い)
- 後方互換性のため、一応まだ使える
- 代わりに関数をexportするスタイルになった
- タスクの直列実行、並列実行は新関数gulp.series(), gulp.parallel()で制御
// 3系: gulp.task(”タスク名”, タスク用の関数) gulp.task("buildFrontend", () => { /* フロントエンドのビルド処理 */ }); gulp.task("buildBackend", () => { /* バックエンドのビルド処理 */ }); gulp.task("build", ["buildFrontend", "buildBackend"]); // []は並列実行 // 4系: export const タスク名 = タスク用の関数; export const buildFrontend = () => { /* フロントエンドのビルド処理 */ }; export const buildBackend = () => { /* バックエンドのビルド処理 */ }; export const build = gulp.parallel(buildFrontend, buildBackend);3系に比べて可読性があがりましたね。
なお、exportの順番が大切で、自行より下で定義された関数を参照するとエラーになります。(これは微妙)// ダメな例 export const build2 = gulp.parallel(buildFrontend2, buildBackend2); export const buildFrontend2 = () => { /* フロントエンドのビルド処理 */ }; export const buildBackend2 = () => { /* バックエンドのビルド処理 */ }; // 実行すると以下のエラーが出る $ npx gulp build > my-package-name@0.0.0 build /home/duser1/repository-name > gulp build /home/duser1/repository-name/gulpfile.js:10 const build = gulp.parallel(buildFrontend2, buildBackend2); ^ ReferenceError: Cannot access 'buildFrontend2' before initialization at Object.<anonymous> (/home/duser1/repository-name/gulpfile.js:10:29) at Module._compile (internal/modules/cjs/loader.js:955:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10) at Module.load (internal/modules/cjs/loader.js:811:32) at Function.Module._load (internal/modules/cjs/loader.js:723:14) at Module.require (internal/modules/cjs/loader.js:848:19) at require (internal/modules/cjs/helpers.js:74:18) at execute (/home/duser1/repository-name/node_modules/gulp/node_modules/gulp-cli/lib/versioned/^4.0.0/index.js:36:18) at Liftoff.handleArguments (/home/duser1/repository-name/node_modules/gulp/node_modules/gulp-cli/index.js:201:24) at Liftoff.execute (/home/duser1/repository-name/node_modules/liftoff/index.js:201:12) at module.exports (/home/duser1/repository-name/node_modules/flagged-respawn/index.js:51:3) at Liftoff.<anonymous> (/home/duser1/repository-name/node_modules/liftoff/index.js:191:5) at /home/duser1/repository-name/node_modules/liftoff/index.js:149:9 at /home/duser1/repository-name/node_modules/v8flags/index.js:138:14 at /home/duser1/repository-name/node_modules/v8flags/index.js:41:14 at /home/duser1/repository-name/node_modules/v8flags/index.js:53:7 npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! my-package-name@0.0.0 build: `gulp build` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the my-package-name@0.0.0 build script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /home/duser1/.npm/_logs/2020-01-15T10_04_26_061Z-debug.log
まとめ
- バージョン更新は思った以上に大変
- こまめな更新が、バージョン更新のコストを下げる
- npm lsでパッケージの依存関係をチェックできる
- nodeにはdedupeという素敵機能がある
- node12でgulp3系は使えない。4系に移行するか、webpackなど他ツールへ移行する
webpackちゃんと使えるようになりたいです。
- 投稿日:2020-01-16T08:54:30+09:00
npm を使用して、誰かが書いたコードをリユースする方法
npmで誰かが書いたコードを使用する
NPM(Node Package Manager)は、誰かが書いたコードを使用できる便利な管理システム。
自分で1から作るんじゃなくて、誰かが書いたコードを使用できるなら、それをリユースして無駄な時間を削減しようっていう考え方を元に作成された管理システム。
npm を使用するまでの手順
今回は intro-to-node のフォルダ内のindex.jsというファイルでnpmを使用できるようにします。
npm を初期化する
コマンドラインでちゃんと intro-to-node フォルダに移動しているか確認してください。
確認できたら
npm initで初期化します。
色々入力を求められるので、こんな感じで入力していきます。
まぁほとんどコマンドラインの提案通りにEnter押していくだけで、実際入力したのは、description(説明)とauthor(著者)のみ。
すると、package.jsonファイルが intro-to-nodeフォルダに作成されているのがわかります。
ちなみに、package.jsonの中身はこんな感じ。
package.json{ "name": "intro-to-node", "version": "1.0.0", "description": "This is a introduction to node project.", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "kibinag0", "license": "ISC" }npm で使用したいパッケージを選ぶ
npm の公式サイト
(https://www.npmjs.com/)
にいって、使用したいパッケージを選ぶ。今回使うのは、下記のスーパーヒーローの名前を取得してくれるパッケージです。
https://www.npmjs.com/package/superheroes『superheroes name』 と検索したら、出てきました。
使用するパッケージをインストールする
各パッケージには、インストールの部分があるので、コマンドラインを使用してインストールします。
ちゃんと自分が使用するフォルダ(intro-to-node)にいるか確認してから、インストールを実行しましょう。
『npm install パッケージ名』
これでインストールは完了。
パッケージを使用する
使用するときは、パッケージのUsageを見るとわかりやすいです。
index.js// superheroes をファイル内で使用できるようにする const superheroes = require("superheroes"); // Usage に記載されている random() を使用する var hero = superheroes.random(); // ランダムで Super Hero の名前を取得できるこれにてnpmの使用方法まとめ終了です。
このコンテンツはUdemyの The Complete 2020 Web Development Bootcamp を参考にしています。
- 投稿日:2020-01-16T02:16:57+09:00
ネットサークル「TeamKitten」のメンバー管理APIをNodeで書き直した
TeamKittenというインターネット上のサークルのリーダーをやっているTinyKittenです。
最近goa(v1だったかな)で書いていたメンバー管理用APIをNode.js(NestJS)で書き直したことと、エコシステムについて書いていきます。
晩酌中に書いてるので普段以上に文が意味不明になってるかと思いますがご容赦ください。
そもそもなぜ移行したか?
いままでgoaというGolangで書いたDSLをよしなにSwaggerと実装テンプレートに落とし込んでくれるすぐれものを使っていました。が、
突然のアップデートでgo getすらできなくなる
という事態が発生ししばらく安定して動くコードで騙し騙しで動かしていました。
しかし、APIにバグが見つかりどうにも現行コードベースでは修正できないと判断し移行した次第です。goaをアップグレードすればよかったのでは?
それもそうなのですが、goa自体にそれほど固執がなかったのと、チーム内にGolangを書けるメンバーがいなかったのでNode.jsを使ったNestJSフレームワークに白羽の矢が立ったわけです。
それにデザインから書くのが割と面倒だったので。デザインから書くことで助かったことも割と多かったですが、うちのAPIはそこまでクリティカルなものではないので。NestJSとは?
NestJSとは、AngularにインスパイアされたサーバーサイドNode.jsフレームワークです。
Angularにインスパイアされたということで、書き方もほぼAngularです。
仕事でAngularを長年(というほどでもない)使っているので、割とすんなり書ける感じでそこも選ぶ要因の一つでした。スタックはどのように変わった?
goaを使っていたときはGCPを使っていました。なんとなくGoogleに揃えたかったのと、AWSのコンソールが複雑怪奇だと当時思ってたからです。
上記の図の通り、シンプルにすべてのTeamKitten内部サービスからGAEのAPIにアクセスし、バックではデータベースにCloudSQL(MySQL)、オブジェクトストレージにCloudStorageを用いていました。
今はどう変わったかというと、単純にAWSになりました。(ALBとかRoute53も増えてますが...)
このような図はあまり書いたことがなく見づらくて恐縮です。
ポータル、公式サイト、すごいBOT等のエコシステムにAPIをつないでいます。(後述)
費用に関しては、個人的な機械学習に使ったEC2も混じっているのではっきりとは言えませんが、今の時点で\$100程度請求されています。(多分\$30くらいが機械学習)
GCPのときは\$50しませんでした。費用削減の余地はありそう。良かった点は?
仕事ではTypeScript・Angularを扱っているのでスムーズに書ける点でした。
NestJSのドキュメントは割と充実しているので英語さえ多少読めればすぐに扱えます。
テストコードもだいたいAngularっぽいです。(JasmineがJestになってますが)苦労した点は?
仕事柄、GoよりもJavaScript(ここではTypeScript)を扱うことの方が慣れているので、割とサクサク書くことができました。
が、強いて言うならTSLintを怒らせたくないがためにレスポンスのスネークケースをキャメルケースに置き換えたり、最初からデザインから書くわけではないのでSwaggerがまだ整備できていない点でしょうか。(多分クライアントを作るのは自分だけなのでそれほど必要はないですが)エコシステムのポータルとは?
メンバーの方々がログインして、自己紹介・アイコン・スクリーンネーム(ログイン用に使える名前)・カバーイメージなどを自主的に変更できるチーム内サービスです。
EXCメンバー(一般メンバーより偉いメンバー)は他の人のパスワード、担当を変更できたりします。
リーダー権限のメンバー(自分だけ)は、メンバー削除、権限降格・昇格などが可能にしてます。
また、監査という機能を新APIには実装して、誰が誰の情報をいじったかを可視化できるようにしました。これで権限を使って勝手なことをするメンバーがいたとしても、すぐに検出できます。(この機能は上位メンバーのみ見れます)
このサービスは今まではNuxt.jsで書かれていましたが、自分の個人的な趣向とまともなUIフレームワークを欲していたのでIonic 4にしました。
新APIに対応させるために改装中です。エコシステムのすごいBOTとは?
これに関してはチーム内の機密情報なのですが、DiscordのBOTです。まあおもちゃみたいな存在とだけ言います。あとはメンバーの照会ができます。
まとめ
適当に取り留めもなく書いてしまいましたが、Node.js化して正解でした。
メンバーもNode.jsならできるという方もいますし、個人的にもTypeScriptが一番しっくり来るので良かったです。GitHub