爆速でウェブアプリを公開する方法(無料でSSL独自ドメイン)

知ってる人には当たり前かもですが、今回新しいプロジェクトを作成するにあたり、手っ取り早くウェブアプリを公開する方法を模索しました。
素早く公開する方法を調べていて、結局時間がかかっているというのは本末転倒ですね。


フロントエンド

React

何でも良いのですが、慣れてるもので。
ビルドの設定がいつも面倒くさいのですが create-react-app 使いました。Webpackとか開発用のサーバーとかテストとか、設定がほんとに一瞬で終わります。
https://github.com/facebook/create-react-app

Typescript

デフォルトは flow なのですが、今回は typescript で。
flowは遅いなーといつも思ってます。
https://github.com/wmonk/create-react-app-typescript
  
上の2つを組み合わせる手順はこちらが分かりやすいです。
https://github.com/Microsoft/TypeScript-React-Starter#typescript-react-starter
  
create-react-app とか使うとロックインされて逆に将来面倒くさいのでは?と思ってましたが、小さいプロジェクトで存続するかも分からないので、別に気にすることないなと感じました。プロジェクトが大きくなってカスタマイズが必要になっても npm run eject コマンドを叩くだけ。
ただ、ビルドプロセスのメンテを自分でやらないといけなくなるので、気軽に叩くのは止めたほうが良いと思います。

メモ

$ create-react-app --version
1.5.2

このバージョンでやりましたが、いきなりエラーが出たので解消方法。
https://github.com/wmonk/create-react-app-typescript/issues/314
https://github.com/wmonk/create-react-app-typescript/issues/282

package.json
1
2
3
"@types/node": "^9.6.7", // was 10.0.0
...
"test": "react-scripts-ts test --env=jsdom --watchAll", // --watchAll を追加

ホスティング

今まで Heroku 使ってましたが firebase hosting にしました。
無料で独自ドメインを設定することができます。

https://firebase.google.com/docs/hosting/quickstart

もちろんドメインは別途買う必要がありますが、無料でSSLに対応してくれるのが嬉しい。
あ、あとDNSで少しだけお金かかるかもですね。無視できるくらいだと思いますが。

  • ★ 基本は無料
  • ★ 独自ドメイン設定もすごい簡単(しかもSSL)
  • ★ deploy がコマンド1つ

create-react-app の本番ビルドが /build ディレクトリに設定されているので、
設定を少し変更する必要があります。

firebase.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "hosting": {
    "public": "build", // here
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "destination": "/index.html"
    }]
  }
}


サーバーサイド

CloudFunction
https://firebase.google.com/docs/functions/get-started

ホスティングに firebase なので CloudFunction が自然な流れかと。
DBも Firestore でOKです。

1
2
3
$ yarn build
=> フロントをビルド
$ firebase serve

ローカルで実行するときがちょっと面倒なので、ここは改善したいところ。
でも firebase.json の内容を読んで rewrites や redirects の設定を devサーバーに反映させるのは eject しないとちょっと無理そう。
サーバーサイドの開発中に頻繁にフロントを触ることは無いと思うので、まぁここは分離して考えるということで妥協しました。

開発を始めるにあたって、create-react-app の Typescript と CloudFunction の Typescript がうまく共存できないようなことがありました。CloudFunction で yarn build すると、なぜかプロジェクトルート(Reactの方)の node_modules のパッケージ関係でエラーがでる。
tsconfig.json のドキュメント読んでみましたが解決しなかったので、場当たり的ですが、下記のようにして回避しました。

functions/tsconfig.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "compilerOptions": {
    "lib": ["es6", "dom"],
    "module": "commonjs",
    "noImplicitReturns": true,
    "outDir": "lib",
    "sourceMap": true,
    "target": "es6"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

firebase init functions で生成されるファイルを下記のように修正しただけです。

js
1
2
"lib": ["es6"] // was
"lib": ["es6", "dom"] // dom を追加

また、create-react-app の方の tsconfig.json は functions/ を無視するように設定しましょう。

tsconfig.json
1
2
3
4
5
6
{
  ...,
  "exclude": [
    "functions"
  ]
}

ServiceWorker

create-react-app が予め用意してくれてますが SWPrecacheWebpackPlugin が使用されているので workbox 使いたくなります。でも eject はしたくない。

これを使えば workbox でServiceWorker書けます。
https://www.npmjs.com/package/react-app-rewire-workbox

ドキュメント通りにインストールして設定ファイル置いたら、 package.json も編集しましょう。今回は Typescript を使ってるので -scripts-version react-scripts-ts が必要になります。 flow のままなら必要ないですが。

package.json
1
2
3
4
5
6
  "scripts": {
    "start": "react-app-rewired start --scripts-version react-scripts-ts",
    "build": "react-app-rewired build --scripts-version react-scripts-ts",
    "test": "react-app-rewired test --scripts-version react-scripts-ts --env=jsdom --watchAll",
    "eject": "react-scripts-ts eject"
  },

そのうち create-react-app も workbox に乗り換えそうなので、
そうなったらこの手順は不要です。


テスト

create-react-app には最初から jest がセットされてますので

1
$ yarn test

を実行するだけでテストが走ります。
ただこれだと実行中に処理を止めることができないので、新しく package.json にコマンドを追加しましょう。

package.json
1
2
3
4
<!-- filename -->
  "scripts": {
    "test:debug": "react-app-rewired --inspect-brk test --scripts-version react-scripts-ts --env=jsdom --watchAll --runInBand",
  }
  • ★ react-app-rewired の後に --inspect-brk
  • ★ 最後の --runInBand オプションはすべてのテストを同じプロセスで実行させるオプションです

  
あとはコードの中に debugger; を記述して、 yarn test:debug を実行。
chromeのURLバーに chrome://inspect ( about:inspect ) と入力。 inspect をクリックしたらデベロッパーツールが開きます。
  
開いたら勝手に処理が止まってますが、この画面を開くのを待ってくれているだけです。
実行 ▶ ボタンを押して、処理を再開したらdebugger; の所で止まります。

  

スナップショットテスト

コンポーネントが正しくレンダリングされているかを1つずつテストしていっても良いのですが、スナップショットテストが楽ですよね。

下記を追加して npm install します。

package.json
1
2
3
4
5
  "dependencies": {
    "@types/react-test-renderer": "^16.0.1",
    "react-test-renderer": "^16.3.2",
    ...
  }
jsx
1
2
3
4
5
6
7
8
9
import * as React from 'react';
import * as renderer from 'react-test-renderer';
import Hello from './Hello';

test('Hello renders correctly', () => {
  const tree = renderer.create(<Hello name="Shun" level={5} />)
                       .toJSON();
  expect(tree).toMatchSnapshot();
});

yarn test を実行するとスナップショットが作成される。便利ー。
react-scripts-ts 使っているので ts-jest とかを別途設定する必要はありません。

__snapshots__ ディレクトリがコンポーネントと同じ階層に作成されます。この中に入っている内容と、テスト結果が異なったらエラーになるという仕組み。
  
コンポーネントがいろんな階層に入っていてそれらをテストする場合、 __snapshots__ ディレクトリが色んなところにできてしまって、個人的には気持ち悪いです。ルートかどこかにまとめておきたい…。
この件についてはこちらで議論されていますが、進展はない様子。
https://github.com/facebook/jest/issues/1650
  
エラーになったけど、テスト結果のスナップショットの方が正しい場合 u をタイプすることでスナップショットが更新されます。ちゃんとgitに含んでおきましょう。


エディター

Atom

これも何でも良いと思いますがTypescriptとの相性が良いということで Atom。
こちらのプラグインをインストールが必要です。

https://atom.io/packages/atom-typescript

ドキュメントにもありますが、依存関係として atom-ide-ui こちらも apm でイントールを忘れずに。

便利機能

atom-import-js が .ts ファイルをインポートしてくれないので、こちらを使いました。
https://atom.io/packages/typescript-modules-helper

1
2
3
4
5
6
// 一度インポートしたいファイルを開いて
command + shift + P
build index とタイプして実行

// 読み込みたいファイルを開いて、読み込みたいコンポーネントにカーソルをあてた上で、
control + option + M

一度インデックスを作らないといけないのが面倒ですが、まぁそんなに手間でもないかな。
やらなくてもよくなるようにすると書いてありますが、そのまえに atom-typescript が実装するような気もする。

   
以上です。
最初は Webpack の設定とかコツコツやってたから時間がかかってしまった… 結局捨てたし…

次回からはこの流れですぐ作れそう。
  
と思いましたが、実際は案件によりますよね。
Railsと連携して色々やりたい、サーバーサイドレンダリングが必要、とかであればまた変わってくると思います。代替手段としてはこちらを参考に。
https://github.com/facebook/create-react-app/blob/master/README.md#popular-alternatives
  
それではー

  

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた