1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Twitterクローンを作ります #1 プロジェクト作成

Posted at

Twitterクローンを作っていく企画の第1回です。
今回から実際に作業を進めていきます。

※ 今回のコードはこちらで確認できます。

今回はクライアントとAPIサーバのプロジェクトをそれぞれ作成し、通信ができるところまで進めます。

はじめにnodeのバージョンを確認しておきます。

$ npm --version
6.14.12

$ node --version
v14.16.1

クライアント側のプロジェクト作成

クライアント側のプロジェクトを作成します。
/path/to/project/ はプロジェクトのルートディレクトリのつもりです。

$ npm install -g @vue/cli
$ cd /path/to/project/
$ vue create client

プリセットの選択を求められたので Manually select features を選択します。
Babel, Router, Vuex, Linter / Formatter を選択します。
Vue.js のバージョンは 3.x を選択します。
Use history mode for router? は Y を入力しておきます。
linter / formatter の設定は ESLint with error prevention only を選択しておきました。
aditional lint features は Lint on save を選択しました。
設定は In dedicated config files を選択しました。

Vue CLI v5.0.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: Basic
? 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

とりあえず起動してみます。

$ cd client
$ npm run serve

http://localhost:8080 にアクセスすると無事表示されました。

スクリーンショット 2022-02-24 11.24.50.png

APIサーバ側のプロジェクトを作成

まずはディレクトリと、Pythonの仮想環境を作ります。

$ cd /path/to/project/
$ mkdir api
$ cd api
$ python3 -m venv api-env

仮想環境を起動します。

$ source ./api-env/bin/activate

下記の内容で、 requirements.txt を作成します。後で constraints.txt も作成する予定なので、ここではバージョンを指定しません。

requirements.txt
Flask

それではライブラリをインストールします。

$ pip install -r requirements.txt

constraints.txt を作っておきましょう。

$ pip freeze > constraints.txt

僕の環境では以下の様になりました。

constraints.txt
click==8.0.4
Flask==2.0.3
itsdangerous==2.1.0
Jinja2==3.0.3
MarkupSafe==2.1.0
Werkzeug==2.0.3

以後、Pythonのライブラリを追加する際は、requirements.txt にライブラリを追記 → pip install -r requirements.txt -c constraints.txtpip freeze > constraints.txt という流れで requirements.txt と constraints.txt を更新していきます。

ここで .gitignore も作っておきましょう。プロジェクトのルートディレクトリに下記の内容で作成します。

.gitignore
api-env/
__pycache__/

クライアント側については、vue create clientによって client/.gitignore が生成されているので現段階ではapi側の仮想環境を無視するだけで良さそうです。

APIサーバとクライアントの通信

apiディレクトリの直下に下記の内容で main.py を作成します。

main.py
from flask import Flask, jsonify, session

app = Flask(__name__)
app.secret_key = 'DUMMY'

@app.route("/api/hello")
def hello_world():
    if 'count' not in session:
        session['count'] = 0
    session['count'] += 1
    return jsonify({
        'count': session['count'],
        'message': 'hello'
    })

下記で起動できます。仮想環境が起動していないとエラーになるので注意してください。

$ cd /path/to/project/api
$ FLASK_APP=main flask run

この状態で http://localhost:5000/api/hello にアクセスすると {"count":1,"message":"hello"} のような文字列が表示されることが確認できると思います。

ここからは、クライアント側からAPIが呼び出せるか? と その際にセッションを利用できるか? を確認していきます。

まずはAPI呼び出し用のライブラリをインストールしておきます。

$ cd /path/to/project/client
$ npm install axios

client/src/components/HelloWorld.vueを下記のように書き換えてAPI呼び出しを試してみます。

client/src/components/HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>メッセージ : {{ message }}</p>
    <p>カウント : {{ count }}</p>
    <button @click=onClick>push</button>
  </div>
</template>

<script>
import axios from 'axios';
import { ref } from 'vue';

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup () {
    const message = ref('');
    const count = ref(0);
    const onClick = () => {
      axios.get('http://localhost:5000/api/hello')
        .then(res => {
          message.value = res.data.message;
          count.value = res.data.count;
        });
    };
    return {
      message,
      count,
      onClick
    };
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

push と書かれたボタンをクリックするとAPIを呼び出してその内容が画面に表示されるはずですが、実際に押してみても反応がありません。ブラウザの開発者ツール等で確認するとわかりますが、CORSでエラーになっています。
これを解消するには、vue.config.js を下記のように修正します。

vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    proxy: {
      "^/api/*": {
        target: "http://localhost:5000"
      }
    }
  }
})

あと、先程の client/src/components/HelloWorld.vue の onClick を下記のように修正しておいてください。

    const onClick = () => {
      axios.get('/api/hello')
        .then(res => {
          message.value = res.data.message;
          count.value = res.data.count;
        });
    };

この状態でクライアントを起動すると、ちゃんとAPIを呼び出せることとセッションに保存した値がインクリメントされていくことが確認できると思います。

スクリーンショット 2022-02-24 11.30.25.png

今回はここまでです。
次回はログイン周りをやっていこうと思います。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?