tag:crieit.net,2005:https://crieit.net/users/chirunari_6a3bb/feed リリカルはなくそオーガスタの投稿 - Crieit Crieitでユーザーリリカルはなくそオーガスタによる最近の投稿 2021-03-02T16:05:22+09:00 https://crieit.net/users/chirunari_6a3bb/feed tag:crieit.net,2005:PublicArticle/15064 2019-06-06T08:03:42+09:00 2021-03-02T16:05:22+09:00 https://crieit.net/posts/025d5322aa1f0e9d87109ded9b6254b3 短歌投稿サイト「ちるなり」の技術メモ <h2 id="この記事について"><a href="#%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">この記事について</a></h2> <p>「ちるなり|短歌の投稿サイト」の技術的な話のメモです。</p> <h2 id="functionの配列を受け取ってasync.parallelする"><a href="#function%E3%81%AE%E9%85%8D%E5%88%97%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%81%A3%E3%81%A6async.parallel%E3%81%99%E3%82%8B">functionの配列を受け取ってasync.parallelする</a></h2> <p>複雑な処理になると自分でasync/awaitやPromiseをごにょごにょして書くのがつらいことがあるので、よく<a target="_blank" rel="nofollow noopener" href="https://caolan.github.io/async/v3/index.html">caolan/async</a>を使います。このなかの<a target="_blank" rel="nofollow noopener" href="https://caolan.github.io/async/v3/docs.html#parallel">async/parallel</a>はfunctionの配列やオブジェクトを第一引数に、すべてのタスクのあとに実行するコールバックを第二引数に受け取ります。このとき、第一引数に渡されるfunctionはその第一引数としてコールバックをトリガーするfunctionを受け取るのでなければなりません。</p> <p>で、そのようなfunctionの配列を任意のオブジェクトをわたして生成してasync.parallelしたかったときの実装のサンプルです。<a target="_blank" rel="nofollow noopener" href="https://lodash.com/docs/4.17.11#curry">lodash/curry</a>とかを使っています。</p> <pre><code class="js">const express = require("express"); const async = require("async"); const _ = require("lodash"); const router = express.Router(); const admin = require("../admin/admin.js"); const refusers = admin.database.ref().child("users"); // firebaseのRealtimeDBの参照です router.patch("/hogehoge", (req, res) => { const closures = _.partial(function (callback, album) { return _.map(req.body.patches, (patch, key) => { return _.curry(function (callback) { /* 何かの処理 */ callback(null, null); })(callback); }); }); function execClosures (album) { async.parallel(closures(_, album), (err, result) => { res.status(200).end(); }); } refusers.child(req.body.uid).once("value", (snapshot) => { if (snapshot) { const album = snapshot.val(); execClosures(album); } else { res.status(500).send({ err: "No snapshot found" }); } }).catch(err => { res.status(403).send({ err: err }); }); }); </code></pre> <h2 id="HerokuにデプロイしたNuxt.jsのプロジェクトの静的ファイルをFirebase Hostingから配信する"><a href="#Heroku%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%97%E3%81%9FNuxt.js%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%9D%99%E7%9A%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92Firebase+Hosting%E3%81%8B%E3%82%89%E9%85%8D%E4%BF%A1%E3%81%99%E3%82%8B">HerokuにデプロイしたNuxt.jsのプロジェクトの静的ファイルをFirebase Hostingから配信する</a></h2> <p>静的ファイルだけvuepressで生成したページとあわせてHostingにあげます。package.jsonに以下のようなことを書きます。<code>YOUR_TOKEN</code>の部分はfirebase-toolsの<code>login:ci</code>というコマンドであらかじめ取得しておいたトークンに読み替えてください。</p> <pre><code class="json"> "scripts": { "dev": "cross-env NODE_ENV=\"development\" nodemon server/index.js --watch server", "build": "cross-env NODE_ENV=\"production\" nuxt build", "start": "cross-env NODE_ENV=\"production\" forever --killSignal=SIGTERM -c 'nodemon --exitcrash' server/index.js", "inspect": "cross-env NODE_ENV=\"development\" node --require dotenv/config --optimize_for_size --max_old_space_size=920 --gc_interval=100 --inspect server/index.js", "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs", "deploy:nuxt": "rimraf docs/.vuepress/dist/nuxt && mkdirp docs/.vuepress/dist/nuxt && cpy .nuxt/dist docs/.vuepress/dist/nuxt", "deploy:static": "rimraf docs/.vuepress/dist/static && mkdirp docs/.vuepress/dist/static && cpy static/contents docs/.vuepress/dist/static", "deploy:hosting": "firebase deploy --token 'YOUR_TOKEN' --except functions", "deploy:functions": "firebase deploy --only functions", "heroku-postbuild": "yarn build && yarn run docs:build && yarn run deploy:nuxt && yarn run deploy:static && yarn run deploy:hosting" }, "devDependencies": { "cpy-cli": "^2.0.0", "cross-env": "^5.2.0", "dotenv": "^7.0.0", "firebase-tools": "^6.5.3", "forever": "^1.0.0", "mkdirp": "^0.5.1", "nodemon": "^1.18.10", "rimraf": "^2.6.3", "vuepress": "^1.0.0-alpha.47" } </code></pre> <p>nuxt.config.jsでアセットをFirebase Hostingから取得するように設定します。ローカルで開発しているときには手元のファイルを参照したいので、production時のみにしましょう。</p> <pre><code class="js">const isdev = (process.env.NODE_ENV === "development") module.exports = { // buildのところだけ抜粋 build: { publicPath: isdev ? "/_nuxt/" : "https://your_project_name.firebaseapp.com/nuxt", } } </code></pre> <p>firebase.jsonのhostingの設定をします。ヘッダーを設定しないとクロスオリジン制約で配信できなくなるので、ここで必ず設定します。</p> <pre><code class="json"> "hosting": { "public": "docs/.vuepress/dist", "ignore": [ "firebase.json", ], "headers": [ { "source" : "**/assets/**", "headers" : [{ "key" : "Access-Control-Allow-Origin", "value" : "*" }] }, { "source" : "**/nuxt/**", "headers" : [{ "key" : "Access-Control-Allow-Origin", "value" : "*" }] }, { "source" : "**/static/**", "headers" : [{ "key" : "Access-Control-Allow-Origin", "value" : "*" }] }], "cleanUrls": true, "trailingSlash": false }, </code></pre> リリカルはなくそオーガスタ