7
7

More than 3 years have passed since last update.

Vue.jsのSPAをFlaskのバックエンドで支えて、Herokuで動かす!

Posted at

前提

開発環境

  • mac OS X
  • Python 3.7.1
  • pip 19.3.1
  • Pipenv, version 2018.11.26 (インストール:python -m pip install pipenv)
  • Flask
  • Node.js v10.16.0
  • Vue.js (@vue/cli v4.1.2)
  • Herokuのアカウント、あるよ。

ディレクトリ構成の目標

[approute] 
   |-- [server] -- サーバーサイド(Flask app)
   |-- [client] -- クライアントサイド(Vue app)
   `-- サーバー起動にまつわる設定ファイル

サーバーサイドの準備

仮想空間の作成

$ pipenv install flask

→プロジェクト用の仮想空間&[Pipfile][Pipfile.lock]ファイルが作成される

[approute]
   |-- Pipfile
   `-- Pipfile.lock


(pc)Users/xxxxxx/virtualenvs/xxxxxxx

Flask appのシンプルな内容のコードを取り急ぎ置いてみる

HOME URLにやってきたら「Hello world」って返すだけ。

approute/server/main.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    hello = "Hello world"
    return hello

if __name__ == "__main__":
    app.run(debug=True)

仮想空間で実行するscriptを作成

packageは仮想空間にあるので、そちらを実行するようなスクリプトを作成

approute/Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
flask = "*"

[requires]
python_version = "3.7"

[scripts]                          //←追記
start = "python server/main.py"    //←追記

$ pipenv run start で実行できるようになる

Herokuにdeploy

gunicornをインストール

HerokuのPythonサポートはgunicornというWEBサーバーを通して行なっている様です。

https://devcenter.heroku.com/articles/python-gunicorn

ということで $ pipenv install gunicorn

approute/Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
flask = "*"
gunicorn = "*"   //←ここが追記された

[requires]
python_version = "3.7"

[scripts]
start = "python server/main.py"

そして、実行スクリプトを記載。server/main.pyのappを実行するには、↓のように書く

approute/Procfile
web: gunicorn server.main:app --log-file -

一応、ローカルでも$ gunicorn server.main:appで実行確認してみる

Herokuでapp作成

Heroku( https://jp.heroku.com/ )でアカウントを作成して、appも作成。
そしたらdeploy手順が掲載されているので、順次実行していく。

$ heroku login  // Herokuにログイン
$ cd approute //作業ルートに移動
$ git init   //git初期化
$ heroku git:remote -a hogehoge   //Herokuにリモートレポジトリ
$ git add .  
$ git commit -am "make it better"  //gitにコミット
$ git push heroku master  //Herokuにpush
$ heroku open //デプロイしたアプリを開く

Herokuにデプロイしたappから「hello world」言われました。
世界が開けたようです。よかったよかった。

クライアントアプリを作成

Vue UIでプロジェクトを作成

Vue UI、使いやすいので活用しようと思います。

z.png

Y.png

↑今回はアプリルートのgit使っているのでoffります。

これ以降のプリセットとかはとりあえず好きにすればいいと思う。
SPAなので、Routerは必須。

そしたら、しばらくダウンロードとかで待つと。。。
できあがるので、↓の画面から実行スクリプトも実行できますよと。

x.png

SPA

クライアントサイドでSPA作る

Vue UIの「プロジェクト設置>Vue CLI>アセットディレクトリ」からでも、
主導で設定ファイルを作ってでもいいので、staticファイルの書き出し先をstaticに設定。

approute/client/vue.config.js
module.exports = {
  assetsDir: 'static'
}

で、Vue UIでも、termimnalでもいいから、$ npm run buildを実行→appがコンパイルされる

[approute] 
   |-- [client] 
      |--[dist]   //←生成される
         |--[static]   //←jsとか書き出される
         `--index.html   //←rootのHTMLができる
      |--[public]
      |--[src]
      |--vue.config.js
      `--その他設定ファイル

サーバーサイドでクライアントアプリをテンプレートとして設定

結論として、こんな感じに書き換えます。

approute/server/main.py
import os
from flask import Flask, render_template

app = Flask(__name__, static_folder='../client/dist/static', template_folder='../client/dist')

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template('index.html')


if __name__ == "__main__":
    app.run()

ちっと分解。

from flask import Flask, render_template

    return render_template('index.html')

↑Flaskのrendar_templateを追加しまして、Vueのapp側で書き出したルートファイルである[index.html]をセットします。

app = Flask(__name__, static_folder='../client/dist/static', template_folder='../client/dist')

↑Vueのapp側で書き出したstaticファイルの場所をこのファイルから見た相対パスで書きます。

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):

↑どんなURLパスでやってきても、こちらで受け止めます、な感じ。

pipenv run start → お、世界に色が宿りました。

改めて、Herokuにpush

$ git add .  
$ git commit -am "color from vue"
$ git push heroku master
$ heroku open

してみたら、、
500 Internal Server Error

jinja2.exceptions.TemplateNotFound: index.html

とのことで、ローカルでは見つかっていたVueによって生成されたindex.htmlが見つからない...ってことですかね?
世界が闇に包まれました。

Herokuにdeploy・改

複数のbuildpackに対応する

すでに、pipfileによって、自動的にpythonサーバーが起動する。
そこに、node.jsサーバーもたちあげたい。

$ heroku buildpacks:add --index 1 heroku/nodejs

$ heroku buildpacks
=== xxx Buildpack URLs
1. heroku/nodejs
2. heroku/python

で、このまま起動しても

remote:  !     The 'heroku/nodejs' buildpack is set on this application, but was
remote:  !     unable to detect a Node.js codebase.
remote:  !         
remote:  !     A Node.js app on Heroku requires a 'package.json' at the root of
remote:  !     the directory structure.

と言われるわけで、package.jsonをルートに持ってこいと言われます。

Vue.jsのアプリのディレクトリ構造を変更する

いったん書き出していた[dist]ディレクトリを削除して、[client]ディレクトリの中身をまるっとルートに移動させる

[approute] 
   ===Flask===
   |--[server] -- main.py 
   |--Pipfile
   |--Procfile
   |--その他設定ファイル
   ===Vue.js===
   |--[public]
   |--[src]
   |--package.js
   |--babel.config.js
   |--vue.config.js
   `--その他設定ファイル

それにともなって、書き換え

approute/server/main.py
app = Flask(__name__, static_folder='../dist/static', template_folder='../dist')

Herokuにpushしてみたら、動いた!世界に光が戻りました。
ということで、このベースの世界から発展開発をしていきたいと思います。

結論

とりあえず、やったことを書いてみましたが。。
あったんだよね、先人の知恵
https://github.com/gtalarico/flask-vuejs-template
https://github.com/oleg-agapov/flask-vue-spa

なんか、ディレクトリ構成がね〜。
vue.config.jsとか設定して、1段掘れないかしら。

参考

FlaskとVue.jsでSPA Webアプリ開発
Heroku 複数ビルドパックの使い方

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7