通过Django模板替换Webpack热模块

时间:2017-08-09 19:35:21

标签: django reactjs webpack

我试图为通过Django模板系统提供的捆绑前端静态资产设置热模块替换,如果可能的话。我每当编译资产发生变化时,都会通过livereload刷新页面,但编译时间越来越长,任何CSS更改都会导致整页重新加载。

这是Django中模板文件的一个示例。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!-- Header Links -->
  </head>
  <body>
    <div id="app"></div>

    <script type="text/javascript">
      window.CONFIG = {
        /** Injected application configuration from Django. */
      };
    </script>

    <!-- Webpack bundle url -->
    <script src="{{ bundle_url }}"></script>

  </body>
</html>

我已经能够通过webpack dev服务器提供资源,并通过模板变量注入bundle url http://localhost:3000/bundle.js,所以我可以在视图中看到该应用程序。

Webpack配置

'use strict';

const webpack = require('webpack');
const CONFIG = require('./config');

/**
 * Webpack configuration for a development environment.
 * @type {Object}
 */
module.exports = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    require.resolve('core-js/shim'),
    CONFIG.PATHS.ENTRY,
  ],
  output: {
    path: CONFIG.PATHS.BUILD,
    filename: CONFIG.OUTPUT_FILENAME,
  },
  module: {
    rules: CONFIG.SHARED_RULES.concat([{
      test: /\.css$/,
      use: ['style-loader', 'css-loader'],
    }, {
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader']
    }]),
  },
  resolve: CONFIG.WEBPACK_RESOLVE,
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
};

启动脚本:

'use strict';

// Crashes the script on unhandled rejections instead of silently ignoring.
process.on('unhandledRejection', (error) => { throw error; });

process.env.NODE_ENV = 'development';

// Vendor
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const chalk = require('chalk');

// Local
const WEBPACK_CONFIG = require('../config/webpack.config.dev');
const CONFIG = require('../config/config');

const PORT = parseInt(process.env.PORT, 10) || CONFIG.DEFAULT_PORT;
const HOST = process.env.HOST || CONFIG.DEFAULT_HOST;
const URL = `http://${HOST}:${PORT}/`;

const compiler = webpack(WEBPACK_CONFIG);
const server = new WebpackDevServer(compiler, {
  compress: true,
  hot: true,
  host: HOST,
  stats: 'minimal',
});

server.listen(PORT, HOST, (error) => {
  if (error) { return console.log(chalk.red(error)); }

  console.log(chalk.cyan(`Starting the development server at ${URL}...`));


  ['SIGINT', 'SIGTERM'].forEach((signal) => {
    process.on(signal, () => {
      server.close();
      process.exit();
    });
  });
});

我不确定开发服务器如何触发热重新加载。我的印象是该捆绑包包含一个脚本,该脚本连接到开发服务器上的Websocket连接,并且该连接将触发脚本下载并显示新资产。但情况可能并非如此,而且我还没有找到任何有关如何传达热重载的信息。我只发现了客户端收到更新后热重载如何工作的一般概述。

2 个答案:

答案 0 :(得分:1)

经过大量的搜索,我终于找到了解决问题的方法。我找到了information about how to integrate webpack-dev-server with an existing server in the old webpack docs,所以我摆脱了整个构建脚本,并用package.json中的一个脚本替换它,它只使用了webpack-dev-server而没有任何标志:

"scripts": {
  "start": "cross-env NODE_ENV=development webpack-dev-server",
  // Scripts...
}

这会自动将热模块替换代码注入我的包中,并在更改时刷新我的页面。这比我之前的livereload服务器快得多。捆绑包是通过我的应用程序模板中的URL http:localhost:8080/bundle.js引用的,而不是通过本地路径引用的。由于捆绑包保存在内存中,本地路径无论如何都不会起作用。

该网址还解释了如何使--inline --hot功能正常运行,但我无法让它在我的设置上运行。

如果您需要使用本地路径而不是通过url引用捆绑包,那么您必须依赖于使用webpack的监视模式并手动刷新页面或依赖Django插件。我发现的解决方案对我来说很有效,因为它反映了我们的生产环境。我们的Django部署通过我们管理的CDN引用前端资产。如果你必须使用Django代码部署前端资产,它可能不适合你,但如果你创建一个在两个不同的应用程序模板之间切换的Django设置,它可能是有效的:一个用于使用URL拉动的开发在脚本中,一个用于生成,引用STATICFILES_DIRS

中的文件

答案 1 :(得分:0)

我不认为的问题是Webpack的错。我注意到当我让Django提供我的React文件时会出现这些速度问题。当您使用Django时,您的文件由Django服务器提供服务,与webpack-dev服务器相比,这本身就很慢。 webpack dev服务器与Django之间的整个通信过程可能需要时间,必须让Django服务器触发更改,然后再次重新提供静态文件。

一个解决方案是将React前端代码与后端代码隔离,让React使用Django的REST API。它运行非常顺畅,减少了服务器上的大量负载。