[英]Django/Webpack - How to serve generated webpack bundles with webpack dev server
Django's 'static' tag generates urls using STATIC_URL, which results in something like '/static/myapp/js/bundle.js' Mean while, webpack-dev-server is serving bundles from the url 'localhost:3000' Django 的 'static' 标签使用 STATIC_URL 生成 url,这会导致类似 '/static/myapp/js/bundle.js' 的结果同时,webpack-dev-server 正在提供来自 url 'localhost:3000' 的包
My question is how do I get Django 'static' template tag to generate a different url ( which points to webpack dev server) for js bundles.我的问题是如何让 Django 'static' 模板标签为 js 包生成不同的 url(指向 webpack 开发服务器)。 Of course I can hardcode it in the template, but that would not be a good solution.
当然,我可以在模板中对其进行硬编码,但这不是一个好的解决方案。
Below is my project configuration下面是我的项目配置
webpack.config.js webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const BundleTracker = require('webpack-bundle-tracker')
module.exports = {
mode: 'development',
context: path.dirname(path.resolve(__dirname)),
entry: {
index: './typescript_src/index.ts',
},
output: {
path: path.resolve('./myproject/assets/myapp/bundles/'),
filename: "[name]-[hash].js"
},
resolve: {
extensions: ['.ts', '.js' ]
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new BundleTracker({filename: './myproject/webpack-stats.json'})
],
devServer: {
port: 3000,
publicPath: '/myapp/bundles/',
// hot: true,
headers: {
"Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
}
}
}
settings.py设置.py
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'BUNDLE_DIR_NAME': 'myapp/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']
}
}
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'assets'),
)
Initially I decided webpack should serve other static files as well during development最初我决定 webpack 也应该在开发过程中提供其他静态文件
webpack.config.js webpack.config.js
devServer: {
port: 3000,
publicPath: '/myapp/bundles/',
contentBase: path.resolve('./myproject/assets')
// hot: true,
headers: {
"Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
}
settings.py设置.py
# in development mode serve from wepack dev server
if DEBUG:
STATIC_URL = 'http://localhost:3000/'
else:
STATIC_URL = '/static/'
But I later realized I have to serve static files of other apps (admin, tinymce, ...), which is impossible for webpack Dev server to reach但后来我意识到我必须提供其他应用程序(admin、tinymce 等)的静态文件,这是 webpack Dev 服务器无法访问的
The problem here is that the url generated by 'render_bundle' tag of django-webpack-loader (/static/myapp/bundles/bundle-name.js) will result in a Http 404 because webpack-dev-server keeps the generated bundle in memory and not on disk这里的问题是 django-webpack-loader (/static/myapp/bundles/bundle-name.js) 的 'render_bundle' 标签生成的 url 将导致 Http 404,因为 webpack-dev-server 将生成的包保留在内存而不是磁盘
Also if I set另外如果我设置
STATIC_URL = localhost:3000
and configure webpack-dev-server to serve other static files of my app, static files of other apps won't be served并配置 webpack-dev-server 为我的应用程序的其他静态文件提供服务,其他应用程序的静态文件将不会提供
Let's analyze the issue:我们来分析一下这个问题:
We have 2 servers and we want to route requests to one or the other based on the path requested:我们有 2 个服务器,我们希望根据请求的路径将请求路由到其中一个:
"/static/webpackbundles/** ==> webpack dev server
other paths ==> django dev server
This is exactly the job of a proxy server, it can be achieved with a third server (haproxy, nginx ...), but that might seem like an overkill, especially if we know that webpack dev server
can be used as a proxy!这正是代理服务器的工作,它可以通过第三台服务器(haproxy、nginx ...)来实现,但这似乎
webpack dev server
过头了,尤其是当我们知道webpack dev server
可以用作代理时! (https://webpack.js.org/configuration/dev-server/#devserverproxy ) (https://webpack.js.org/configuration/dev-server/#devserverproxy )
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: '/path/to/django_project/django_project/static/webpackbundles',
publicPath: '/static/webpackbundles/',
},
devServer: {
contentBase: '/path/to/django_project/django_project/static/webpackbundles',
hot: true,
proxy: {
'!/static/webpackbundles/**': {
target: 'http://localhost:8000', // points to django dev server
changeOrigin: true,
},
},
},
};
In your django template:在您的 Django 模板中:
<script type="text/javascript" src="{% static 'webpackbundles/main.js' %}"></script>
Now access your django app/site using webpack dev server
address: ex: http://localhost:8081
现在使用
webpack dev server
地址访问您的 django 应用程序/站点:例如: http://localhost:8081
With this simple config you'll have browser auto refresh and hot module replacement.通过这个简单的配置,您将拥有浏览器自动刷新和热模块更换功能。 You will not need to change anything in django, also no need for django-webpack-loader
您不需要在 django 中更改任何内容,也不需要 django-webpack-loader
Building on @Ejez answer, i was able to configure webpack-dev-server to serve all static files (including, media files)基于@Ejez 的回答,我能够配置 webpack-dev-server 来提供所有静态文件(包括媒体文件)
webpack.config.js webpack.config.js
module.exports = {
// project root (usually package.json dir)
context: path.dirname(path.resolve(__dirname)),
output: {
path: path.resolve('./path/to/bundles/'),
filename: "[name]-[hash].js"
},
resolve: {
extensions: ['.ts', '.js' ]
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
plugins: [
new CleanWebpackPlugin(),
new BundleTracker({filename: '/path/to/webpack-stats.json'})
],
optimization: {
splitChunks: {
chunks: 'all',
name: 'lib' // bundle all their party libraries in lib.js
}
},
devServer: {
// if you do not mind webpack serving static files of other apps
// collect them (with django collectstatic) into /static_root/static/
// this way webpack-dev-server can serve from your own app's /static/
// directory and also /static_root/static/ directory (which contains
// static files of other apps
contentBase: [path.resolve('./project'), path.resolve('./project/static_root')],
// webpack bundles will be served from http://locahost:3000/static/project/bundles/
publicPath: '/static/project/bundles/',
port: 3000,
// proxy all request except (static and media files) to django dev server
proxy: [{
context: ['**', '!/static/**', '!/media/**'],
target: 'http://localhost:8000',
changeOrigin: true,
}]
}
}
Now you can access your project from webpack-dev-server url localhost:3000
.现在您可以从 webpack-dev-server url
localhost:3000
访问您的项目。 Do not forget to start both dev servers (webpack and django)不要忘记启动两个开发服务器(webpack 和 django)
Is generally not justified using STATICFILES_DIRS, instead use STATIC_ROOT.一般不合理使用STATICFILES_DIRS,而是使用STATIC_ROOT。 If You have permission to copy static files to the project folder then use STATIC_ROOT.
如果您有权将静态文件复制到项目文件夹,则使用 STATIC_ROOT。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.