django-webpack-loader

Transparently use webpack with django
授权协议 View license
开发语言 JavaScript
所属分类 Web应用开发、 常用JavaScript包
软件类型 开源软件
地区 不详
投 递 者 焦宁
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

django-webpack-loader

Read http://owaislone.org/blog/webpack-plus-reactjs-and-django/ for a detailed step by step guide on setting up webpack with django using this library.

Use webpack to generate your static bundles without django's staticfiles or opaque wrappers.

Django webpack loader consumes the output generated by webpack-bundle-tracker and lets you use the generated bundles in django.

A changelog is also available.

Compatibility

Test cases cover Django>=2.0 on Python>=3.5. 100% code coverage is the target so we can be sure everything works anytime. It should probably work on older version of django as well but the package does not ship any test cases for them.

Install

npm install --save-dev webpack-bundle-tracker

pip install django-webpack-loader

Migrating from version < 1.0.0

In order to use django-webpack-loader>=1.0.0, you must ensure that webpack-bundle-tracker@1.0.0 is being used on the JavaScript side. It's recommended that you always keep at least minor version parity across both packages, for full compatibility.

This is necessary because the formatting of webpack-stats.json that webpack-bundle-tracker outputs has changed starting at version 1.0.0-alpha.1. Starting at django-webpack-loader==1.0.0, this is the only formatting accepted here, meaning that other versions of that package don't output compatible files anymore, thereby breaking compatibility with older webpack-bundle-tracker releases.


Configuration


Assumptions

Assuming BASE_DIR in settings refers to the root of your django app.

import sys
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Assuming assets/ is in settings.STATICFILES_DIRS like

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'assets'),
)

Assuming your webpack config lives at ./webpack.config.js and looks like this

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

module.exports = {
  context: __dirname,
  entry: './assets/js/index',
  output: {
      path: path.resolve('./assets/webpack_bundles/'),
      filename: "[name]-[hash].js"
  },

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

Default Configuration

WEBPACK_LOADER = {
    'DEFAULT': {
        'CACHE': not DEBUG,
        'BUNDLE_DIR_NAME': 'webpack_bundles/', # must end with slash
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'TIMEOUT': None,
        'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
        'LOADER_CLASS': 'webpack_loader.loader.WebpackLoader',
    }
}

CACHE

WEBPACK_LOADER = {
    'DEFAULT': {
        'CACHE': not DEBUG
    }
}

When CACHE is set to True, webpack-loader will read the stats file only once and cache the result. This means web workers need to be restarted in order to pick up any changes made to the stats files.


BUNDLE_DIR_NAME

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'bundles/' # end with slash
    }
}

BUNDLE_DIR_NAME refers to the dir in which webpack outputs the bundles. It should not be the full path. If ./assets is one of your static dirs and webpack generates the bundles in ./assets/output/bundles/, then BUNDLE_DIR_NAME should be output/bundles/.

If the bundle generates a file called main-cf4b5fab6e00a404e0c7.js and your STATIC_URL is /static/, then the <script> tag will look like this

<script src="/static/output/bundles/main-cf4b5fab6e00a404e0c7.js"/>

NOTE: If your webpack config outputs the bundles at the root of your staticfiles dir, then BUNDLE_DIR_NAME should be an empty string '', not '/'.


STATS_FILE

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

STATS_FILE is the filesystem path to the file generated by webpack-bundle-tracker plugin. If you initialize webpack-bundle-tracker plugin like this

new BundleTracker({filename: './webpack-stats.json'})

and your webpack config is located at /home/src/webpack.config.js, then the value of STATS_FILE should be /home/src/webpack-stats.json


IGNORE

IGNORE is a list of regular expressions. If a file generated by webpack matches one of the expressions, the file will not be included in the template.


POLL_INTERVAL

POLL_INTERVAL is the number of seconds webpack_loader should wait between polling the stats file. The stats file is polled every 100 milliseconds by default and any requests to are blocked while webpack compiles the bundles. You can reduce this if your bundles take shorter to compile.

NOTE: Stats file is not polled when in production (DEBUG=False).


TIMEOUT

TIMEOUT is the number of seconds webpack_loader should wait for webpack to finish compiling before raising an exception. 0, None or leaving the value out of settings disables timeouts.


LOADER_CLASS

LOADER_CLASS is the fully qualified name of a python class as a string that holds the custom webpack loader.This is where behavior can be customized as to how the stats file is loaded. Examples include loading the stats filefrom a database, cache, external url, etc. For convenience, webpack_loader.loader.WebpackLoader can be extended;The load_assets method is likely where custom behavior will be added. This should return the stats file as an object.

Here's a simple example of loading from an external url:

# in app.module
import requests
from webpack_loader.loader import WebpackLoader

class ExternalWebpackLoader(WebpackLoader):

  def load_assets(self):
    url = self.config['STATS_URL']
    return requests.get(url).json()


# in app.settings
WEBPACK_LOADER = {
  'DEFAULT': {
      'CACHE': False,
      'BUNDLE_DIR_NAME': 'bundles/',
      'LOADER_CLASS': 'app.module.ExternalWebpackLoader',
      # Custom config setting made available in WebpackLoader's self.config
      'STATS_URL': 'https://www.test.com/path/to/stats/',
  }
}

Usage


Manually run webpack to build assets.

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.

Settings

Add webpack_loader to INSTALLED_APPS

INSTALLED_APPS = (
    ...
    'webpack_loader',
)

Templates

{% load render_bundle from webpack_loader %}

{% render_bundle 'main' %}

render_bundle will render the proper <script> and <link> tags needed in your template.

render_bundle also takes a second argument which can be a file extension to match. This is useful when you want to render different types for files in separately. For example, to render CSS in head and JS at bottom we can do something like this,

{% load render_bundle from webpack_loader %}

<html>
  <head>
    {% render_bundle 'main' 'css' %}
  </head>
  <body>
    ....
    {% render_bundle 'main' 'js' %}
  </body>
</head>

Preload

The is_preload=True option in the render_bundle template tag can be used to add rel="preload" link tags.

{% load render_bundle from webpack_loader %}

<html>
  <head>
    {% render_bundle 'main' 'css' is_preload=True %}
    {% render_bundle 'main' 'js' is_preload=True %}

    {% render_bundle 'main' 'css' %}
  </head>

  <body>
    {% render_bundle 'main' 'js' %}
  </body>
</html>

Skipping the generation of multiple common chunks

You can use the parameter skip_common_chunks=True to specify that you don't want an already generated chunk be generated again in the same page.

In order for this option to work, django-webpack-loader requires the request object to be in the context, to be able to keep track of the generated chunks.

The request object is passed by default via the django.template.context_processors.request middleware with using the Django built-in templating system, and also with using Jinja2.

If you don't have request in the context for some reason (e.g. using Template.render or render_to_string directly without passing the request), you'll get warnings on the console.

Appending file extensions

The suffix option can be used to append a string at the end of the file URL. For instance, it can be used if your webpack configuration emits compressed .gz files.

qwe

{% load render_bundle from webpack_loader %}

<html>
  <head>
    <meta charset="UTF-8">
    <title>Example</title>
    {% render_bundle 'main' 'css' %}
  </head>

  <body>
    {% render_bundle 'main' 'js' suffix='.gz' %}
  </body>
</html>

Multiple webpack projects

Version 2.0 and up of webpack loader also supports multiple webpack configurations. The following configuration defines 2 webpack stats files in settings and uses the config argument in the template tags to influence which stats file to load the bundles from.

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'bundles/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
    },
    'DASHBOARD': {
        'BUNDLE_DIR_NAME': 'dashboard_bundles/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-dashboard.json'),
    }
}
{% load render_bundle from webpack_loader %}

<html>
  <body>
    ....
    {% render_bundle 'main' 'js' 'DEFAULT' %}
    {% render_bundle 'main' 'js' 'DASHBOARD' %}

    <!-- or render all files from a bundle -->
    {% render_bundle 'main' config='DASHBOARD' %}

    <!-- the following tags do the same thing -->
    {% render_bundle 'main' 'css' 'DASHBOARD' %}
    {% render_bundle 'main' extension='css' config='DASHBOARD' %}
    {% render_bundle 'main' config='DASHBOARD' extension='css' %}

    <!-- add some extra attributes to the tag -->
    {% render_bundle 'main' 'js' 'DEFAULT' attrs='async charset="UTF-8"'%}
  </body>
</head>

File URLs instead of html tags

If you need the URL to an asset without the HTML tags, the get_filestemplate tag can be used. A common use case is specifying the URL to acustom css file for a Javascript plugin.

get_files works exactly like render_bundle except it returns a list ofmatching files and lets you assign the list to a custom template variable. For example,

{% get_files 'editor' 'css' as editor_css_files %}
CKEDITOR.config.contentsCss = '{{ editor_css_files.0.publicPath }}';

<!-- or list down name, path and download url for every file -->
<ul>
{% for css_file in editor_css_files %}
    <li>{{ css_file.name }} : {{ css_file.path }} : {{ css_file.publicPath }}</li>
{% endfor %}
</ul>

Refer other static assets

webpack_static template tag provides facilities to load static assets managed by webpackin django templates. It is like django's built in static tag but for webpack assets instead.

In the below example, logo.png can be any static asset shipped with any npm package.

{% load webpack_static from webpack_loader %}

<!-- render full public path of logo.png -->
<img src="{% webpack_static 'logo.png' %}"/>

The public path is based on webpack.config.js output.publicPath.


From Python code

If you want to access the webpack asset path information from your application code then you can usethe function in the webpack_loader.utils module.

>>> utils.get_files('main')
[{'url': '/static/bundles/main.js', u'path': u'/home/mike/root/projects/django-webpack-loader/tests/assets/bundles/main.js', u'name': u'main.js'},
 {'url': '/static/bundles/styles.css', u'path': u'/home/mike/root/projects/django-webpack-loader/tests/assets/bundles/styles.css', u'name': u'styles.css'}]
>>> utils.get_as_tags('main')
['<script src="/static/bundles/main.js" ></script>',
 '<link href="/static/bundles/styles.css" rel="stylesheet" />']

How to use in Production

It is up to you. There are a few ways to handle this. I like to have slightly separate configs for production and local. I tell git to ignore my local stats + bundle file but track the ones for production. Before pushing out newer version to production, I generate a new bundle using production config and commit the new stats file and bundle. I store the stats file and bundles in a directory that is added to the STATICFILES_DIR. This gives me integration with collectstatic for free. The generated bundles are automatically collected to the target directory and synched to S3.

./webpack_production.config.js

var config = require('./webpack.config.js');
var BundleTracker = require('webpack-bundle-tracker');

config.output.path = require('path').resolve('./assets/dist');

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

// override any other settings here like using Uglify or other things that make sense for production environments.

module.exports = config;

settings.py

if not DEBUG:
    WEBPACK_LOADER.update({
        'BUNDLE_DIR_NAME': 'dist/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json')
    })



You can also simply generate the bundles on the server before running collectstatic if that works for you.

Extra

Jinja2 Configuration

If you need to output your assets in a jinja template we provide a Jinja2 extension that's compatible with the Django Jinja module and Django 1.8.

To install the extension add it to the django_jinja TEMPLATES configuration in the ["OPTIONS"]["extension"] list.

from django_jinja.builtins import DEFAULT_EXTENSIONS
TEMPLATES = [
    {
        "BACKEND": "django_jinja.backend.Jinja2",
        "OPTIONS": {
            "extensions": DEFAULT_EXTENSIONS + [
                "webpack_loader.contrib.jinja2ext.WebpackExtension",
            ],
        }
    }
]

Then in your base jinja template:

{{ render_bundle('main') }}


Enjoy your webpack with django :)

Alternatives to Django-Webpack-Loader

Below are known projects that attempt to solve the same problem:

Note that these projects have not been vetted or reviewed in any way by me.These are not recommendation.Anyone can add their project to this by sending a PR.

  • 背景与问题 最近在捯饬一个东西: 后台服务由 Django 提供 视图使用 Django 的模板进行处理 前端界面的一些逻辑,使用其他前端框架,例如 Vue 这意味着前端的代码需要使用 webpack 来进行打包,我遇到了两个问题: 问题一:如何在 Django 的模板中,和 webpack 输出的动态 JS 文件挂钩? 问题二:如何实现前后端代码的快速联调、测试? django-webpack-

  • https://github.com/owais/django-webpack-loader 1. 初始化django django-admin.py startproject VueDjango 使用django-admin工具初始化项目 cd WebpackDemo python manage.py startapp FreeMap 每一个project下会自带项目管理工具manage.py

  • 自己在django中写静态文件时,出过这样的问题: 对一个已经写好的文件(例: example.js, example.png, example.css),如果我再去修改/替换的话,如果最终文件的地址不变,用户的浏览器可能会因为缓存而依旧使用旧的文件。类似的,cdn服务商处可能也需要我们去手动刷新以更新。这样既麻烦,也容易出错。 之前在使用react的时候接触到了webpack,他有一个很方便的功

  • webpack打包时html-webpack-plugin不自动的引用CommonsChunkPlugin公共文件 webpack打包的时CommonsChunkPlugin抽出的公共js和css文件,html-webpack-plugin渲染出的html不自动的引用公共文件。 用wewbpack构建多页应用,每个页面单独一个入口js文件,用很多公共代码所以用了CommonsChunkPlugin

  • 我试图在我的项目中将我的前端和后端分离.我的前端由reactjs组成,路由将使用react-router完成,我的后端如果是Django,我打算使用前端对Django进行API(ajax)调用. 现在我不确定如何让这两个方面正确地相互交谈. 这是我的项目的link 这是我的项目结构: /cherngloong /app (frontend) /cherngloong /templates inde

  • 1.ViewSet 解析:ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典[比如{‘get’:‘list’}]的映射处理工作。 2.APIView 解析:DRF框架的视图的基类是APIView,APIView的基本使用和View类似: [1]Django默认的View请求对象是HttpRequest,REST framework的请求对象是Request。

  • |-[root] |-[project folder] |-setting.py |-urls.py |-wsgi.py |-env.py |-[modules] |-[app1] |-[api] |-[service] |-api1.py |-api2.py |-[view] |-

  • Javascript @NdagiStanley has mirrored the fork to have this repo here. This starterpack has proved useful to many and I thank you for the emails I have received from all of you. The reasoning behind t

  • Webpack配置 webpack 是需要传入一个配置对象(configuration object)。取决于你如何使用 webpack,可以通过两种方式之一:终端或 Node.js。下面指定了所有可用的配置选项。 注意整个配置中我们使用 Node 内置的 path 模块,并在它前面加上 __dirname这个全局变量。可以防止不同操作系统之间的文件路径问题,并且可以使相对路径按照预期工作。 选项

 相关资料
  • 更改历史 * 2017-11-12 王莹 webpack内容更新 第一章 webpack介绍 1.1 概述 Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs

  • art-template loader for webpack. Install npm install art-template npm install art-template-loader --save-dev Usage By default every local <img src="image.png"> is required (require('./image.png')).

  • Webpack 是一个模块打包器,主要目的是在浏览器上打包 JavaScript 文件。 TL;DR 捆绑 ES 模块、CommonJS 和 AMD 模块(以及绑定)。 可以创建在运行时异步加载的单个捆绑包或多个块(以减少初始加载时间)。 在编译过程中解决了依赖性,从而减小了运行时大小。 加载程序可以在编译时对文件进行预处理,例如,将 TypeScript 转换为 JavaScript、将Hand

  • 问题内容: 我开始在开发使用的服务器端渲染应用程序的环境中工作。我对每个Webpack包在开发和生产(运行时)环境中的作用感到非常困惑。 这是我的理解摘要: :是一个软件包,是一种工具,用于将Web应用程序的不同部分结合在一起,然后捆绑成一个.js文件(通常是)。然后,结果文件将在产品环境中提供以由应用程序加载,并包含运行代码的所有必需组件。功能包括缩小代码,缩小代码等。 :是一个提供 服务器 以

  • 本文向大家介绍webpack Webpack简单示例,包括了webpack Webpack简单示例的使用技巧和注意事项,需要的朋友参考一下 示例 使用Webpack的最低要求是以下命令: Web pack将获取源文件,编译到输出目标并解决源文件中的所有依赖关系。

  • 原文地址:https://cesiumjs.org/tutorials/cesium-and-webpack/ Cesium 和 Webpack Webpack是非常强大非常流行的JavaScript 模块打包工具。它可以让开发人员以一种简单直观的 require 方式去加载各种页面需要的文件,极大的方便了开源人员对代码和资源文件进行结构化设计。当编译的时候,它会跟踪代码依赖性,把所有的模型打包到