create-react-appで作ったフロントとFlaskで作ったAPIをつなげる(サーバーをふたつ立ち上げる必要をなくす)方法の備忘録です。
こちらの動画を参考にさせていただきました。
Serving React with a Flask Backend
前提
ツリー構造はこんな感じ。
react-flask-app/
├─Flask-Backend
| ├─static
| ├─templates
| └─app.py
└─React-Frontend
├─public
├─src
├─package.json
└─yarn.lock
app.pyはこんな感じ。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()
Webpack解放
$ cd React-Frontend
$ yarn eject
$ Are you sure you want to eject? This action is permanent. (y/N) y
React-Frontendフォルダの下にconfigフォルダが追加されます。
react-flask-app/
├─Flask-Backend
| ├─static
| ├─templates
| └─app.py
└─React-Frontend
├─config
| └─jest
| ├─env.js
| ├─paths.js
| ├─webpack.config.js
| └─webpackDevServer.config.js
├─public
├─src
├─package.json
└─yarn.lock
paths.js内で、buildフォルダを作成する場所のパスをbuild
からFlask-Backend/static/react
に変更します。
(省略)
module.exports = {
(省略)
appBuild: resolveApp('../Flask-Backend/static/react'),
(省略)
}
webpack.config.js内で、static/js/[name].[chunkhash:8].js
-> js/[name].[chunkhash:8].js
のように、ファイル名のパスがstatic/
から始まっているところを全て消します。
次に、HtmlWebpackPluginオブジェクト内にfilenameを追加し、Flask-Backendフォルダのtemplatesフォルダ下にindex.htmlをビルドするよう指定します。
(省略)
plugins: [
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
filename: '../../templates/index.html' <-- 追加
},
(省略)
)
)
]
package.json内にhomepageの項目を追加し、buildフォルダ(ここではreactフォルダ)を指定します。
{
"homepage": "/static/react",
}
ビルドして立ち上げる
yarn build
でビルドします。staticフォルダとtemplatesフォルダの下にビルド後のファイルが追加されます。
react-flask-app/
├─Flask-Backend
| ├─static
| | └─react
| | ├─css
| | └─js
| ├─templates
| | └─index.html
| └─app.py
└─React-Frontend
├─config
| └─jest
| ├─env.js
| ├─paths.js
| ├─webpack.config.js
| └─webpackDevServer.config.js
├─public
├─src
├─package.json
└─yarn.lock
$ cd Flask-Backend
$ python app.py
http://localhost:5000/ にアクセスします。
以上。
追記: ejectしない方法
yarn eject
してwebpackの設定を弄らずともつなげられるようです。
React-Frontendに移動します。
yarn build
します。
React-Frontend内にbuildフォルダが追加されます。
app.py内でstaticフォルダとtemplatesフォルダのパスを指定します。
from flask import Flask, render_template
app = Flask(__name__, static_folder='../React-Frontend/build/static',
template_folder='../React-Frontend/build')
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()