django-webpack-loader是Django去年的热门App之一,实现Django和Webpack的绑定。做法很简洁,就是用一个nodejs模块处理Webpack的输出,Django再去读取这个模块生成的JSON文件,加载对应的bundle文件就行了。最近在cygwin里重新部署了一次,分享其中的关键点。环境是:
Django 1.9.5
NodeJS v6.0.0
Win7(64)+Cygwin2.4.1
场景是将现有的一个Django项目,转成用Webpack来处理静态文件。因为没有执行npm init
,安装时会提示找不到package.json,一些常见的基础配置、错误提示等本文不会涉及。
Install & Settings
首先用npm/pip安装相关的包:
npm install webpack webpack-bundle-tracker
npm install babel-loader babel-core babel-preset-es2015
pip install django-webpack-loader
然后设置Django(settings.py),把webpack_loader加到INSTALLED_APPS中,指定templates和static目录,新增WEBPACK_LOADER:
INSTALLED_APPS = [
...
'webpack_loader',
]
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
TEMPLATES[0]['DIRS'].append(os.path.join(BASE_DIR, 'templates'))
#针对Webpack的设置
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'js/dist/'
}
}
这样Django会从/static/js/dist/读取Webpack生成的文件。接下来配置Webpack,在目录中新建webpack.config.js,内容如下:
var BundleTracker = require('webpack-bundle-tracker');
module.exports = {
context: __dirname,
entry: "./static/js/src/index", //entry文件的位置
output: {
path: './static/js/dist', //和settings.py里的WEBPACK_LOADER的设置对应
filename: "[name].dev.js"
},
module: { //使用babel loader
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['es2015']
}
}
]
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'})
]
};
Usage
在当前目录执行webpack
(全局或是项目),会自动读取/static/js/src/index.js,生成/static/js/dist/main.dev.js。当然,现在会报错提示找不到entry,要创建对应的js文件,以下只写了import语句来验证loader已经加载:
import path from 'path';
alert('sep is ' + path.sep);
执行后在dist中生成js文件。现在要自动把生成的文件(bundle)加载到模板,django-webpack-loader使用template tag的方式来实现。创建一个模板文件,内容为:
{% load render_bundle from webpack_loader %}
{% render_bundle 'main' %}
这样生成的js文件就会以script标签的形式自动插入当前模板了。Webpack执行的结果(通过webpack-bundle-tracker)会写入webpack-stats.json文件中,Django运行时会读取这个json文件,如果出错会抛出500错误。
Extension
render_bundle也接受参数来指定文件扩展,可以处理css文件。例如要在Django中使用AdminLET,执行以下步骤可以通过Webpack来加载:
npm install admin-let
npm install css-loader url-loader file-loader extract-text-webpack-plugin
上列命令安装AdminLET和需要的loader,因为css文件中通常都会指定图片文件(还是字体等),所以还需要url-loader/file-loader。extract-text-webpack-plugin用来把css合并到一个文件中。
修改webpack.config.js:
var BundleTracker = require('webpack-bundle-tracker'),
ExtractTextPlugin = require('extract-text-webpack-plugin'); //加载extract-text-webpack-plugin
module.exports = {
context: __dirname,
entry: './static/js/src/index', //entry文件的位置
output: {
path: './static/js/dist', //跟Django中WEBPACK_LOADER的设置对应
filename: '[name].dev.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['es2015']
}
},
//加载css-loader,处理扩展名为css和jpg的文件
{test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader')},
{test: /\.jpg$/, loader: 'url-loader?limit=100000'}
]
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new ExtractTextPlugin('[name].css')//增加插件
]
};
最后修改/static/js/src/index.js文件和模板文件:
//在index.js文件中加载css文件
import 'admin-lte/dist/css/AdminLTE.css';
{% load render_bundle from webpack_loader %}
{% render_bundle 'main' 'css' %}
{% render_bundle 'main' %}
<button class="btn">Load CSS</button>
可以看到按钮已经应用了样式。
[…] 將 Webpack 與 Django 一起使用:無需插件! 在Django中使用Webpack:再也不需要插件了! Modern Django: Part 1: Setting up Django and React 从零开始创建react+Django项目 Webpack 簡介[筆記][React]從零到一的webpack開發環境(1)-安裝執行篇 如何讓Django和ReactJS一起工作? React 教程:概述和演练 用DJANGO-WEBPACK-LOADER实现DJANGO和WEBPACK的绑定 […]