ゴール
- バックエンドでDjango、フロントエンドでVue.jsを使いたい。
- 単一ファイルコンポーネントを使いたい。
- SPAを使う
流れ
- Vueを使えるようにする
- Djangoを使えるようにする
- 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でかにばってる件は単一ファイルコンポーネントでなんとかなるでしょう。
この点もこれから調査します。