透明地使用webpack与django
项目描述
django-webpack-loader
使用简单的模板标签将Webpack包集成到Django模板中
{% load render_bundle from webpack_loader %}
<html>
<head>
{% render_bundle 'main' 'css' %}
</head>
</html>
幕后,Django Webpack Loader消耗由webpack-bundle-tracker生成的stats文件,并允许您在Django中使用生成的包。
提供变更日志。
兼容性
通常,Python、Django和Node LTS版本将支持到EOL。有关详细信息,请检查tests/tox.ini
。
不在tests/tox.ini
中列出的版本可能仍然可以使用,但维护者不会测试它们,也不会解决与它们相关的问题。
以下示例在Webpack 5中。
安装
npm install --save-dev webpack-bundle-tracker
pip install django-webpack-loader
配置
要启动一个带有有见地的开发和生产设置的完整示例项目,您可以查看django-react-boilerplate
。对于更灵活的配置,请继续阅读。
配置webpack-bundle-tracker
在配置 django-webpack-loader
之前,我们先配置 webpack-bundle-tracker
所需的内容。更新你的 Webpack 配置文件(它通常位于项目根目录下的 webpack.config.js
)。确保你的文件看起来像这样(根据需要调整):
const path = require("path");
const webpack = require("webpack");
const BundleTracker = require("webpack-bundle-tracker");
module.exports = {
context: __dirname,
entry: "./assets/js/index",
output: {
path: path.resolve(__dirname, "assets/webpack_bundles/"),
publicPath: "auto", // necessary for CDNs/S3/blob storages
filename: "[name]-[contenthash].js",
},
plugins: [
new BundleTracker({ path: __dirname, filename: "webpack-stats.json" }),
],
};
上面的配置期望 index.js
(应用程序入口文件)位于 /assets/js/
目录内(本指南后续将假定所有前端相关文件都放置在 /assets/
目录下,不同类型的文件按其子目录排列)。
生成的编译文件将放在 /assets/webpack_bundles/
目录下,有关包和资源的 统计文件(webpack-stats.json
)将存储在项目根目录。你可以将 webpack-stats.json
添加到 .gitignore
中。
配置 Django 设置文件
首先,将 webpack_loader
添加到 INSTALLED_APPS
中。
INSTALLED_APPS = (
...
'webpack_loader',
...
)
以下是使用 django-webpack-loader
时 Django 设置文件的推荐设置。
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'assets'),
)
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'webpack_bundles/',
'CACHE': not DEBUG,
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
}
}
请注意,你必须设置你的静态资源和 Webpack 包所在的路径到 STATICFILES_DIRS
。
对于这种设置,我们使用 Django 提供的 DEBUG
变量。由于在生产环境中(DEBUG = False
),资产文件不会不断更改,我们可以安全地缓存结果(CACHE=True
)并优化流程,因为 django-webpack-loader
只会读取一次统计文件并将资产路径存储在内存中。如果 CACHE=False
,我们将始终读取统计文件以获取资产路径。
STATS_FILE
参数表示由 webpack-bundle-tracker
生成的输出文件。由于在 Webpack 配置文件中我们将其命名为 webpack-stats.json
并存储在项目根目录,我们必须在后端复制这个设置。
在开发过程中,统计文件会经常更改,因此我们希望始终检查其更新版本(每 0.1 秒检查一次,如 POLL_INTERVAL
所定义)。
⚠️ 在生产环境(
DEBUG=False
)中,我们只获取一次统计文件,因此POLL_INTERVAL
被忽略。
IGNORE
是一个正则表达式列表。如果由 Webpack 生成的文件与其中一个表达式匹配,则该文件不会被包含在模板中。
编译前端资产
使用 Webpack,在使用 django-webpack-loader
在 Django 模板中之前,你必须使用 webpack-bundle-tracker
生成前端包和统计文件。请注意,你可能会在开发和生产中使用不同的配置。流程应如下所示
flowchart TD
A("Run webpack")
A --> |CSS, JS, imgs, fonts| B(Collect compiled assets)
A --> |webpack-stats.json| C(Read on Django templates)
在开发中,我们可以简单地这样做
# in one shell
npx webpack --mode=development --watch
# in another shell
python manage.py runserver
查看开发中的完整示例。
此外,通过特定的配置,还提供了热重载。查看本节。
⚠️ 对于在生产环境中编译和提供前端资产,请参阅本节。
用法
为了将前端代码渲染到 Django 模板中,我们使用 render_bundle
模板标签。
它的行为是接受一个字符串,包含统计文件中入口点的名称(在我们的例子中,我们使用 main
,这是 默认),然后它会继续包含该入口点下的所有文件。你可以在这里了解更多关于入口点概念的信息这里。
⚠️ 你也可以在这里查看如何使用多个
entry
值的示例这里。
以下是模板中 render_bundle
的基本用法
{% load render_bundle from webpack_loader %}
<html>
<head>
{% render_bundle 'main' 'css' %}
</head>
</html>
这将渲染模板中所需的正确 <script>
和 <link>
标签。
在测试中使用
为了运行出现在 render_bundle
中的测试,由于在那个点我们没有 webpack-bundle-tracker
来生成统计文件,渲染包的调用将会失败。解决方案是在您的测试设置中使用 FakeWebpackLoader
WEBPACK_LOADER['DEFAULT']['LOADER_CLASS'] = 'webpack_loader.loaders.FakeWebpackLoader'
在生产环境中使用
建议的方法是在 部署阶段 生成前端包和统计文件的生产管道。我们建议将生成的包和统计文件放在版本控制之外。换句话说,将 webpack-stats.json
和 assets/webpack_bundles/
添加到您的 .gitignore
假设静态文件已通过 Django 内置或类似 django-storages 正确配置,简单的生产部署可以使用 Django 的 collectstatic
。请记住,Django 设置的 STATICFILES_DIRS
、BUNDLE_DIR_NAME
、STATS_FILE
和 Webpack 的 output.path
必须兼容
// webpack.config.js
module.exports = {
// ...
context: __dirname,
output: {
// Emit bundle files at "assets/webpack_bundles/":
path: path.resolve(__dirname, "assets/webpack_bundles/"),
publicPath: "auto", // necessary for CDNs/S3/blob storages
filename: "[name]-[contenthash].js",
},
plugins: [
// Emit 'webpack-stats.json' in project root for Django to find it:
new BundleTracker({ path: __dirname, filename: "webpack-stats.json" }),
],
};
# app/settings.py
BASE_DIR = ... # set to project root
STATICFILES_DIRS = (
# make Django collect all "assets/" and "assets/webpack_bundles"
# to be served at "my-static-url.com/asset-name.png"
# and "my-static-url.com/webpack_bundles/main.js"
os.path.join(BASE_DIR, 'assets'),
)
WEBPACK_LOADER = {
'DEFAULT': {
# Bundle directory, like in "my-static-url.com/webpack_bundles/main.js":
'BUNDLE_DIR_NAME': 'webpack_bundles/',
# Absolute path to where 'webpack-stats.json' is in Django project root:
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
# ...
}
}
在您的部署脚本中,必须在调用 collectstatic
之前先以生产模式运行您的 Webpack 构建
NODE_ENV=production webpack --progress --bail --mode=production
python manage.py collectstatic --noinput
这意味着我们正在构建资产,由于我们在 Webpack 构建管道中使用了 webpack-bundle-tracker
,webpack-stats.json
统计文件也被填充。如果您遵循默认配置,webpack-stats.json
将位于 Django 项目的根目录(BASE_DIR
),并且 render_bundle
模板标签将能够使用它。
然而,此包的生产使用相对灵活,因为整个 Django-Webpack 集成仅依赖于 webpack-stats.json
文件。
⚠️ Heroku 是一个自动为您运行 collectstatic 的平台,因此您需要设置环境变量
DISABLE_COLLECTSTATIC=1
,并在运行 Webpack 后手动运行 collectstatic。在 Heroku 上,这通过post_compile
钩子实现。这里有一个 示例。
高级使用
热重载
热重载(热模块替换)对于改善开发工作流程至关重要。如果您想为项目启用它,请查看 此示例,特别是 webpack.config.js 的配置。关键是设置 publicPath
和 devServer
。
动态导入
如果您想使用 动态导入,请查看 此示例,特别是 webpack.config.js 的配置。
webpack-bundle-tracker
的额外选项
请查看 webpack-bundle-tracker
的 README 了解所有支持选项,例如相对路径、完整性散列、时间戳日志等。
Django 中的额外 WEBPACK_LOADER
设置
按照以下方式设置这些额外设置
WEBPACK_LOADER = {
'DEFAULT': {
# settings go here
}
-
TIMEOUT
是 webpack_loader 等待 Webpack 完成编译并引发异常之前应等待的秒数。设置为0
、None
或省略设置将禁用超时。 -
INTEGRITY
是启用 子资源完整性 的标志,用于渲染<script>
和<link>
标签。完整性散列从统计文件和BundleTracker
的一侧配置中获得,其中需要配置选项integrity: true
。 -
LOADER_CLASS
是一个字符串形式的完全限定 Python 类名,用于存储自定义 Webpack 加载器。这是自定义如何加载统计文件行为的地方。例如,可以从数据库、缓存、外部 URL 等加载统计文件。为了方便,可以扩展webpack_loader.loaders.WebpackLoader
。很可能会在load_assets
方法中添加自定义行为。这应该返回一个包含统计文件的对象。
以下是从外部 URL 加载的简单示例
import requests
from webpack_loader.loaders import WebpackLoader
class ExternalWebpackLoader(WebpackLoader):
def load_assets(self):
url = self.config['STATS_URL']
return requests.get(url).json()
SKIP_COMMON_CHUNKS
(默认:False
)是一个标志,防止已生成的块再次包含在同一页中。这通常发生在您在每个 Django 模板中使用多个入口点(多个render_bundle
调用)时。通过启用此选项,您可以获得与 HtmlWebpackPlugin 相同的默认行为。使用skip_common_chunks
在render_bundle
上的注意事项相同,请参阅下面的该部分以获取更多详细信息。
根据文件扩展名渲染
render_bundle
还可以接受第二个参数,即可以匹配的文件扩展名。当您想单独渲染不同类型的文件时,这非常有用。例如,要渲染 CSS 到 head 和 JS 到底部,我们可以这样做
{% load render_bundle from webpack_loader %}
<html>
<head>
{% render_bundle 'main' 'css' %}
</head>
<body>
....
{% render_bundle 'main' 'js' %}
</body>
</head>
使用预加载
在 render_bundle
模板标签中,可以使用 is_preload=True
选项添加 rel="preload"
链接标签
{% 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>
访问其他 Webpack 资产
webpack_static
模板标签提供了在 Django 模板中加载由 Webpack 管理的静态资产的便利。它类似于 Django 内置的 static
标签,但用于 Webpack 资产。
在下面的示例中,logo.png
可以是任何与任何 npm 包一起分发的静态资产
{% load webpack_static from webpack_loader %}
<!-- render full public path of logo.png -->
<img src="{% webpack_static 'logo.png' %}"/>
公共路径基于 webpack.config.js
的 output.publicPath。
请注意,此方法将使用原始资产文件,而不是 Webpack 管道中经过处理的文件,如果该文件已经过此流程(例如:在 React 端导入了一个图像并使用它,React 组件中使用的文件可能具有哈希字符串的名称等。此处理文件将与您使用 webpack_static
获取的文件不同)。
在 render_bundle
上使用 skip_common_chunks
您可以使用参数 skip_common_chunks=True
或 skip_common_chunks=False
来覆盖特定捆绑包的全局 SKIP_COMMON_CHUNKS
设置。
为了使此选项生效,django-webpack-loader
需要模板上下文中存在 request
对象。默认情况下,通过 django.template.context_processors.request
上下文处理器传递 request
对象,所以请确保您有它。
如果您由于某些原因(例如使用 Template.render
或直接使用 render_to_string
而没有传递请求)在上下文中没有 request
,您将在控制台收到警告,并且公共块将保持重复。
追加文件扩展名
可以使用 suffix
选项在文件 URL 的末尾追加一个字符串。例如,如果您的 Webpack 配置生成压缩的 .gz
文件,则可以这样做。
{% 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>
多个 Webpack 配置
django-webpack-loader
还支持多个 Webpack 配置。假设您有不同的 Webpack 配置,每个配置有不同的 output.path
,则以下配置在设置中定义了 2 个 Webpack 统计文件,并使用模板标签中的 config
参数来影响从哪个统计文件加载捆绑包
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>
文件 URL 而不是 HTML 标签
如果您需要资产 URL 而不是 HTML 标签,则可以使用 get_files
模板标签。常见用例是为 JavaScript 插件指定自定义 CSS 文件的 URL。
get_files
与 render_bundle
的工作方式完全相同,除了它返回一个匹配的文件列表,并允许您将列表分配给自定义模板变量。
返回列表中的每个对象都有 2 个属性
name
,它是统计文件中块的名字;url
,可以是- 如果资源有,则为
publicPath
; - 如果没有
publicPath
,则为静态文件存储中资源的path
。
例如
{% load get_files from webpack_loader %}
{% get_files 'editor' 'css' as editor_css_files %}
CKEDITOR.config.contentsCss = '{{ editor_css_files.0.url }}';
<!-- or list down name and url for every file -->
<ul>
{% for css_file in editor_css_files %}
<li>{{ css_file.name }} : {{ css_file.url }}</li>
{% endfor %}
</ul>
Jinja2 配置
如果您需要在 Jinja 模板中输出资源,我们提供了一个与 django-jinja 兼容的 Jinja2 扩展。
要安装扩展,请将其添加到 TEMPLATES
配置中的 ["OPTIONS"]["extension"]
列表。
from django_jinja.builtins import DEFAULT_EXTENSIONS
TEMPLATES = [
{
"BACKEND": "django_jinja.backend.Jinja2",
"OPTIONS": {
"extensions": DEFAULT_EXTENSIONS + [
"webpack_loader.contrib.jinja2ext.WebpackExtension",
],
}
}
]
然后在您的基 Jinja 模板中,执行
{{ render_bundle('main') }}
注意:Jinja2 中的 get_files
被称为 webpack_get_files
。
从版本 < 1.0.0 迁移
为了使用 django-webpack-loader>=1.0.0
,您必须确保在 JavaScript 端使用了 webpack-bundle-tracker@1.0.0
。建议您始终保持两个包的至少小版本兼容性,以实现完全兼容。
贡献
该项目包含一个 Makefile,它提供了用于构建、安装和发布项目的几个有用命令。请随时打开 PR 或创建问题!
可用命令
clean
:删除生成的文件和目录。build
:清理项目并构建分发包。test
:运行测试。install
:安装项目的构建依赖项。如果不存在,将初始化虚拟环境。publish
:构建分发包并将它们发布到指定的仓库。register
:在指定的仓库中注册包。
要执行命令,请在项目的根目录中运行 make <command>
。
虚拟环境设置
ENV
:虚拟环境名称。(默认:venv
)REPOSITORY
:发布分发包的仓库。(默认:pypi
)
特别感谢
Django Webpack Loader 最初由 Owais Lone 创建,自推出以来收到了 50 多位开发者的贡献,以及许多在问题、评论、文章、演讲等方面提供帮助的人。感谢所有为 Django Webpack Loader 社区做出贡献的人!
商业支持
该项目目前由 Vinta Software 维护,并用于 Vinta 客户的产品中。我们一直在寻找令人兴奋的工作,如果您需要任何商业支持,请随时联系我们:contact@vinta.com.br
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源分发
构建分发
哈希 for django_webpack_loader-3.1.1-py2.py3-none-any.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 15c05cb685b113c5e6f947efa8ee3888a03c2969a2dd0da4c7610b3e695f67ba |
|
MD5 | 610e42d9ab049628b93a63a7afce0087 |
|
BLAKE2b-256 | e901121be0ea43ff35e19a6f66c0d23a2b06b68189e454eb92042dd99f54b378 |