Help us understand the problem. What is going on with this article?

Vue.js とCloud Functions for Firebase をFirebase Hostingへデプロイするための環境構築手順

前置き

Qiitaに Vue.jsFirebaseCloud Functions for Firebase などの記事を書いてて、ツールのセットアップや環境構築を都度継ぎ足してきたのですが、一度に構築する方法が整理できてなかったので、メモっておきます。

本記事で説明が足りないところは、適宜下記の記事を見ていただくとよいかもしれません。

コレをやったらできること

  • Vue.jsのコマンドラインツールとFirebaseのコマンドラインツールがインストールできます
  • Vue.jsのプロジェクトをローカルのWEBサーバで動かせます(npm run dev 上で)
  • Vue.jsのプロジェクトをFirebaseのローカルWEBサーバで動かせます
  • Cloud FunctionsをFirebaseのローカルWEBサーバで動かせます
  • Vue.jsのプロジェクトをFirebase Hostingにデプロイできます
  • Cloud FunctionsをFirebaseへデプロイできます
  • Cloud FunctionsをHostingのドメインで呼び出す事ができます

2020/07/18 追記
改訂前の記事 では vue/cli のバージョンが 2.9.6 向けだったのですが、新しいバージョン向け(2020/07/18時点の最新 4.4.6) に多少書き直しました

前提環境

%  sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.5
BuildVersion:   19F101

% node --version
v10.19.0    <-ホントはFunctionsとかのバージョンに合わせるべきなんだけどいったん気にしない :-)

準備

コマンドラインツール達のインストールと、Firebaseへのログインなど。あ、Firebaseはサインアップ済みってことで、、、。

vue コマンドラインツールのインストール

vue-cli というVue.jsのテンプレを生成してくれるコマンドラインツールをインストールします。
公式: https://cli.vuejs.org/

% npm install -g @vue/cli
% source ~/.zshrc
% vue --version
@vue/cli 4.4.6

よさそうですね。

firebase-toolsのインストール

firebaseのコマンドラインツール。

% npm install -g firebase-tools
% source ~/.zshrc
% firebase --version
8.6.0

Firebaseにログイン

% firebase login
? Allow Firebase to collect anonymous CLI usage and error reporting information?
 No

Visit this URL on any device to log in:
https://accounts.google.com/o/oauth2/auth?client_id=...   // OAuthでアクセスの認可まち

Waiting for authentication...

✔  Success! Logged in as masatomix@example.com

やってみる

まずは プロジェクト全体の作成

メインとなるプロジェクトは Vue.jsのコマンドラインツールで作成します。

% vue create fb_vue_template

↓ とりあえず下記の通りManuallyでやってみた

Vue CLI v4.4.6
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Linter
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No

Vue CLI v4.4.6
✨  Creating project in /Users/masatomix/git/fb_vue_template.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

....

41 packages are looking for funding
  run `npm fund` for details

🚀  Invoking generators...
📦  Installing additional dependencies...

...

📄  Generating README.md...

🎉  Successfully created project fb_vue_template.
👉  Get started with the following commands:
 $ cd fb_vue_template
 $ npm run serve

%

完了しました。

Vue.jsの Hello World を表示

最後にcd fb_vue_template,npm run serve とでてましたので、その通りに。。

% cd fb_vue_template
% npm run serve

> fb_vue_template@0.1.0 serve /Users/masatomix/git/fb_vue_template
> vue-cli-service serve

 INFO  Starting development server...
98% after emitting CopyPlugin

 DONE  Compiled successfully in 7310ms                       10:00:05 AM


  App running at:
  - Local:   http://localhost:8080/
  - Network: http://192.168.xx.xx:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

さて、メッセージ通りにブラウザで http://localhost:8080 をひらいてみます。
image.png

よさそうですね。。問題なければ、プロンプトは Ctrl-c で終了ておきましょう。

Firebase関連情報を設定

さて Firebase関連です。

Firebase Hosting設定

まずはこの Vue.js プロジェクトをサーバへデプロイするためのHosting設定を行います。

$ pwd
/xxx/xxxx/fb_vue_template
$ firebase init hosting

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /xxx/xxxx/fb_vue_template


=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

? Select a default Firebase project for this directory: hoge-xxxx (hoge)
i  Using project hoge-xxxx (hoge)

↑ デプロイしたい先のプロジェクトを選びます


=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? dist

↑ public?って聞いてきますが、vue.jsのプロジェクトが出力する先「dist」を選択します。


? Configure as a single-page app (rewrite all urls to /index.html)? Yes
✔  Wrote dist/index.html

SPAで作成するので、Yesを選択します。
サーバにデプロイした際、どのURLを叩いてもindex.html を表示するよっていう設定になります。

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!
$

$ cat firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"  
        # サーバにデプロイした際、どのURLを叩いてもindex.html を
        # 表示するよっていう設定。
      }
    ]
  }
}
$

サーバにデプロイするための設定が追加されました。

Cloud Functions 設定

つづいてバックエンド機能となる、Cloud Functions の設定を行います。

$ pwd
/xxx/xxxx/fb_vue_template
$ firebase init functions

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:
  /xxx/xxxx/fb_vue_template
=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.


? Select a default Firebase project for this directory: hoge-xxxx (hoge) ← 使用するプロジェクト選択
? What language would you like to use to write Cloud Functions? TypeScript   ← TypeScriptをえらんでみた
? Do you want to use TSLint to catch probable bugs and enforce style? Yes    ← Yesをえらぶ
? Do you want to install dependencies with npm now? Yes

✔  Firebase initialization complete!
$
$ cat firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  }
}

Functionsの設定が追加されましたね。よさそうです。

最終的に、ディレクトリ構成は以下のようになりました。

% tree -a
.
├── .browserslistrc
├── .eslintrc.js
├── .firebaserc
├── .gitignore
├── README.md
├── babel.config.js
├── dist
│   └── index.html
├── firebase.json
├── functions
│   ├── .gitignore
│   ├── package-lock.json
│   ├── package.json
│   ├── src
│   │   └── index.ts
│   ├── tsconfig.json
│   └── tslint.json
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   └── index.html
└── src
    ├── App.vue
    ├── assets
    │   └── logo.png
    ├── components
    │   └── HelloWorld.vue
    └── main.js

36 directories, 80 files
%
(適度に整形)

ビルド

初回のセットアップである程度ビルドや 外部ライブラリのインストールなどは済んでるんですが、一応 ライブラリのインストールとビルドまでの手順を書きます。

Firebase Hosting 側

% pwd
/xxx/xxxx/fb_vue_template
% npm install    ← こちらは外部ライブラリを再度入れるときだけ実施
% npm run build  ← こちらはVue.js側のコードをいじったら毎回実施
% ls -lrt dist
total 24
drwxr-xr-x  3 masatomix  staff    96  7 18 10:12 img
-rw-r--r--  1 masatomix  staff   738  7 18 10:12 index.html
drwxr-xr-x  3 masatomix  staff    96  7 18 10:12 css
-rw-r--r--  1 masatomix  staff  4286  7 18 10:12 favicon.ico
drwxr-xr-x  6 masatomix  staff   192  7 18 10:12 js

distディレクトリに ビルドされたファイル群ができました。

Cloud Functions 側

$ pwd
/xxx/xxxx/fb_vue_template
$ cd functions

ビルドするとき、プロジェクト初期状態の index.ts だと、関数がないためにエラーとなってしまうので、下記の通りコメントを外しておきます。

$ cat src/index.ts
import * as functions from 'firebase-functions';

// // Start writing Firebase Functions
// // https://firebase.google.com/docs/functions/typescript
//
export const helloWorld = functions.https.onRequest((request, response) => {
 response.send("Hello from Firebase!");
});

$ npm install    ← こちらは外部ライブラリを再度入れるときだけ実施
$ npm run build  ← こちらはfunctionsのtsコードをいじったら毎回実施
$ ls -lrt lib/
total 16
-rw-r--r--  1 xxx  staff  296  3  5 13:39 index.js.map
-rw-r--r--  1 xxx  staff  380  3  5 13:39 index.js
$
$ cd ../

こちらは「lib」のディレクトリに ビルドされたファイル群ができました。

ローカルのWEBサーバ起動

以下のコマンドで、ローカルのWEBサーバ上で起動します。

$ pwd
/xxx/xxxx/fb_vue_template
$ firebase serve --only hosting,functions

=== Serving from '/xxx/xxxx/fb_vue_template'...

i  functions: Preparing to emulate functions.
i  hosting: Serving hosting files from: dist
✔  hosting: Local server: http://localhost:5000
Warning: You're using Node.js v10.14.2 but Google Cloud Functions only supports v6.11.5.
✔  functions: helloWorld: http://localhost:5001/hoge-xxxx/us-central1/helloWorld

ブラウザで、http://localhost:5000 へアクセスすると、先ほどのVue.jsの画面が表示されると思います。またcurlで curl http://localhost:5001/hoge-xxxx/us-central1/helloWorld とアクセスしてfunctionsを呼び出してみましょう。

$ curl http://localhost:5001/hoge-xxxx/us-central1/helloWorld
Hello from Firebase!
$

OKそうですね。。Ctrl-c で終了しておきましょう

Functionsの関数達を Hosting のドメイン経由で処理できるようにする

サーバにデプロイしたときのFirebase Hostingのドメイン(URL)と、Cloud Functions が使用するドメインは異なっています。具体的には、

Firebase Hosting: https://hoge-xxxx.firebaseapp.com/
Cloud Functions: https://us-central1-hoge-xxxx.cloudfunctions.net/

とかになったりします。HostingしたWEBアプリからCloud Functions の関数を呼び出すときにドメインが異なっていると、CORSの考慮やURLをフルパス指定しないといけないなど何かとメンドウなので、HostingのURLでアクセス出来るようHostingのリバースプロキシを有効にします。

具体的には以下の通り firebase.json に設定を追加します。

firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/hello",   # /hello にきたら、
        "function": "helloWorld"   #functionsの helloWorld 関数へ転送
      }, 
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  }
}

rewrites にリバースプロキシの設定を追加しました。 "source":"**" の設定よりも先に書いてるのがポイントです(後に書くと、**が優先されちゃう)。

さて、ローカルのWEBサーバをもいちど起動します。

$ firebase serve --only hosting,functions

疎通します。

$ curl  http://localhost:5000/hello
Hello from Firebase
$

これでHostingとCloud Functionsがおなじドメインとなりました。

"source": "/hello" の箇所は "source": "/hello/**" などとかけるので、必要なパラメタに応じて適宜工夫するのがよさそうです。

サーバにデプロイする

ココまでできていれば、サーバへのデプロイも簡単です

$ pwd
/xxx/xxxx/fb_vue_template
$ firebase deploy --only hosting,functions

... 割愛

✔  functions[helloWorld(us-central1)]: Successful create operation.
Function URL (helloWorld): https://us-central1-hoge-xxxx.cloudfunctions.net/helloWorld
i  hosting[hoge-xxxx]: finalizing version...
✔  hosting[hoge-xxxx]: version finalized
i  hosting[hoge-xxxx]: releasing new version...
✔  hosting[hoge-xxxx]: release complete

✔  Deploy complete!

Please note that it can take up to 30 seconds for your updated functions to propagate.
Project Console: https://console.firebase.google.com/project/hoge-xxxx/overview
Hosting URL: https://hoge-xxxx.firebaseapp.com
$

表示されたサーバに アクセスしてみましょう。

ブラウザで: https://hoge-xxxx.firebaseapp.com
curlで: https://us-central1-hoge-xxxx.cloudfunctions.net/helloWorld
curlで: https://hoge-xxxx.firebaseapp.com/hello

いままでおなじ結果が得られればOKです。

ビルド手順まとめ

$ pwd
/xxx/xxxx/fb_vue_template

プロジェクトがココに展開されている想定で、コマンドを整理しておきます。

Hosting側(Vue.jsのWEBアプリ)

ビルド

$ cd /xxx/xxxx/fb_vue_template
$ npm run build

ローカルWEBサーバ起動(事前にビルド要)

$ cd /xxx/xxxx/fb_vue_template
$ firebase serve --only hosting
カンマ区切りで、functionsもならべられる

デプロイ(事前にビルド要)

$ cd /xxx/xxxx/fb_vue_template
$ firebase deploy --only hosting
カンマ区切りで、functionsもならべられる

Cloud Functions

ビルド

$ cd /xxx/xxxx/fb_vue_template
$ cd functions && npm run build && cd ../

ローカルWEBサーバ起動(事前にビルド要)

$ cd /xxx/xxxx/fb_vue_template
$ firebase serve --only functions

デプロイ

$ cd /xxx/xxxx/fb_vue_template
$ firebase deploy --only functions
ちなみにfunctionsは、deploy時に自動で再ビルドが走るので、事前にビルドは不要

おつかれさまでした。

関連リンク

公式

いままで書いたVue.js/Firebase関連記事

masatomix
JavaEEの開発やリッチクライアント開発のアーキテクトが専門でしたが、最近はRPAとAIがメイン。。。RPAはUiPathとOrchestratorの構築が中心です。 FirebaseとかOAuth/OIDCなど新しいモノ、あと数学もすき。 最近は UiPath Friends っていうユーザコミュニティにも関わってます。 あ、UiPath Japan MVP 2019,2020 す。
primebrains
プライム・ブレインズは、マネジメントスキルだけでなく、最新のITスキルを兼ね備えた技術者がお客様の立場でお客様と共に、成功に向けてプロジェクトを推進します。
http://www.primebrains.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away