django vueを追加する
MPAでvueを使いたい。。。
色んな方法で実現できると分かった。
最終的にはvue cliを使って構築するのがわかりやすいと感じた。cdnはもちろんかんたんだけれどもvuetifyを組み合わせて使う方法が全然わからなかった。
vue cliを使わない方法を試してみたのでそのメモを記す。 ファイルの構成を以下のようなりわかりやすいと感じた。
PROJECT - assets - django-project - node_modules - package-lock.json - package.json - webpack-stats.json - webpack.config.js
仕組みは ./node_modules/.bin/webpack --config webpack.config.jsを実行するとwebpack-stats.jsonがPROJECTのディレクトリに生成される。このファイルをdjango-webpack-loaderが読み込みvueが表示される仕組み。
webpackについてはこれを見ればわかる。 https://qiita.com/soarflat/items/28bf799f7e0335b68186:totle
webpack.config.jsはwebpackの設定ファイル。 エントリーポイントや、ファイルの出力場所、プラグインなどを設定することができます。
モジュール化するためにjavascriptで
export default function
を使うようだ。 それについてはここに詳しく書いてある. ES6のexportについて詳しく調べた - Qiita
webpackコマンドはnode_modules/.bin/webpackに実行ファイルがあるので別にパスを通さなくてもこれで実行すれば良い。
webpackのメリット
- 機能ごとにファイルを分割(モジュール化)する開発ができる
- 自分が作成したモジュールだけでなく、外部モジュール(npmなどでインストールできるパッケージvuetifyなど)も利用できる
- リクエスト数を減らせる
- 依存関係を解決したファイルを出力できる
外部モジュールを利用するときはどのようにすれば利用できるのか...
npmにインストールする。
npm install jquery --save
そしてmain.js(エントリポイントでimportすれば良い)
import $ from 'jquery';
参考記事: django-webpack-loader のセットアップ - Qiita
Vue cliを使ってMPAを実現する
webpackのみでdjangoとvueを統合する場合はwebpack.config.jsでcss関係の調整が必要で知識が必要になる。 これは自分で調整するために行うので別途知識を補充する必要がある。
一方vue cliを使う方法はvue cliが色々なパッケージの調整をしてくれるのでcssについて考える必要がなくてなんとか環境を構築することができた。
Vue CLI は、アプリケーションの構築の複雑さを抽象化するために作られた次世代の cli ツールです。Vue CLI でアプリを起動すると、公式の WebPack の更新や構成の変更、Vuetify の更新を困難なアップグレードプロセスなしで取得することもできます。
環境構築方法をメモしておく。
前提: - vuetifyを導入する - django-webpack-loaderを使って構築する
環境
Django==2.2.6 django-webpack-loader==0.7.0 webpack-bundle-tracker@0.4.3 vue/cli@4.4.6
最初にdjangoのインストール
pip install django
プロジェクトの作成
django-admin startproject myproject cd myproject
以下を入力してプロジェクトの起動
python manage.py runserver
http://127.0.0.1:8000ここにアクセスして以下が表示されればココまではおっけい。
djangonのプロジェクトテンプレート準備する
- settings.pyにおいてテンプレートディレクトリを定めること
- テンプレートを作成する
- urls.pyでテンプレートを表示させる設定を行う
#myproject/myproject/settings.py #以下を追加 TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates') #DIRSにTEMPLATES_DIRを加える TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [TEMPLATES_DIR,], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
テンプレートを作成する。
# myproject/templates/application.html <h2>ああああああ</h2>
urls.pyのセッティング
#myproject/myproject/urls.py from django.contrib import admin from django.urls import path from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path("", TemplateView.as_view(template_name="application.html"), name="app", ), ]
ここまでは通常のdjangoのプロジェクトを作っていく流れです。ここからvue cliを使ってvueのプロジェクトを作成していきます。
pip install django-webpack-loader==0.7.0
#myproject/myproject/settings.py #以下を追加する FRONTEND_DIR = os.path.join(BASE_DIR, 'frontend') WEBPACK_LOADER = { 'DEFAULT': { 'CACHE': DEBUG, 'BUNDLE_DIR_NAME': '/bundles/', #最後にスラッシュを忘れないこと 'STATS_FILE': os.path.join(FRONTEND_DIR, 'webpack-stats.json'), } } INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'webpack_loader', #これを追加 ]
settings.pyに記述したwebpack_loaderやWEBPACK_LOADERはdjango-webpack-loaderに関するものである。
INSTALLED_APPSでdjango-webpack-loaderを有効にする。
WEBPACK_LOADERの'STATS_FILE'でwebpack-stats.jsonを読み込むパスを定める。webpack-stats.jsonはバンドル化したファイルに関連するファイルで、これを通じてバンドル化したファイルを読み込むのだろうと推測している。詳しくはまだ調べきれていない。
次にvueのプロジェクトを作成する。
npm install -g @vue/cli
vue --version @vue/cli 4.4.6
vue create frontend
vuetifyをvue cliを使ってプロジェクトに加える。この方法を使うとwebpackのみで構築する方法と違ってwebpack.config.jsを自分でいじる必要がなくなるのでハマるリスク回避できる。webpackのみでハマったのでこれはありがたいです。
cd frontend vue add vuetify
関連するパッケージをインストールする。
npm install
このバージョンをインストールしないと後々DJANGO側でエラーが出てしまい困ることになるので重要。
npm install --save-dev webpack-bundle-tracker@0.4.3
npm run serve
下のように表示されればおっけい
vue.config.jsを編集する。
const BundleTracker = require("webpack-bundle-tracker"); module.exports = { publicPath: "http://127.0.0.1:8080/", outputDir: './dist/', chainWebpack: config => { config.optimization .splitChunks(false) config .plugin('BundleTracker') .use(BundleTracker, [{filename: '../frontend/webpack-stats.json'}]) config.resolve.alias .set('__STATIC__', 'static') config.devServer .public('http://0.0.0.0:8080') .host('0.0.0.0') .port(8080) .hotOnly(true) .watchOptions({poll: 1000}) .https(false) .headers({"Access-Control-Allow-Origin": ["\*"]}) } };
cd frontend npm run serve
python manage.py runserver
これでdjangoのテンプレートとvueを統合することができた。
次に各エンドポイントに応じてテンプレートを変更することを実現させる。これはもちろん使用されるテンプレートに応じてvueを使い分けるということである。
これはvue.config.jsを修正すれば良い。module.exportsにpagesを加えれば良い。またpagesの値を定める。
const BundleTracker = require("webpack-bundle-tracker"); //追加事項 const pages = { 'vue_app_01': { entry: './src/main.js', chunks: ['chunk-vendors'] }, 'vue_app_02': { entry: './src/main2.js', chunks: ['chunk-vendors'] }, } module.exports = { pages: pages, //これを追加 publicPath: "http://127.0.0.1:8080/", outputDir: './dist/', ... ... }
次に./src/main2.jsを作成する。これは例として以下のようなファイルとする。
import Vue from 'vue' import App2 from './App2.vue' #後でファイルを作成する import vuetify from './plugins/vuetify'; Vue.config.productionTip = false Vue.config.delimiters = ["[[", "]]"]; new Vue({ vuetify, render: h => h(App2) }).$mount('#app')
App2.vueの作成
cd src touch App2.vue
<template> <v-app> <v-app-bar app color="primary" dark > <div class="d-flex align-center"> <v-img alt="Vuetify Logo" class="shrink mr-2" contain src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png" transition="scale-transition" width="40" /> <v-img alt="Vuetify Name" class="shrink mt-1 hidden-sm-and-down" contain min-width="100" src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png" width="100" /> </div> <v-spacer></v-spacer> <v-btn href="https://github.com/vuetifyjs/vuetify/releases/latest" target="_blank" text > <span class="mr-2">Latest Release</span> <v-icon>mdi-open-in-new</v-icon> </v-btn> </v-app-bar> <v-content> <HelloWorld/> </v-content> </v-app> </template> <script> import HelloWorld from './components/HelloWorld'; export default { name: 'App', components: { HelloWorld, }, data: () => ({ // }), }; </script>
次に必要なdjangoプロジェクトのテンプレートを調整する
urlpatterns = [ path('admin/', admin.site.urls), path("", TemplateView.as_view(template_name="application.html"), name="app",), #以下を追加する path("test/", TemplateView.as_view(template_name="test.html"), name="app",), ]
touch templates/test.html
{% load render_bundle from webpack_loader %} <div id="app"> </div> vue_app_02 {% render_bundle 'chunk-vendors' %} {% render_bundle 'vue_app_02' %}
これでテンプレートによって別のvueを使うことができるようになる。
参考: Integrating Django and VueJs with Vue CLI 3 and Webpack Loader