見出し画像

vue-cliを使用しないでDjangoでvue.jsの環境を作る

DjangoはLaravelPHPやRuby on Railsと違ってモダンなフロントエンドの環境で開発するための機能が標準ではサポートされていません。

そのため、Vue, angular, Reactといったモダンなjsフレームワークを使ってWEBアプリケーションを開発するためには自分で導入するしかありません。

今回はDjangoでvue.jsを使って開発するための環境構築の方法をご紹介します。

読者の対象としてはDjangoをある程度使えたりすることを前提とておくため、Djangoの細かい設定や内容などは扱いません。

シンプルに構築する

どの環境でも共通することですが、vue.jsを使って開発をする場合は以下の二つの方法があると思います。

・vue-cliを使ってvue.jsを開発するための環境を構築する
・npmやyarn経由で自分でvue.jsを入れる

今回は下記の方法を使ってvue.jsの開発環境を構築していきます。

つまりは、Djangoの静的ファイル(jsやcssなどのstatic)を扱うディレクトリの中にvue.jsのファイルを作っていくため、Djangoというフレームワークにvue.jsを組み込んでいくことになります。

Djangoのプロジェクトを作成

Djangoのプロジェクトを作成。まずは以下のコマンドでプロジェクトを作成して、マイグレーションもしておきます。

$ django-admin startproject django_vue
$ python manage.py migrate

webpackを導入してフロントエンドを整備

webpackやjavascriptなどのモジュール類をダウンロードするには、npm(node package manager)が必要です。

npmは各OSによって導入方法が違うため、npm自体のインストールは各自調べて導入してください。npm自体はnodejsが入っていることを前提としています。
自分の環境の場合は、v10以上のnodeが動いています。

$ node -v
v10.13.0

まずは以下のコマンドを打ち込みます。package.jsonが作成されます。

$ npm init -f
$ cat package.json
{
  "name": "django_webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

以下のコマンドで、まずはwebpackとvueを導入します。style-loaderとcss-loaderも入れます。webpackはversion 4以上から、webpack-cliが必要だそうです。

$ npm install --save-dev webpack webpack-cli webpack-bundle-tracker
$ npm install --save-dev vue-loader
$ npm install --save-dev style-loader css-loader sass-loader

$ npm install --save vue

babelも導入していきます。babel関連のモジュールも導入、その他必要だと思われるモジュール類も導入していきます。

$ npm install --save-dev @babel/core @babel/preset-env
$ npm install --save-dev babel-loader

(一応必要かなと思うモジュール類なども入れていますが、各自で必要だと思うモジュールを調整してください)

webpackの設定ファイルを作成

webpack.config.jsという設定ファイルを作成する必要があります。以下のコマンドで作成します。

$ touch webpack.config.js

webpack.config.jsの中身を開いて以下のように設定します。エディタなどで開いて、以下のように書き換えていきましょう。
static/jsというディレクトリのapp.jsの内容を読み込んで、それらをトランスパイルしていき、static/bundlesにトランスコンパイルされたjsのファイルを作成するための設定内容です。

var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');


module.exports = {
    context: __dirname,
    entry: './static/js/app.js',

    output: {
        filename: "[name]-[hash].js",
        path: path.resolve('./static/bundles/'),
        // publicPath: '/'
    },

    plugins: [
        new BundleTracker({filename: './webpack-stats.json'})
    ],
}

outputのfilenameの項目にある"[name]-[hash].js"と出ているように、トランスパイルする毎にファイル名の違うjsファイルがbundlesに保存されていきます。

webpack-stats.jsonは、最新のトランスパイルされたbundles内のjsファイルを指しています。

試しに動作に問題ないかを見てみます。webpack.config.js内にあるscripts内を以下のように編集します。

{
 "name": "app",
 "version": "1.0.0",
 "description": "### pollsアプリケーション",
 "main": "index.js",
 "scripts": {
   "test": "echo \"Error: no test specified\" && exit 1",
   "dev": "node_modules/.bin/webpack --mode development",
   "build": "node_modules/.bin/webpack --mode production",
   "watch": "node_modules/.bin/webpack --watch -d"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
}

「npm run dev」を入力することで、「./node_modules/.bin/webpack --mode development」が動くようになります。

以下のように表示されればトランスパイルが成功しています。

> webpack --mode development

Hash: 311c684f4ad1d38be9e1
Version: webpack 4.29.6
Time: 102ms
Built at: 03/25/2019 2:45:01 AM
                       Asset      Size  Chunks             Chunk Names
main-311c684f4ad1d38be9e1.js  4.04 KiB    main  [emitted]  main
Entrypoint main = main-311c684f4ad1d38be9e1.js
[./static/js/app.js] 237 bytes {main} [built]

Djangoにトランスパイルされたjsファイルを読み込むように設定

まずは以下のlsコマンドを入力し、lsコマンドで作られたファイル類を確認していきましょう。

$ ls
django_webpack/  package.json       webpack-stats.json
manage.py*       package-lock.json
node_modules/    static/

まずはDjango上でwebpackを読み込めるように、django-webpack-loaderをpipでインストールします。

pip install django-webpack-loader

webpackでトランスパイルされたjsファイルをDjango上で読み込むには、Djangoの設定ファイルを編集して以下の項目を設定していきましょう。

django_vue/settings.pyの中身を開いて、以下の項目を追加していきましょう。

...

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

...

WEBPACK_LOADER = {
   'DEFAULT': {
       'BUNDLE_DIR_NAME': 'bundles/',
       'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
   }
}

...

INSTALLED_APPS = (
    ...
    'webpack_loader',
)

INSTALLED_APPSにはwebpack_loaderを入れて、Djangoのアプリケーション上でwebpack_loaderを読み込むようにします。

STATICFILES_DIRSには、静的ファイルを読み込むディレクトリを指定します。

WEBPACK_LOADERには、トランスパイルされた最新のjsのpathを指しているwebpack-stats.jsonのpathを指定します。

webpackの設定ファイルを再度修正する

webpack.config.jsの内容を編集して設定していきます。.vueやその他css等のファイルもトランスパイルできるように編集していきます。

インポートするモジュール部分を以下のように設定していきます。

var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var VueLoaderPlugin = require('vue-loader/lib/plugin');

var env = process.env.NODE_ENV;

次に.vueファイルを読み込めるようにpluginsにVueLoaderPluginを追加します。

module.exports = {
   context: __dirname,
   mode: env,
   entry: './static/js/app.js',

   output: {
       filename: "[name]-[hash].js",
       path: path.resolve('./static/bundles/')
   },

   plugins: [
       new BundleTracker({filename: './webpack-stats.json'}),
       // .vueファイルを読み込めるようにする
       new VueLoaderPlugin()
   ],

....

次にmoduleとresolve部分に以下を設定していきます。これによりcssやscssなどをトランスパイルできるようにします。

....

    module: {
       rules:  [
           {
               test: /\.js$/,
               loader: 'babel-loader',
           },
           {
               test: /\.vue$/,
               loader: 'vue-loader'
           },
           {
               test: /\.scss$/,
               use: [
                   'style-loader',
                   'css-loader',
                   'sass-loader'
               ]
           },
           {
               test: /\.css$/,
               use: [
                   "vue-style-loader",
                   'style-loader',
                   {
                       loader: 'css-loader',
                       options: {
                           url: false,
                           sourceMap: true
                       }
                   }
               ]
           },
       ]
   },

   resolve: {
       extensions: ['.js', '.vue'],
       modules: [
           "node_modules"
       ],
       alias: {
           'vue': path.resolve('./node_modules/vue/dist/vue.js'),
       }
   },

.....

全体としてはwebpack.config.jsの内容は以下のようになります。

var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var VueLoaderPlugin = require('vue-loader/lib/plugin');

var env = process.env.NODE_ENV;

module.exports = {
   context: __dirname,
   mode: env,
   entry: './static/js/app.js',
   output: {
       filename: "[name]-[hash].js",
       path: path.resolve('./static/bundles/')
       // publicPath: '/'
   },

   plugins: [
       new BundleTracker({filename: './webpack-stats.json'}),
       // .vueファイルを読み込めるようにする
       new VueLoaderPlugin()
   ],

   module: {
       rules:  [
           {
               test: /\.js$/,
               loader: 'babel-loader',
           },
           {
               test: /\.vue$/,
               loader: 'vue-loader'
           },
           {
               test: /\.scss$/,
               use: [
                   'style-loader',
                   'css-loader',
                   'sass-loader'
               ]
           },
           {
               test: /\.css$/,
               use: [
                   "vue-style-loader",
                   'style-loader',
                   {
                       loader: 'css-loader',
                       options: {
                           url: false,
                           sourceMap: true
                       }
                   }
               ]
           },
       ]
   },

   resolve: {
       extensions: ['.js', '.vue'],
       modules: [
           "node_modules"
       ],
       alias: {
           'vue': path.resolve('./node_modules/vue/dist/vue.js'),
       }
   }

}

TemplateとVueのファイルを設定する

static/js内にあるapp.jsに以下を設定します。これにより、全てのtemplateでvueファイルを読み込めるようにします。

window.Vue = require('vue');

後はtemplateファイル内に以下を入れてトランスパイルされたファイルをhtmlから読み込めるように設定します。

{% load render_bundle from webpack_loader %}
{% render_bundle 'main' %}

参考資料


この記事が気に入ったらサポートをしてみませんか?