20190830のNode.jsに関する記事は10件です。

child_process.exec を使ってみた

元ネタは現代の JavaScript チュートリアル

sync_iterator.js
'use strict';

let range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    return {
      current: this.from,
      last: this.to,
      next() {
        if (this.current <= this.last)
          return { done: false, value: this.current++ };
        else
          return { done: true }
      }
    }
  }
}

for (const value of range) console.log(value);
test.js
'use strict';

const assert = require('assert');
const child_process = require('child_process');

describe('Async iterator', () => {
  it('should output sequence', done => {
    child_process.exec('node ./async_iterator.js', (error, stdout) => {
      assert.equal(stdout, '1\n2\n3\n4\n5\n');
      done();
    });
  });
});

参考にしたページ

Child Process | Node.js v12.9.1 Documentation

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

HerokuでExpressのSessionをRedisで管理する

前書き

これは、本を読むのが好きだけど探すのが嫌いな僕が、適当な説明文を書いておけば誰かが勝手におすすめのものを教えてくれる「積んでけ」というサービスを作った際に学んだことを書いているものです。

Herokuにheroku-redisを追加

コマンドでHerokuにAddonを追加

heroku addons:create heroku-redis:hobby-dev

インストール後に以下のコマンドでURLが見えているかを確認

heroku config:get REDIS_URL

インストール

最低限必要なものだけ

npm install --save express
npm install --save express-session
npm install --save redis
npm install --save connect-redis

設定

必要な部分だけ

node.js
const express = require("express");
const session = require("express-session");
const redis = require("redis");
const RedisStore = require("connect-redis")(session);
app.use(
    session({
        store: new RedisStore({
            url: process.env.REDIS_URL,
            client: redis.createClient({
                url: process.env.REDIS_URL
            })
        })
    }),
    ...
);

参考

https://github.com/velizarn/redis-demo

宣伝

もし興味があれば使ってくれると嬉しいです。

積んでけ

世界にはあなたやわたしがまだ出会っていないすばらしいものが無数に存在します。 あなたが知っている素晴らしいものは、だれかが探し続けているものかもしれません。 あなたが探し続けているものは、だれかがすでに素晴らしいと思って使っているものかもしれません。 「積んでけ」はだれもが気軽に軽い気持ちで自分が知っている素晴らしいものを教えあうサービスを目指しています。

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

LINE-Botアプリを開発するにあたっての事前調査メモ

【1】 LINE-Botアプリを運用するために、LINEに対して発生する費用に関して

  • 結論
    • 最終的に、 「Proプラン:32,400円/月」を契約する必要 あり.
      • これは、 1つのLINE-Botアプリ に対して
  • 詳細
    • 開発〜試験運用までは、 LINEへ課金なし で進行可能.
    • 試験運用が終了して、本格的に運用となった場合、以下3つのプランのいずれかでリリース可能.
      1. Freeプラン: 0円/月
      2. Basicプラン: 5,400円/月
      3. Proプラン: 32,400円/月
      4. もちろん、安いプランほど、機能制限が多い.
      5. 以下の「MessagingAPIで利用できる料金プラン」の詳細が記載.
    • 機能制限で、1番のネックは、 メッセージ配信の制限 だと思われる.
      1. Freeプラン: 1,000通 まで無料
      2. Basicプラン: 5,000人 以内はメッセージ数無制限で無料
      3. Proプラン: 100,000人 以内はメッセージ数無制限で無料
    • より多くの人にメッセージ配信を行っていくためには、プロプランの契約が必須.

【2】 LINE-Botアプリの開発工数に関して

  • 要件によって変動はするが、 だいたい1ヶ月〜3ヶ月 の期間でほとんどのLINEアプリは開発できそう.

    • ちょっと主観が入ってるので、一般的かどうかは無視で...
  • 通常アプリとの開発の違い

    • フロント(UI)箇所は、ほぼLINE側でパーツは用意してくれている
      • そのため、フロント実装は、そのパーツの組み合わせ良い.
      • 通常のフロントアプリ開発より工数は少なめ.
    • サーバサイド実装は、通常アプリ同様に独自実装が必要( プログラミング言語は、Javascript(Node.js) )
      • 主にDB制御や、外部サービス連携がメイン
      • 通常のバックエンド開発(API開発)とほぼ同じくらい.

【3】 LINE-Botアプリ上のLINEアカウントの関係性に関して

  • LINE-Botアプリ開発を進めるにあたって、2つのアカウント概念が存在する.

    • 開発者アカウント
    • LINE@アカウント
      • LINE-Botアプリに1対1で対応させておく必要があるアカウント.
      • 管理画面: LINE@ Manager
      • アカウントの開設方法は、 こちら
      • このアカウントの中にも、2つのアカウントの概念が存在する.
        • 一般アカウント :
          • 誰でも登録できるが、LINE-Botアプリの一部機能(グループやトークルーム関係)制限が発生する.
          • このアカウントで登録後も、 認証済みアカウントへ申請可能.
        • 認証済みアカウント :
          • LINEの審査が必要なアカウント
          • 詳細は こちら ![image][82711]
  • したがって、LINE-Botアプリ開発を進めるためには、 開発者アカウント&LINE@アカウントの2つ用意する必要 がある.

    • 開発者アカウントは一度作ってしまえば、2回目以降のアプリ開発で使い回せる.
    • また、機能制限を解除するために、 LINE@アカウントは、承認済みアカウントにする必要 がある.
  • 参考資料: LINE Messaging APIの使い始めで混乱した概念色々

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

LINEボットアプリを開発・運用するにあたっての事前調査メモ

【1】 LINEボットアプリを運用するために、LINEに対して発生する費用に関して

  • 開発〜試験運用までは、 LINEへ課金なし で進行可能.
  • 試験運用が終了して、本格的に運用となった場合、以下3つのプランのいずれかでリリース可能.
    1. Freeプラン: 0円/月
    2. Basicプラン: 5,400円/月
    3. Proプラン: 32,400円/月
      • もちろん、安いプランほど、機能制限が多い.
      • 以下の「MessagingAPIで利用できる料金プラン」の詳細に記載.
  • 機能制限で、個人的に1番のネックだと感じたのは、 メッセージ配信の制限
    1. Freeプラン: 1,000通 まで無料
    2. Basicプラン: 5,000人 以内はメッセージ数無制限で無料
    3. Proプラン: 100,000人 以内はメッセージ数無制限で無料
  • より多くの人にメッセージ配信を行っていくためには、Proプランの契約が必須.

【2】 LINEボットアプリの開発工数に関して

  • 要件によって変動はするが、 だいたい1ヶ月〜3ヶ月 の期間でほとんどのLINEアプリは開発できそう.

    • (個人の主観が入ってるので、一般的かどうかは無視で...)
  • 通常アプリとの開発の違い

    • フロント(UI)箇所は、ほぼLINE側でパーツは用意してくれている
      • そのため、フロント実装は、そのパーツの組み合わせで良い. (※ こだわりがある場合は別)
      • 通常のフロントアプリ開発より工数は少なめ. (※ こだわりがある場合は別)
    • サーバサイド実装は、通常アプリ同様に独自実装が必要( プログラミング言語は、Javascript(Node.js) )
      • 主にDB制御や、外部サービス連携がメイン
      • 通常のバックエンド開発(API開発)とほぼ同じくらい.

【3】 LINEボットアプリ上のLINEアカウントの関係性に関して

  • LINEボットアプリ開発を進めるにあたって、大きく2つのアカウント概念が存在する.
    • 開発者アカウント
    • LINE@アカウント
      • LINEボットアプリに1対1で対応させておく必要があるアカウント.
      • 管理画面: LINE@ Manager
      • アカウントの開設方法は、 こちら
      • このアカウントの中にも、2つのアカウントの概念が存在する.
        • 一般アカウント :
          • 誰でも登録できるが、LINEボットアプリの一部機能(グループやトークルーム関係)制限が発生する.
          • このアカウントで登録後も、 認証済みアカウントへ申請可能.
        • 認証済みアカウント :
          • LINEの審査が必要なアカウント
          • 詳細は こちら

スクリーンショット 2019-08-30 19.02.19.png

  • したがって、LINEボットアプリ開発を進めるためには、 開発者アカウント&LINE@アカウントの2つ用意する必要 がある.

    • 開発者アカウントは一度作ってしまえば、2回目以降のアプリ開発で使い回せる.
    • フル機能を活用するためには、 LINE@アカウントは、承認済みアカウントにする必要 がある.
  • 参考資料: LINE Messaging APIの使い始めで混乱した概念色々

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

【Firebase】素人が個人開発で動画サイトをリリースしたお話

野山のよそおいも日に日に秋めいて、夏も終わりを告げようとしております。

さみしげに鳴くヒグラシに、夏の終わりを深く感じますが、皆様におかれましては、お元気にお過ごしのことと存じます。

さて、この度は今夏の思い出ということで、私事で誠に恐縮ですが、
しがないマーケターがFirebaseを使って動画サイトをリリースしたお話をさせて頂ければと思います。

「夏休みの課題の発表」ぐらいな簡単な気持ちでどうぞお聞きくださいませ。

まず始めに簡単な自己紹介

以下が私の簡単な略歴となります。

防衛省・海上自衛隊(09幹候)→Klab(株)→クックビズ(株)
を経て、今年の4月に独立し、現在はフリーランス(個人)でWebマーケティングのコンサルティングを人材系企業を中心に請け負っております。

今夏リリースしたサイト

採用動画プラットフォーム
「ENLIST(エンリスト) https://enlist.jp

簡単に説明しますと、企業や自治体、官公庁等が採用マーケティングを行う際に、求職者を対象にした動画を制作してYoutubeやVimeoにアップロードしているのですが、そういったアーカイブされた「採用動画」を検索・閲覧できるような動画サイトになります。

サイトの名称に関しては「採用」ということで、「縁」を想起させます。
「縁」となるよう動画が「リスト」として並んでいるので「ENLIST(エンリスト)」と思われる方もいらっしゃるかも知れません。
ですがこれは違います。

「ENLIST」は、日本語で「募兵」を意味します。これが正しいサイト名の由来になります。

TOPページ

FireShot Capture 017 - ENLIST(エンリスト)|採用動画・採用ムービーサイト - enlist.jp.jpg

動画詳細ページ

FireShot Capture 027 - 人力車のえびす屋 採用ムービー|ENLIST(エンリスト) - enlist.jp.jpg

サイト構造について

サイトの構造としては、いたってシンプルです。

  • ページ分割されたTOPページ
    • 新着順の動画リスト
  • 動画詳細ページ
  • カテゴリ別の動画アーカイブリスト
  • タグ別のアーカイブリスト
  • 企業・組織別のアーカイブリスト
  • カテゴリ一覧ページ(実装中)
  • タグ一覧ページ(実装中)
  • 企業・組織一覧ページ(実装中)

SEO上の問題

情報提供が主体となる「メディアサイトにおける最低限必要なSEO」としての要件は満たしていると思いますが、
ただ如何せん動画コンテンツに関しては、Youtube・Vimeo等の外部サイトからクロールしているため、オリジナル性が低いという問題があります。

もちろんオリジナル性を向上させる為に、ログイン機能と動画プレイヤーを作って、企業側で動画を投稿できるように改修を行っていく予定ではあります。

それ以外にも動画詳細ページに更にオリジナルテキストを付与する等の対策は考えていますが、現時点では動画詳細ページへの直接的な検索流入を期待するというよりは、各項目別のアーカイブページへの検索エンジンからのランディングを重要視しています。

著作権的にはどうなの?

動画コンテンツは全て埋め込みの為、著作権的には問題無いと考えています。
ただYotubeの利用規約の中で、

“大量の YouTube 動画を埋め込んだだけで、意図的に広告収入を得ようとするだけのウェブサイトは、利用規約に違反しているものと見なします。”

引用元:YouTubeヘルプ「YouTube ウェブサイトの商用利用が禁止されるケースと許可されるケース」

とあるので、ビジネスとして収益をあげる為には、やはり前述した通り、オリジナル動画の獲得にシフトしなければなりません。

サイト構築の上で使用した技術について

タイトルの通りFirebaseを使ってサーバーレスアーキテクチャを実現しています。
アーキテクチャのベース部分は約2年前に書いた以下の記事である程度は形としてできていたので、それを基にしてひたすら作業を進めていきました。

【Firebase】Cloud Functions + Express + EJSで動的コンテンツを配信する

環境

  • Firestore
  • Cloud Functions or Firebase
  • Firebase Hosting

サーバーサイド

  • Node.js
  • Express
  • EJS

その他

  • moment

作業日数

他に仕事もあったので、これだけにずっと時間を割けた訳では無いのですが、お盆入る前ぐらいから始めて、お盆明けぐらいには、ある程度見せれるぐらいの形になったという感じです。
そこまでで、ざっと約2週間ぐらいでしょうか。

ただ、まずは区切りがつくとこまでやりきってリリースすることを目指していたので、まだまだ機能的にも不十分で、出来ていない部分も多く未完成ではあります。

なぜFirebaseを使用したのか?

それは色々と事情がある訳なんですが、言える範囲でざっとまとめると以下になります。

  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い

とにかくお金と時間がありませんでした。
また、夏が終わる前に必ずリリースすると決めていたので、余計なこと(お金がかかりそうなこと・時間がかかりそうなこと)は一切削ぎ落としました。

時間に関して言えば、元々ある程度FirebaseやGCPの知見があったからで、
もし何も知見が無ければ、どうしても知らないことを調査する為の時間に追われるので、Firebaseを選択していなかったかもしれません。

お金に関して言えば、Firebaseは無料で始めれるのが大きな魅力。
掛かったコストはドメイン代(enlist.jp)と寝不足・不規則な生活・ストレスで肌が荒れないようにする為のビタミン剤ぐらいです。

最初はテストマーケティング的なリリースなので、まずは無料のsparkで良いかなと。
もしsparkで収まらなくなったり、本格的に投資していく段階になれば、FlameプランかBlazeプランに切り替えます。

余談ですが、ドメインに関しては趣味としてサービスを立ち上げる分には、安いドメインでも問題無いと思いますが、
ビジネスとしてやっていく考えがあるのであれば、信用の面から国内向けサービスであれば多少高くても「.jp」を買うことをおすすめします。

Firebaseを使うメリット

当然ながらWebなのかアプリなのか、サービス内容・開発規模等にもよって違いますが、
全てに共通して言えるとすれば、mBaaSという利点から、バックエンドのことを考える必要が無いので、その分やはり開発速度が早いということです。

特に個人開発となるとたった一人でアレもやって、これもやってとなるので、正直めんどくさくなって途中で投げ出したくなるので(自身の経験上)、そういった意味では一定のレベルまで作りきれたのでFirebaseを選んで良かったと思っています。

NoSQLであるFirestoreのデータベース設計に関しては、私自身はRDBもMongoDBの経験も両方あったので、取っ付きにくくさは特に感じず、今回は結構ノリな感じで作りました。

Firestoreの場合、最初の設計がミソとなるのですが、別に駄目だったらスクラップアンドビルドすれば良いという、そんな気持ちにさせてくれる魅力がFirestoreというプロダクトにはありました。(あくまで個人開発での話)

また「Firestore + Cloud Functions + Firebase Hosting + Express + EJS」という組み合わせは非常にシンプルです。

Function側でModelとViewを制御して、日付であったりテキストであったりの細かい処理はEJS側で行いました。

Firebaseを使うデメリット

文句と言えばアレですが、とにかく言いたいことは多々あります。

一つはFirestoreのクエリ機能がとにかく貧弱なことです。それでもRealtime Databaseと比べればだいぶ進化しているのですが、LIKE検索の部分一致が出来ず、今回の開発では、まだフリーワード検索の機能が実現できていません。

全文検索をする為に、AlgoliaやElasticsearchなどのサードパーティの検索サービスを使用するかどうかは、まだ検討中です。

他に問題として挙げたいのは、無料プランの場合、Cloud Functionのメモリが256MB固定で割り当てられているので、Functionの実行速度が遅く感じます。
ログをまだちゃんと見れてないですが、リージョンが「us-central1」だからかどうか、深夜が特に遅く、日中はそうでもありません。

Functionの実行速度で言えば、私のindex.jsのプログラムに問題があるのもそうだと思います。
とにかく急ぎで実装を進めた為、関数の分割もできておらず、グローバル変数化も微妙で、ルーティングを全て1ファイルにぶっこんでいるので、かなり冗長化して見通しが悪いコードであるのは確かです。

なぜ「採用動画サイト」を作ろうと思ったのか?

新卒・既卒含めて、買い手市場の昔と売り手市場である現在とでは、採用における状況が大きく変わり、求職者が企業を選ぶ上での決定的な要素が、給与や勤務時間、福利厚生等の条件が良いのは当たり前の時代となっています。

そんな中で、求職者をどのような点を就職の上で重視するのかと言いますと、例えば企業の雰囲気であったり、自己実現が可能なのかといった、これまでのテキストベースの求人票では可視化しにくい要素がポイントになってきています。

そこで、求めれられてくるのが「採用動画」です。

ただ現在、採用動画を制作する企業は増えてきていますが、アップロード先はYouTubeに限定されています。

現状では「採用動画」に特化したプラットフォームが無いので、求職者を対象にした採用動画を活用したマーケティングが行いにくいという状況があるので、無いのであれば作ってしまおうと至った訳です。

恐らく、しばらくの間は水面ギリギリの低空飛行が続くと思いますが、地道に機能を拡張し、また認知度をあげていければと思います。

今後、拡張予定の機能

今後はざっとですが、可能性を考えると以下のような機能を作っていこうと考えています。
ゆくゆくは動画を軸にした企業と求職者のマッチングサービスにできればと思います。

  • ビュー数カウント
  • いいね・BAD機能
  • 動画投稿機能
  • 動画レコメンド機能
  • 企業側ログイン機能
  • エンドユーザーログイン機能
  • 採用説明会用のLIVE配信機能

ぜひ温かい目で見守っていただけると幸いです。

さいごに

最後までお読みいただき、ありがとうございました。

夏が終わりますね。夏の終わりから、秋にかけての季節が最も人間が創作意欲を掻き立てられる時期と言われているので他にも何かサービスを企画してみようと思います。皆様もいかがでしょうか?

もしご意見・ご質問等がございましたら、TwitterのDMなりでお気軽にご連絡ください。

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

【Firebase】2週間で動画サイトをリリースしたお話【個人開発】

野山のよそおいも日に日に秋めいて、夏も終わりを告げようとしております。

さみしげに鳴くヒグラシに、夏の終わりを深く感じますが、皆様におかれましては、お元気にお過ごしのことと存じます。

さて、この度は今夏の思い出ということで、私事で誠に恐縮ですが、
しがないマーケターがFirebaseを使って動画サイトをリリースしたお話をさせて頂ければと思います。

「夏休みの課題の発表」ぐらいな簡単な気持ちでどうぞお聞きくださいませ。

まず始めに簡単な自己紹介

以下が私の簡単な略歴となります。

防衛省・海上自衛隊(09幹候)→Klab(株)→クックビズ(株)
を経て、今年の4月に独立し、現在はフリーランス(個人)でWebマーケティングのコンサルティングを人材系企業を中心に請け負っております。

今夏リリースしたサイト

採用動画プラットフォーム「ENLIST(エンリスト)」

簡単に説明しますと、企業や自治体、官公庁等が採用マーケティングを行う際に、求職者を対象にした動画を制作してYoutubeやVimeoにアップロードしているのですが、そういったアーカイブされた「採用動画」を検索・閲覧できるような動画サイトになります。

サイトの名称に関しては「採用」ということで、「縁」を想起させます。
「縁」となるよう動画が「リスト」として並んでいるので「ENLIST(エンリスト)」と思われる方もいらっしゃるかも知れません。
ですがこれは違います。

「ENLIST」は、日本語で「募兵」を意味します。これが正しいサイト名の由来になります。

TOPページ

FireShot Capture 017 - ENLIST(エンリスト)|採用動画・採用ムービーサイト - enlist.jp.jpg

動画詳細ページ

FireShot Capture 027 - 人力車のえびす屋 採用ムービー|ENLIST(エンリスト) - enlist.jp.jpg

サイト構造について

サイトの構造としては、いたってシンプルです。

  • ページ分割されたTOPページ
    • 新着順の動画リスト
  • 動画詳細ページ
  • カテゴリ別の動画アーカイブリスト
  • タグ別のアーカイブリスト
  • 企業・組織別のアーカイブリスト
  • カテゴリ一覧ページ(実装中)
  • タグ一覧ページ(実装中)
  • 企業・組織一覧ページ(実装中)

SEO上の問題

情報提供が主体となる「メディアサイトにおける最低限必要なSEO」としての要件は満たしていると思いますが、
ただ如何せん動画コンテンツに関しては、Youtube・Vimeo等の外部サイトからクロールしているため、オリジナル性が低いという問題があります。

もちろんオリジナル性を向上させる為に、ログイン機能と動画プレイヤーを作って、企業側で動画を投稿できるように改修を行っていく予定ではあります。

それ以外にも動画詳細ページに更にオリジナルテキストを付与する等の対策は考えていますが、現時点では動画詳細ページへの直接的な検索流入を期待するというよりは、各項目別のアーカイブページへの検索エンジンからのランディングを重要視しています。

著作権的にはどうなの?

動画コンテンツは全て埋め込みの為、著作権的には問題無いと考えています。
ただYotubeの利用規約の中で、

“大量の YouTube 動画を埋め込んだだけで、意図的に広告収入を得ようとするだけのウェブサイトは、利用規約に違反しているものと見なします。”

引用元:YouTubeヘルプ「YouTube ウェブサイトの商用利用が禁止されるケースと許可されるケース」

とあるので、ビジネスとして収益をあげる為には、やはり前述した通り、オリジナル動画の獲得にシフトしなければなりません。

サイト構築の上で使用した技術について

タイトルの通りFirebaseを使ってサーバーレスアーキテクチャを実現しています。
アーキテクチャのベース部分は約2年前に書いた以下の記事である程度は形としてできていたので、それを基にしてひたすら作業を進めていきました。

【Firebase】Cloud Functions + Express + EJSで動的コンテンツを配信する

環境

  • Firestore
  • Cloud Functions or Firebase
  • Firebase Hosting

サーバーサイド

  • Node.js
  • Express
  • EJS

その他

  • moment

作業日数

他に仕事もあったので、これだけにずっと時間を割けた訳では無いのですが、お盆入る前ぐらいから始めて、お盆明けぐらいには、ある程度見せれるぐらいの形になったという感じです。
そこまでで、ざっと約2週間ぐらいでしょうか。

ただ、まずは区切りがつくとこまでやりきってリリースすることを目指していたので、まだまだ機能的にも不十分で、出来ていない部分も多く未完成ではあります。

なぜFirebaseを使用したのか?

それは色々と事情がある訳なんですが、言える範囲でざっとまとめると以下になります。

  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い

とにかくお金と時間がありませんでした。
また、夏が終わる前に必ずリリースすると決めていたので、余計なこと(お金がかかりそうなこと・時間がかかりそうなこと)は一切削ぎ落としました。

時間に関して言えば、元々ある程度FirebaseやGCPの知見があったからで、
もし何も知見が無ければ、どうしても知らないことを調査する為の時間に追われるので、Firebaseを選択していなかったかもしれません。

お金に関して言えば、Firebaseは無料で始めれるのが大きな魅力。
掛かったコストはドメイン代(enlist.jp)と寝不足・不規則な生活・ストレスで肌が荒れないようにする為のビタミン剤ぐらいです。

最初はテストマーケティング的なリリースなので、まずは無料のsparkで良いかなと。
もしsparkで収まらなくなったり、本格的に投資していく段階になれば、FlameプランかBlazeプランに切り替えます。

余談ですが、ドメインに関しては趣味としてサービスを立ち上げる分には、安いドメインでも問題無いと思いますが、
ビジネスとしてやっていく考えがあるのであれば、信用の面から国内向けサービスであれば多少高くても「.jp」を買うことをおすすめします。

Firebaseを使うメリット

当然ながらWebなのかアプリなのか、サービス内容・開発規模等にもよって違いますが、
全てに共通して言えるとすれば、mBaaSという利点から、バックエンドのことを考える必要が無いので、その分やはり開発速度が早いということです。

特に個人開発となるとたった一人でアレもやって、これもやってとなるので、正直めんどくさくなって途中で投げ出したくなるので(自身の経験上)、そういった意味では一定のレベルまで作りきれたのでFirebaseを選んで良かったと思っています。

NoSQLであるFirestoreのデータベース設計に関しては、私自身はRDBもMongoDBの経験も両方あったので、取っ付きにくくさは特に感じず、今回は結構ノリな感じで作りました。

Firestoreの場合、最初の設計がミソとなるのですが、別に駄目だったらスクラップアンドビルドすれば良いという、そんな気持ちにさせてくれる魅力がFirestoreというプロダクトにはありました。(あくまで個人開発での話)

また「Firestore + Cloud Functions + Firebase Hosting + Express + EJS」という組み合わせは非常にシンプルです。

Function側でModelとViewを制御して、日付であったりテキストであったりの細かい処理はEJS側で行いました。

Firebaseを使うデメリット

文句と言えばアレですが、とにかく言いたいことは多々あります。

一つはFirestoreのクエリ機能がとにかく貧弱なことです。それでもRealtime Databaseと比べればだいぶ進化しているのですが、LIKE検索の部分一致が出来ず、今回の開発では、まだフリーワード検索の機能が実現できていません。

全文検索をする為に、AlgoliaやElasticsearchなどのサードパーティの検索サービスを使用するかどうかは、まだ検討中です。

他に問題として挙げたいのは、無料プランの場合、Cloud Functionのメモリが256MB固定で割り当てられているので、Functionの実行速度が遅く感じます。
ログをまだちゃんと見れてないですが、リージョンが「us-central1」だからかどうか、深夜が特に遅く、日中はそうでもありません。

Functionの実行速度で言えば、私のindex.jsのプログラムに問題があるのもそうだと思います。
とにかく急ぎで実装を進めた為、関数の分割もできておらず、グローバル変数化も微妙で、ルーティングを全て1ファイルにぶっこんでいるので、かなり冗長化して見通しが悪いコードであるのは確かです。

なぜ「採用動画サイト」を作ろうと思ったのか?

新卒・既卒含めて、買い手市場の昔と売り手市場である現在とでは、採用における状況が大きく変わり、求職者が企業を選ぶ上での決定的な要素が、給与や勤務時間、福利厚生等の条件が良いのは当たり前の時代となっています。

そんな中で、求職者をどのような点を就職の上で重視するのかと言いますと、例えば企業の雰囲気であったり、自己実現が可能なのかといった、これまでのテキストベースの求人票では可視化しにくい要素がポイントになってきています。

そこで、求めれられてくるのが「採用動画」です。

ただ現在、採用動画を制作する企業は増えてきていますが、アップロード先はYouTubeに限定されています。

現状では「採用動画」に特化したプラットフォームが無いので、求職者を対象にした採用動画を活用したマーケティングが行いにくいという状況があるので、無いのであれば作ってしまおうと至った訳です。

恐らく、しばらくの間は水面ギリギリの低空飛行が続くと思いますが、地道に機能を拡張し、また認知度をあげていければと思います。

今後、拡張予定の機能

今後はざっとですが、可能性を考えると以下のような機能を作っていこうと考えています。
ゆくゆくは動画を軸にした企業と求職者のマッチングサービスにできればと思います。

  • ビュー数カウント
  • いいね・BAD機能
  • 動画投稿機能
  • 動画レコメンド機能
  • 企業側ログイン機能
  • エンドユーザーログイン機能
  • 採用説明会用のLIVE配信機能

ぜひ温かい目で見守っていただけると幸いです。

さいごに

最後までお読みいただき、ありがとうございました。

夏が終わりますね。夏の終わりから、秋にかけての季節が最も人間が創作意欲を掻き立てられる時期と言われているので他にも何かサービスを企画してみようと思います。皆様もいかがでしょうか?

もしご意見・ご質問等がございましたら、TwitterのDMなりでお気軽にご連絡ください。

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

【夏の終わり】マーケターがFirebaseを使って個人開発で動画サイトをリリースしたお話

野山のよそおいも日に日に秋めいて、夏も終わりを告げようとしております。

さみしげに鳴くヒグラシに、夏の終わりを深く感じますが、皆様におかれましては、お元気にお過ごしのことと存じます。

さて、この度は今夏の思い出ということで、私事で誠に恐縮ですが、
しがないマーケターがFirebaseを使って動画サイトをリリースしたお話をさせて頂ければと思います。

「夏休みの課題の発表」ぐらいな簡単な気持ちでどうぞお聞きくださいませ。

まず始めに簡単な自己紹介

以下が私の簡単な略歴となります。

防衛省・海上自衛隊(09幹候)→Klab(株)→クックビズ(株)
を経て、今年の4月に独立し、現在はフリーランス(個人)でWebマーケティングのコンサルティングを人材系企業を中心に請け負っております。

今夏リリースしたサイト

採用動画プラットフォーム
「ENLIST(エンリスト) https://enlist.jp

簡単に説明しますと、企業や自治体、官公庁等が採用マーケティングを行う際に、求職者を対象にした動画を制作してYoutubeやVimeoにアップロードしているのですが、そういったアーカイブされた「採用動画」を検索・閲覧できるような動画サイトになります。

サイトの名称に関しては「採用」ということで、「縁」を想起させます。
「縁」となるよう動画が「リスト」として並んでいるので「ENLIST(エンリスト)」と思われる方もいらっしゃるかも知れません。
ですがこれは違います。

「ENLIST」は、日本語で「募兵」を意味します。これが正しいサイト名の由来になります。

TOPページ

FireShot Capture 017 - ENLIST(エンリスト)|採用動画・採用ムービーサイト - enlist.jp.jpg

動画詳細ページ

FireShot Capture 027 - 人力車のえびす屋 採用ムービー|ENLIST(エンリスト) - enlist.jp.jpg

サイト構造について

サイトの構造としては、いたってシンプルです。

  • ページ分割されたTOPページ
    • 新着順の動画リスト
  • 動画詳細ページ
  • カテゴリ別の動画アーカイブリスト
  • タグ別のアーカイブリスト
  • 企業・組織別のアーカイブリスト
  • カテゴリ一覧ページ(実装中)
  • タグ一覧ページ(実装中)
  • 企業・組織一覧ページ(実装中)

SEO上の問題

情報提供が主体となる「メディアサイトにおける最低限必要なSEO」としての要件は満たしていると思いますが、
ただ如何せん動画コンテンツに関しては、Youtube・Vimeo等の外部サイトからクロールしているため、オリジナル性が低いという問題があります。

もちろんオリジナル性を向上させる為に、ログイン機能と動画プレイヤーを作って、企業側で動画を投稿できるように改修を行っていく予定ではあります。

それ以外にも動画詳細ページに更にオリジナルテキストを付与する等の対策は考えていますが、現時点では動画詳細ページへの直接的な検索流入を期待するというよりは、各項目別のアーカイブページへの検索エンジンからのランディングを重要視しています。

著作権的にはどうなの?

動画コンテンツは全て埋め込みの為、著作権的には問題無いと考えています。
ただYotubeの利用規約の中で、

“大量の YouTube 動画を埋め込んだだけで、意図的に広告収入を得ようとするだけのウェブサイトは、利用規約に違反しているものと見なします。”

引用元:YouTubeヘルプ「YouTube ウェブサイトの商用利用が禁止されるケースと許可されるケース」

とあるので、ビジネスとして収益をあげる為には、やはり前述した通り、オリジナル動画の獲得にシフトしなければなりません。

サイト構築の上で使用した技術について

タイトルの通りFirebaseを使ってサーバーレスアーキテクチャを実現しています。
アーキテクチャのベース部分は約2年前に書いた以下の記事である程度は形としてできていたので、それを基にしてひたすら作業を進めていきました。

【Firebase】Cloud Functions + Express + EJSで動的コンテンツを配信する

環境

  • Firestore
  • Cloud Functions or Firebase
  • Firebase Hosting

サーバーサイド

  • Node.js
  • Express
  • EJS

その他

  • moment

作業日数

他に仕事もあったので、これだけにずっと時間を割けた訳では無いのですが、お盆入る前ぐらいから始めて、お盆明けぐらいには、ある程度見せれるぐらいの形になったという感じです。
そこまでで、ざっと約2週間ぐらいでしょうか。

ただ、まずは区切りがつくとこまでやりきってリリースすることを目指していたので、まだまだ機能的にも不十分で、出来ていない部分も多く未完成ではあります。

なぜFirebaseを使用したのか?

それは色々と事情がある訳なんですが、言える範囲でざっとまとめると以下になります。

  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い
  • お金が無い
  • 時間が無い

とにかくお金と時間がありませんでした。
また、夏が終わる前に必ずリリースすると決めていたので、余計なこと(お金がかかりそうなこと・時間がかかりそうなこと)は一切削ぎ落としました。

時間に関して言えば、元々ある程度FirebaseやGCPの知見があったからで、
もし何も知見が無ければ、どうしても知らないことを調査する為の時間に追われるので、Firebaseを選択していなかったかもしれません。

お金に関して言えば、Firebaseは無料で始めれるのが大きな魅力。
掛かったコストはドメイン代(enlist.jp)と寝不足・不規則な生活・ストレスで肌が荒れないようにする為のビタミン剤ぐらいです。

最初はテストマーケティング的なリリースなので、まずは無料のsparkで良いかなと。
もしsparkで収まらなくなったり、本格的に投資していく段階になれば、FlameプランかBlazeプランに切り替えます。

余談ですが、ドメインに関しては趣味としてサービスを立ち上げる分には、安いドメインでも問題無いと思いますが、
ビジネスとしてやっていく考えがあるのであれば、信用の面から国内向けサービスであれば多少高くても「.jp」を買うことをおすすめします。

Firebaseを使うメリット

当然ながらWebなのかアプリなのか、サービス内容・開発規模等にもよって違いますが、
全てに共通して言えるとすれば、mBaaSという利点から、バックエンドのことを考える必要が無いので、その分やはり開発速度が早いということです。

特に個人開発となるとたった一人でアレもやって、これもやってとなるので、正直めんどくさくなって途中で投げ出したくなるので(自身の経験上)、そういった意味では一定のレベルまで作りきれたのでFirebaseを選んで良かったと思っています。

NoSQLであるFirestoreのデータベース設計に関しては、私自身はRDBもMongoDBの経験も両方あったので、取っ付きにくくさは特に感じず、今回は結構ノリな感じで作りました。

Firestoreの場合、最初の設計がミソとなるのですが、別に駄目だったらスクラップアンドビルドすれば良いという、そんな気持ちにさせてくれる魅力がFirestoreというプロダクトにはありました。(あくまで個人開発での話)

また「Firestore + Cloud Functions + Firebase Hosting + Express + EJS」という組み合わせは非常にシンプルです。

Function側でModelとViewを制御して、日付であったりテキストであったりの細かい処理はEJS側で行いました。

Firebaseを使うデメリット

文句と言えばアレですが、とにかく言いたいことは多々あります。

一つはFirestoreのクエリ機能がとにかく貧弱なことです。それでもRealtime Databaseと比べればだいぶ進化しているのですが、LIKE検索の部分一致が出来ず、今回の開発では、まだフリーワード検索の機能が実現できていません。

全文検索をする為に、AlgoliaやElasticsearchなどのサードパーティの検索サービスを使用するかどうかは、まだ検討中です。

他に問題として挙げたいのは、無料プランの場合、Cloud Functionのメモリが256MB固定で割り当てられているので、Functionの実行速度が遅く感じます。
ログをまだちゃんと見れてないですが、リージョンが「us-central1」だからかどうか、深夜が特に遅く、日中はそうでもありません。

Functionの実行速度で言えば、私のindex.jsのプログラムに問題があるのもそうだと思います。
とにかく急ぎで実装を進めた為、関数の分割もできておらず、グローバル変数化も微妙で、ルーティングを全て1ファイルにぶっこんでいるので、かなり冗長化して見通しが悪いコードであるのは確かです。

なぜ「採用動画サイト」を作ろうと思ったのか?

新卒・既卒含めて、買い手市場の昔と売り手市場である現在とでは、採用における状況が大きく変わり、求職者が企業を選ぶ上での決定的な要素が、給与や勤務時間、福利厚生等の条件が良いのは当たり前の時代となっています。

そんな中で、求職者をどのような点を就職の上で重視するのかと言いますと、例えば企業の雰囲気であったり、自己実現が可能なのかといった、これまでのテキストベースの求人票では可視化しにくい要素がポイントになってきています。

そこで、求めれられてくるのが「採用動画」です。

ただ現在、採用動画を制作する企業は増えてきていますが、アップロード先はYouTubeに限定されています。

現状では「採用動画」に特化したプラットフォームが無いので、求職者を対象にした採用動画を活用したマーケティングが行いにくいという状況があるので、無いのであれば作ってしまおうと至った訳です。

恐らく、しばらくの間は水面ギリギリの低空飛行が続くと思いますが、地道に機能を拡張し、また認知度をあげていければと思います。

今後、拡張予定の機能

今後はざっとですが、可能性を考えると以下のような機能を作っていこうと考えています。
ゆくゆくは動画を軸にした企業と求職者のマッチングサービスにできればと思います。

  • ビュー数カウント
  • いいね・BAD機能
  • 動画投稿機能
  • 動画レコメンド機能
  • 企業側ログイン機能
  • エンドユーザーログイン機能
  • 採用説明会用のLIVE配信機能

ぜひ温かい目で見守っていただけると幸いです。

さいごに

最後までお読みいただき、ありがとうございました。

夏が終わりますね。夏の終わりから、秋にかけての季節が最も人間が創作意欲を掻き立てられる時期と言われているので他にも何かサービスを企画してみようと思います。皆様もいかがでしょうか?

もしご意見・ご質問等がございましたら、TwitterのDMなりでお気軽にご連絡ください。

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

【LT資料】Node.jsとは?

自己紹介

松田尚也(24)
(一応)二年目エンジニア

最近やったこと・やっていること

  • 金融系のREST APIの開発
  • スマホアプリ設計 / 開発

得意・好き

  • JavaScript
  • Node.js
  • CI/CD (Azure)
  • OAuth2.0/(Open ID Connect)

  • ♡ビール♡
    (最近サッポロビールからアサヒ派になりました)


What is Node.js?


What is Node.js

  1. だいたい ServerSide JavaScript 実行環境
  2. だいたい イベントループ
  3. だいたい ノンブロッキングI/O と 非同期処理

だいたい ServerSide JavaScript 実行環境


ServerSide JavaScript 実行環境

  • 従来ブラウザで動いていたJavaScriptをServerでも動かせるようにした
    WebServer + JavaScript の実行環境がセットになった感じ

  • nodeコマンドを使用できる
    サーバーサイドというよりは、実行環境の提供
    node hoge.js
    これだけで対象ファイルのJavaScriptコードが実行される

  • npm(Node Package Manager)
    非常にかんたんにライブラリ管理を行える


だいたいイベントループ


イベントループ と 背景

Node.jsの開発が開始された2009年

C(クライアント)10K(1万台)問題

クライアントの同時接続数が1万件を超えると、CPU等のリソースは余裕があるにも関わらず、
同時接続のオーバーヘッドにより、速度が遅くなってしまう問題のこと


同時実行(並行処理)の限界

Web及びフロントの発展

Serverに対するリクエスト数が増える

1リクエストに対して1スレッドの処理方式だと、メモリの消費が激しい

結果
1万クライアントを超えると処理が遅くなる


イベントループ

そこで生まれたのがイベントループ
eventLoop.png

  • 一つのスレッドでイベント
  • イベントキューには Node.jsより更に下のOS等がやってくれる処理を登録
    イベントループは常にイベントキューに処理がないか監視し、ある場合は実行する

あれ。。。
遅いんじゃない???


ノンブロッキングI/O と 非同期処理


ノンブロッキングI/O と 非同期処理

同期的なイベントループ方式だと、、、
I/Oが発生するたびに処理がブロック(何もできない状態)されてしまう。


ノンブロッキングI/O と 非同期処理

そこで、ノンブロッキングI/Oな非同期
nonblocking.png

  • I/Oが発生する処理を行うと直ちに処理が返ってくる
  • でも実際には、イベントキューの中で実行待ち状態
  • 実際の処理が終わると、予め処理が終了した際に行うcall back処理が呼び出される

What is Node.js

  1. ServerSide JavaScript 実行環境
  2. イベントループでシングルプロセス
  3. ノンブロッキングI/O で 非同期処理

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

StripeでShared Customerを使ってSubscriptionプラットフォームを作る

Stripe ConnectとStripe Billing

Stripeには、マーケットプレイス、シェアリングエコノミー、プラットフォーム型のビジネスに向けの決済プラットフォームであるStripe Connectというサービスがあります。。例えば、オークションサービスのように出品者と落札者をつなぐサービスで、落札者からの入金を直接出品者に送金することが可能になります。プラットフォームでは、そこからStripeの決済手数料と、プラットフォームの利用手数料を徴収することができます。(Stripe Connectの解説はこの記事などを参照)

また、Subscription(継続課金)を行う為のStripe Billingという機能も用意されています。Stripe Billingは継続課金するサービス(Product)とそのプラン(Plan)を作成して、ユーザに定期的に課金することができます。(Stripe Billingの解説はこちら)

Stripe ConnectとStripe Billingを組み合わせ使うと、Subscriptionを提供するプラットフォームを作り、Stripe Connectを使ってユーザからの課金を、直接お店に送信しつつ、手数料を徴収する仕組みを実装することができます。

前提となるデータ

Stripe ConnectとStripe Billingに出てくるデータのモデルとそのIdは、次のようになります。Stripe Connectの決済フローは、Destination chargeとして、Custom Accountを使う前提で進めます。

  • 課金されるユーザ/お客さん (Customer, CustomerId)
  • 課金するお店/ベンダー (Custom Account, AccountId)
  • 課金する製品/サービス (Product, ProductId)
  • 課金プラン(Plan, PlanId)
  • ユーザと課金プランを紐付けた継続課金(Subscription, SubscriptionId)

最終的に、PlanとCustomerを結びつけたSubscriptionを作成することをゴールとします。

Shared Customer

今回作るSubscriptionプラットフォームサービスは、UberやAirBnBのようなイメージで、利用するユーザ(課金されるユーザ/お客さん)とサービスを提供するユーザ(課金するお店/ベンダー )を直接結びつけ、都度課金ではなく継続課金(Subscription)を行うサービスです。例えば、毎月会費がある複数のクラブやグループを運営するようなサービスをイメージしてください。

Stripe BillingのSubscription機能を使って継続課金をし、Stripe Connectを使って入金されたお金からプラットフォームの手数料を引いて、クラブ/グループ/お店に直接送金します。

このケースでは、Product, Plan, Subscription, Customerの全てに同じAccoountIdを指定する必要があります。また、SubscriptionにはCustomerIdも指定する必要があります。

ここで、CustomerにAccoountIdを指定する必要があるということは、「課金されるユーザ/お客さん」が、「課金するお店/ベンダー」に紐づくということです。Customerと、AccountIdが紐づくと、「課金されるユーザ/お客さん」が、複数の「課金するお店/ベンダー 」が提供するサービスのSubscriptionを利用できないことになります。

ここで、Customerを複数のAccoountIdに紐付けるための「Shared Customer」の登場です。Shared Customerは、作成した「Customer」モデルの決済情報などのデータをそのまま引き継いて別の「Customer」モデルを作成することができます。「Customer」モデルのエイリアスです。
Shared Customerを作成するときに、AccoountIdを指定し、作成したShared CustomerをPlanに紐づけてSubscriptionを作成することで、Customerと、複数のCustom Accountが提供するPlanで継続課金をすることが可能となります。

Shared Customerの詳細はここ

実装

サンプルはNodeのコードです。

ProductとPlan

Subscriptionに必要なProductとPlanを作成します。これらは、Custom AccountのaccountId に紐付けます。

productの作成
export const createProduct = async (name, description, accountId) => {
  const product = await stripe.products.create({
    name: name,
    type: 'service',
    statement_descriptor: description
  }, {
    stripe_account: accountId
  });
  return product;
}
planの作成
export const createPlan = async(amount, name, productId, accoundId) => {
  const plan = await stripe.plans.create({
    amount: amount,
    interval: "month",
    product: productId,
    nickname: name,
    currency: "jpy",
  }, {
    stripe_account: accoundId
  });
  return plan;
};

Shared Customerの作成

Shared Customerを作成するには、customerId, accountIdを使ってcustomer tokenを作成します。そのcustomer tokenのidをcustomer作成時にsourceとして渡します。

CustomerTokenの作成
const createCustomerToken = async (customerId, accountId) => {
  const token = await stripe.tokens.create({
    customer: customerId,
  }, {
    stripe_account: accountId,
  });
  return token;
}
SharedCustomerの作成
export const createSharedCustomer = async(customerTokenId, accountId) => {
  const customer = await stripe.customers.create({
    description: "Shared customer",
    source: customerTokenId,
  }, {
    stripe_account: accountId,
  });
  return customer;
}

上記2つの関数を使って実際にShared Customerを作成します。

sharedCustomerの作成
  const customerToken = await createCustomerToken(customerId, accountId);
  const sharedCustomer = await createSharedCustomer(customerToken.id, accountId);

これで、subscriptionを作成する用意ができました。プラットフォームが徴収する手数料が決済額の10%だとすると、application_fee_percentに10を指定します。Shared CustomerのcustomerIdを使って以下の関数を呼びます。

SharedCustomerの作成
export const createSubscription = async (customerId, plan, accoundId) => {
  const subscription = stripe.subscriptions.create({
    customer: customerId,
    items: [{ plan: plan }],                                                                          
    application_fee_percent: 10,
  }, {
    stripe_account: accoundId
  })
  return subscription;
}

これで、毎月決まった金額を課金して、課金された金額からStripeの手数料とプラットフォームへの手数料を引いた金額がCustom Accountのユーザに送金されるようになります。

謝辞

SubscriptionとBillingが同時に使えないことに気がついて、StripeのUSのサポートチームに質問したところ、Shared Customerについて詳しく教えていただきました。ありがとうございます!!Stripeは丁寧にサポートしてくれるので、何かあれば問い合わせするのがおすすめです。

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

TypeScriptで書いてwebpackでビルドしたjsファイルのエラーをわかりやすくする

Why

webpackでバンドルしてるのでスタックトレースを見てもtsファイルでのエラー箇所がわからない・・ :tired_face:

What

node-source-map-supportをインストールして、tsconfig.json, webpack.config.jsを修正します :muscle:

node-source-map-supportのインストール

$ npm install source-map-support

tsファイルの修正

webpackのエントリポイントにしているtsファイルに以下を追加します。

app.ts
import sourceMapSupport from 'source-map-support'
sourceMapSupport.install()

設定ファイルの修正

webpack, TypeScriptの設定ファイルを修正します。

webpack.config.js
module.exports = {
    mode: 'development',
    target: 'node',
+   devtool: 'inline-source-map',
    ...
}

↑ちなみに、 devtool: 'inline-source-map'でも動きました。

tsconfig.js
{
  "compilerOptions": {
+   "sourceMap": true
   ...
  }
}

これで、webpackでビルドし直すと、エラー時にtsファイルの行数も教えてくれるようになりました :tada:

こんなかんじ :point_down: (app.tsの73行目でエラーになってることがわかる)

at Object.<anonymous> (/path/to/project/dist/webpack:/src/app.ts:73:4)

以上です :hugging:

参考

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