LoginSignup
22
34

More than 3 years have passed since last update.

DjangoとVue.js(Vue CLI)を一緒に使ってSPAを作る

Last updated at Posted at 2019-06-06

ゴール

  • バックエンドでDjango、フロントエンドでVue.jsを使いたい。
  • 単一ファイルコンポーネントを使いたい。
  • SPAを使う

流れ

  1. Vueを使えるようにする
  2. Djangoを使えるようにする
  3. Vueのビルド時、生成されたファイル群がDjangoの適切な場所に吐き出されるように調整する

ファイル構成

第1階層 第2階層 第3階層 第4階層 説明
django-vuejs/ DjangoとVueを一緒に入れる
django_project/ $django-admin startprojectで作ったプロジェクトファイル群
django_app/ $python manage.py startapp で作ったアプリケーションファイル群
templates/ Djangoのルール上テンプレートを格納するディレクトリ
static/ djangoプロジェクトで使うstaticファイル格納場所
vuejs/ $vue generateで作ったファイル

webpackは?

単一ファイルコンポーネントを使うとファイルがむちゃくちゃ増えるからwebpackが必要なのだと思ったけど
Vue CLIには含まれているっぽいので、わざわざインストールしなくていいっぽい。

$vue create xxx
を実行して自動で作られたpackage.jsonを見ると

{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

ビルドするコマンドが入っており、実行するとwebpackさながらのファイルが出力される。

作業ディレクトリの準備

$mkdir django-vuejs
ディレクトリ作ります。

$cd django-vuejs
作ったディレクトリに移動します。

Vueの準備

$vue create vuejs
vue createします。ディレクトリ名を「vuejs」としました。

Vue CLI v3.8.2
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors, Linter
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (w
ith dart-sass)
? Pick a linter / formatter config: Basic
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lin
t on save
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In package.json
? Save this as a preset for future projects? Yes
? Save preset as: 

Enter連打でも構わないと思いますが、Manually select featuresを選択してRouterやVuexも追加しておきます。
「↑」「↓」で移動、「スペースキー」で有効/無効を選択できます。

インストールが終わったらdjango-vuejs/vuejs/に移動して$npm run serveしてみます。

Djangoの準備

$django-admin startproject django_project
Djangoのプロジェクト作ります。プロジェクト名は「django_project」としました。

$cd django_project
django_projectディレクトリに移動して

$python manage.py runserver
動くか試してみます。
migrateしてないのでエラーがでますが、サーバー自体は立ち上がります。

$mkdir static
続いて/django-vuejs/jango_project直下にstaticディレクトリを作ります。
ここにVue側で$npm run buildした時に作られるimg,css,jsを格納するようにします。

$python manage.py startapp django_app
/django-vuejs/django-project/配下にDjangoのアプリケーション作ります。
アプリケーション名は「django_app」としました。

/django-project/django-project/settings.pyのINSTALLED_APPSに今作ったアプリケーションを追加

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_app' //←これを追記
]

続いて

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

staticファイルの場所の設定も追記します。

$cd django_app
django_appディレクトリ内に移動して

$mkdir templates
templatesディレクトリを作ります。
Djangoの仕様上、templatesディレクトリは勝手にテンプレート格納場所だと認識されます。
ここに$npm run buildした時に作られるindex.htmlを格納します。

これからやること

DjangoとVueの準備ができたので、これらを連携します。

Vueのpackage.jsonを編集

ビルド時の出力先を変更する

Vueの$npm run buildは初期設定のままだとdistというディレクトリを作り、その中にindex.html,js,css,img,favicon.icoを出力します。

が、vue.config.jsを作り、設定を記述することで変更することができます。
vue.config.jsの置き場所はpackage.jsonと同じ階層。
今回の例で行けば/django-vuejs/vuejs/の直下になります。

module.exports = {
    //ここで指定した場所で展開する
    outputDir: '../django-root',
    //サーバーを起動した時のルートパス
    publicPath: '/',
    //outputDir起点でindex.htmlを格納する場所を指定
    indexPath: 'django-app/templates/index.html',
    //outputDir起点でstaticファイルを格納する場所を指定
    assetsDir: 'static'
}

outputDirでDjango側のプロジェクトディレクトリを指定しています。
その上でindex.htmlとstaticファイル群を出力する場所を指定しています。

vue.config.jsでwebpackの設定とかもできるようですが、まだそこまで調べられておらず。
https://cli.vuejs.org/config/#chainwebpack

これでビルドすれば良いのですが、その前に非常に重要な設定をします。
それはpackage.jsonのscriptの変更です。

{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

上記が$vue generateした時に自動生成されたpackage.jsonです。
このscriptsのbuildの中身を

{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --no-clean",
    "lint": "vue-cli-service lint"
  },

のように変更します。
具体的には--no-clearnオプションを付けます。

このオプションを指定をしないでビルドすると、指定したディレクトリの中を空にしてからファイルを生成します。

/django-vuejs/django-project/static/
/django-vuejs/django-project/django-app/templates/
この配下にvueとは関係ないファイルが置いてあっても、ごっそり持って行かれます。

エドワード・エルリック『こんな・・・こんなはずじゃ・・・畜生ォ 持って行かれた・・・・・・・・・・・・!!』ってなります。

{
  "scripts": {
    "watch": "vue-cli-service build --no-clean --watch"
  },

ウォッチも出来るようなので上記$npm run watchを追加してみたのですが、
ウォッチ時のビルドではassetsDirが無視されるようです。
https://cli.vuejs.org/config/#assetsdir

--no-clearnを指定しないと、差分のように過去のファイルが残って増え続けるんですね…。
$npm run serveはビルドせずとも即時反映されるので、こちらで確認しつつ、良きタイミングでビルドするって感じでしょうか。

outputDirを相対パスで書いていたり美しくないです。
きっともっとスマートなやり方もあるでしょう。
これからもっと詳しく調べます。

マスタッシュ構文がDjangoとVueでかにばってる件は単一ファイルコンポーネントでなんとかなるでしょう。
この点もこれから調査します。

22
34
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
22
34