简体   繁体   English

Django/Webpack - 如何使用 webpack 开发服务器提供生成的 webpack 包

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM