Front Python Tech

用django-webpack-loader实现Django和Webpack的绑定

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' %}

可以看到按钮已经应用了样式。

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒