wagtail で 作成中の Blog の Front 部に React.js を使いたいのですが、調べたところ、ezhome/django-webpack-loader: Transparently use webpack with django という Django plugin を使えば、構築できそうに思いました。
wagtail + django-webpack-loader + react で一通りの設定を行っている情報が見つけられなかったので、個人的な備忘録として手順をまとめます。
前提
以下の環境で作業は実施しています。
-
OS
% sw_vers ProductName: Mac OS X ProductVersion: 10.13.1 BuildVersion: 17B1003
-
Python の Version
% python3 -V Python 3.6.2
-
Django の Version
% python3 -m pip list --format=columns | grep Django Django 1.11.8
事前環境構築として、以下を実施しています。
* Django プロジェクトを mysite という名前で作成
最終的なディレクトリ構成
インストール、設定後、Django プロジェクトは以下のディレクトリ構成になります。
├── assets // jsファイルの配置先
│ ├── js
│ └── webpack_bundles
├── home // django app
├-- db.sqlite3
├-- manage.py
├-- node_modules
├-- package-lock.json
├-- package.json
├-- requirements.txt
├-- webpack-stats.json
├-- webpack.config.js
└── mysite // django project app
雛形作成の流れ
雛形作成の流れは以下の通りです。
-
webpack、react のインストール、設定
-
django-webpack-loader を インストール、設定
-
雛形ページの作成
1. webpack、react、babel のインストール、設定
webpack のインストール、設定
- インストール
webpackをつかってdjangoでbootstrap4をはじめる - Qiita を参考に、webpack のインストールを実施します。
django の プロジェクトルートフォルダに移動し、以下のコマンドを実行します。
npm init -f npm install --save-dev webpack webpack-bundle-tracker
webpack.config.js の作成
django の プロジェクトルートフォルダにwebpack.config.js
を作成します。
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
/* エントリーポイント */
entry: './assets/js/main.js',
output: {
path: path.resolve('./assets/webpack_bundles/'),
filename: "[name]-[hash].js"
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'})
]
}
エントリポイントの作成
エントリポイントは、./assets/js/main.js
です。
ディレクトリと、main.js ファイルを作成します。
エントリポイントが何かがよくわからなかったので、検索したところ以下がヒットしました。
エントリポイント · JavaScriptの入門書 #jsprimer
現在(2018/01/18)の文章を引用しておきます。
エントリポイントとは、アプリケーションの中で一番最初に呼び出される部分のことです。 アプリケーションを作成するにあたり、まずはエントリポイントを用意しなければなりません。 Webアプリケーションにおいては、常にHTMLドキュメントがエントリポイントとなります。 ウェブブラウザによりHTMLドキュメントが読み込まれたあとに、HTMLドキュメント中で読み込まれたJavaScriptが実行されます。
mkdir -p assets/js
touch assets/js/main.js
js ファイルのビルド
webpack の 初期設定はこれで終了です。
js ファイルをビルドします。
./node_modules/.bin/webpack --config webpack.config.js
------------------------------------------
Hash: 315df4b2f5abf7716c38
Version: webpack 3.10.0
Time: 69ms
Asset Size Chunks Chunk Names
main-315df4b2f5abf7716c38.js 2.47 kB 0 [emitted] main
[0] ./assets/js/index.js 0 bytes {0} [built]
------------------------------------------
react、babel のインストール、設定
Reactを「webpack + babel-loader」でビルドする方法 | maesblog を参考に react のインストール、設定を行います。
react の インストール
django の プロジェクトルートフォルダに移動し、以下のコマンドを実行します。
npm install --save react react-dom
Babel 関連のパッケージのインストール
babel の関連パッケージをインストールします。
npm install --save-dev babel-loader babel-core babel-preset-react babel-preset-es2015
.babelrc の作成
vi .babelrc
-----------------------------------
{
"presets": ["react", "es2015"]
}
-----------------------------------
webpack.config.js の修正
babel、react をインストールしたので、webpack.config.js を修正して、babelの設定を追加します。
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
/* エントリーポイント */
entry: './assets/js/main.js',
output: {
path: path.resolve('./assets/webpack_bundles/'),
filename: "[name]-[hash].js"
},
/* ソースマップをファイル内に出力させる場合は以下を追加 */
devtool: 'inline-source-map',
module: {
/* loaderの設定 */
loaders: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/, // 除外するファイル/ディレクトリ(正規表現可)
loader: 'babel-loader' // 使用するloader
}
]
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'})
]
}
npm コマンドの登録
package.json
に以下、コマンドを追加します。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "./node_modules/.bin/webpack --watch --progress",
"build": "./node_modules/.bin/webpack --config webpack.config.js"
},
上記コマンドの追加後は、django の プロジェクトルートフォルダ で 以下のコマンドが実行できるようになります。
npm run watch
npm run build
# これは`package.json` 追加後、デフォルトで定義されているコマンドになります。
npm run test
以上で、react、babel のインストールは完了です。
2. django-webpack-loader を インストール、設定
続いて、django と webpack の 連携用の plugin ezhome/django-webpack-loader: Transparently use webpack with django をインストールします。
django-webpack-loader のインストール
pip でインストールします。1
python3 -m pip install django-webpack-loader
-------------------------------------------
Collecting django-webpack-loader
Downloading django_webpack_loader-0.5.0-py2.py3-none-any.whl
Installing collected packages: django-webpack-loader
Successfully installed django-webpack-loader-0.5.0
-------------------------------------------
STATICFILES_DIRS の作成 と設定
django の デフォルトの静的コンテンツディレクトリは、static
で、 STATICFILES_DIRS には以下の通り定義されているかと思います。
STATICFILES_DIRS = [
os.path.join(PROJECT_DIR, 'static'),
]
これを、README.md
の内容に合わせて、assets
に変更します。
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'assets'),
os.path.join(PROJECT_DIR, 'static'),
]
settings.py に WEBPACK_LOADER
を追加する
以下も、README.md
の記載の通りです。
settings.py に WEBPACK_LOADER
を追加します。
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'BUNDLE_DIR_NAME': 'webpack_bundles/', # must end with slash
# PROJECT_DIRからここは変えているかもしれません。
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'TIMEOUT': None,
'IGNORE': ['.+\.hot-update.js', '.+\.map']
}
}
INSTALL_APPS に webpack_loader
を追加する
settings.py の INSTALL_APPS に webpack_loader
を追加します。
INSTALLED_APPS = [
...
'webpack_loader',
]
動作確認用のため、template に js 読み込み記述を追加
テンプレートファイルに以下の記述を追加します。
{% load render_bundle from webpack_loader %}
{# 以下は、body タグの直前に #}
{% render_bundle 'main' %}
サーバー起動して、動作確認
サーバーを起動して、動作確認します。
python3 manage.py runserver
http://127.0.0.1:8000
にアクセスすると、{% render_bundle 'main' %}
が、<script type="text/javascript" src="/static/webpack_bundles/main-315df4b2f5abf7716c38.js" ></script>
に変換され、ページが表示できました。
3. 雛形ページの作成
react の 雛形ページを作成します。
mzabriskie/react-example: Simple React example app を参考に作成しました。
必要なファイルは、App.jsx
と、main.js
になります。
wagtail helloword
を出力する。アプリケーションになります。
* assets/js/App.jsx
import React from 'react';
class App extends React.Component {
render() {
return (
<div>wagtail, helloworld</div>
);
}
}
export default App;
- assets/js/main.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.jsx'; ReactDOM.render(<App />, document.getElementById('app'));
発生したエラー
インストール、動作確認時に発生したエラーを記載します。
Module parse failed: Unexpected token (6:6)
React の サンプルアプリケーションを追加した後、webpack のビルド時に以下のエラーが出力されました。
ERROR in ./assets/js/App.jsx
Module parse failed: Unexpected token (6:6)
You may need an appropriate loader to handle this file type.
JSX is not transform by babel loader from node_modules/my_module · Issue #377 · babel/babel-loader
コンパイルする js の拡張子として、jsx の記載がないとエラーになるようです。
webpack.config.js
に、jsx
の記述を追加したところうまく動きました。 module: {
/* loaderの設定 */
loaders: [
{
test: /\.(js|jsx)$/, // jsxも対象にする
exclude: /node_modules/, // 除外するファイル/ディレクトリ(正規表現可)
loader: 'babel-loader' // 使用するloader
}
]
},
Target container is not a DOM element.
画面表示時に以下のエラーが発生しました。
Target container is not a DOM element.
OSError: Error reading /Users/xxxxx/xxxx/webpack-stats.json.
Django の ローカルサーバーを起動して、動作確認したところ以下のエラーが発生しました。
OSError: Error reading /Users/xxxxx/xxxx/webpack-stats.json. Are you sure webpack has generated the file and the path is correct?
One of the core principles of django-webpack-loader is to not manage webpack itself in order to give you the flexibility to run webpack the way you want. If you are new to webpack, check one of the examples, read my detailed blog post or check webpack docs.
django-webpack-loader
は webpack 自体の管理は行わないので、別途ビルドが必要な旨が記載されています。
webpack の ビルド後にサーバ起動したところ発生しなくなりました。
補足
django * react の 連携 は 謎が多くあり、なんとなく検索して、ハマりながら作業を進めました。
ひとしきり作業してから、以下の記事を見つけました。
Create React App and Django
どちらかというとこの構成が一般的な気がしました。
次回構築するときは、この記事を参考に進めようかなと思います。
以上です。
-
README.md
には、npm install --save-dev webpack-bundle-tracker
の記載がありますが、インストール先の調整が必要に思いましたので、とばしています。 ↩
コメント