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

## ゴール
- バックエンドで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](https://cli.vuejs.org/config/)を作り、設定を記述することで変更することができます。
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オプションを付けます。


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



https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-build

/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でかにばってる件は単一ファイルコンポーネントでなんとかなるでしょう。
この点もこれから調査します。