django webpack loader:React 应用程序热重载失败

django webpack loader: React app hot reload failure

一些上下文:我正在开发一个 Django 应用程序,我想在模板中集成一个 React 组件。我是 React 的新手,对 Django 不是。

所以,我正在尝试设置一个 React 开发环境,在我的 Django 模板中热重新加载 React 组件。我遵循了这些教程:

而且看起来还不错,因为我在修改和保存我的js源代码时有以下反馈:

在 npm 控制台中:

> node server.js

Listening at 0.0.0.0:3000
Hash: ecfef9f1eea0022319ef
Version: webpack 3.3.0
Time: 6294ms
                       Asset     Size  Chunks                    Chunk Names
main-ecfef9f1eea0022319ef.js  1.37 MB       0  [emitted]  [big]  main
  [26] ./node_modules/react/react.js 56 bytes {0} [built]
  [77] (webpack)/hot/log.js 1.04 kB {0} [built]
 [141] (webpack)/hot/emitter.js 77 bytes {0} [built]
 [142] ./node_modules/react-dom/index.js 59 bytes {0} [built]
 [169] ./assets/js/App.js 779 bytes {0} [built]
 [170] multi react-hot-loader/patch webpack-dev-server/client?http://localhost:3000 webpack/hot/only-dev-server ./assets/js/index.js 64 bytes {0} [built]
 [171] ./node_modules/react-hot-loader/patch.js 41 bytes {0} [built]
 [172] ./node_modules/react-hot-loader/lib/patch.js 209 bytes {0} [built]
 [293] (webpack)-dev-server/client?http://localhost:3000 5.83 kB {0} [built]
 [302] ./node_modules/loglevel/lib/loglevel.js 6.74 kB {0} [built]
 [335] (webpack)-dev-server/client/overlay.js 3.6 kB {0} [built]
 [340] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
 [342] (webpack)/hot/only-dev-server.js 2.37 kB {0} [built]
 [344] ./assets/js/index.js 1.02 kB {0} [built]
 [430] ./node_modules/react-hot-loader/index.js 41 bytes {0} [built]
    + 430 hidden modules
webpack: Compiled successfully.
webpack: Compiling...
Hash: 8fd43db8b836382b9172
Version: webpack 3.3.0
Time: 206ms
                               Asset       Size  Chunks                    Chunk Names
        main-8fd43db8b836382b9172.js    1.37 MB       0  [emitted]  [big]  main
0.ecfef9f1eea0022319ef.hot-update.js  892 bytes       0  [emitted]         main
ecfef9f1eea0022319ef.hot-update.json   43 bytes          [emitted]
  [26] ./node_modules/react/react.js 56 bytes {0}
  [77] (webpack)/hot/log.js 1.04 kB {0}
 [141] (webpack)/hot/emitter.js 77 bytes {0}
 [142] ./node_modules/react-dom/index.js 59 bytes {0}
 [169] ./assets/js/App.js 780 bytes {0} [built]
 [170] multi react-hot-loader/patch webpack-dev-server/client?http://localhost:3000 webpack/hot/only-dev-server ./assets/js/index.js 64 bytes {0}
 [171] ./node_modules/react-hot-loader/patch.js 41 bytes {0}
 [172] ./node_modules/react-hot-loader/lib/patch.js 209 bytes {0}
 [293] (webpack)-dev-server/client?http://localhost:3000 5.83 kB {0}
 [302] ./node_modules/loglevel/lib/loglevel.js 6.74 kB {0}
 [335] (webpack)-dev-server/client/overlay.js 3.6 kB {0}
 [340] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
 [342] (webpack)/hot/only-dev-server.js 2.37 kB {0}
 [344] ./assets/js/index.js 1.02 kB {0}
 [430] ./node_modules/react-hot-loader/index.js 41 bytes {0}
    + 430 hidden modules
webpack: Compiled successfully.

并且在 react-dev-tools 控制台中我得到:

[HMR] Waiting for update signal from WDS...  main-ecfef9f1eea0022319ef.js:8192:4
[WDS] Hot Module Replacement enabled.  main-ecfef9f1eea0022319ef.js:22302:3
[WDS] App updated. Recompiling... main-ecfef9f1eea0022319ef.js:22305:3
[WDS] App hot update...  main-ecfef9f1eea0022319ef.js:22431:3
[HMR] Checking for updates on the server...  main-ecfef9f1eea0022319ef.js:8192:4
[HMR] Updated modules:  main-ecfef9f1eea0022319ef.js:8192:4
[HMR]  - 169  main-ecfef9f1eea0022319ef.js:8192:4
[HMR] Consider using the NamedModulesPlugin for module names.  main-ecfef9f1eea0022319ef.js:8192:4
[HMR] App is up to date.

这看起来很不错,但我的 django 页面上的 React 组件几乎保持不变,当然,除非我按 F5。我想我可能遗漏了一些明显的东西,我将不胜感激任何有用的指示。

这是我的设置:

package.json(仅限部门):

"devDependencies": {
    "babel": "^6.23.0",
    "babel-core": "^6.0.0",
    "babel-loader": "^7.1.1",
    "babel-preset-env": "^1.6.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-hot-loader": "^3.0.0-beta.7",
    "webpack": "^3.3.0",
    "webpack-bundle-tracker": "^0.2.0",
    "webpack-dev-server": "^2.6.1"
  }

.babelrc:

{
    "presets": ["env", "es2015", "react"],
    "plugins": ["react-hot-loader/babel"]
}

webpack.config.js:

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

const config = {
  context: __dirname,

  entry: [
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './assets/js/index.js', // entry point of our app. assets/js/index.js should require other js modules and dependencies it needs
  ],

  output: {
      path: path.resolve('./assets/bundles/'),
      filename: "[name]-[hash].js",
      publicPath: 'http://localhost:3000/assets/bundles/' // Tell django to use this URL to load packages and not use STATIC_URL + bundle_name
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(), // don't reload if there is an error
    new BundleTracker({filename: './webpack-stats.json'}),
  ],

  module: {
    rules: [
      // we pass the output from babel loader to react-hot loader
      { test: /\.jsx?$/, exclude: /node_modules/, use: ['babel-loader'], },
    ],
  },

  resolve: {
    modules: ['node_modules', 'bower_components'],
    extensions: ['.js', '.jsx']
  },

  devServer: {
    hot: true,
    contentBase: './assets/js',
  }
}

module.exports = config;

server.js:

var webpack = require('webpack')
var WebpackDevServer = require('webpack-dev-server')
var config = require('./webpack.config')

new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    hot: true,
    inline: true,
    historyApiFallback: true,
    headers: {
        'Access-Control-Allow-Origin': '*',
    },
}).listen(3000, '0.0.0.0', function(err, result) {
    if (err) {
        console.log(err)
    }

    console.log('Listening at 0.0.0.0:3000')
})

assets/js/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './App'


const render = Component => {
    ReactDOM.render( 
        <AppContainer>
        <Component />
        </AppContainer>,
        document.getElementById('react-app')
    )
}
render(App)
if (module.hot) {
    module.hot.accept('./App', () => { render(App) })
}

assets/js/App.js:

import React from 'react';

const App = () => {
return (
    <div>
    <h1>Hello Whosebug</h1>
    </div>
    );
}
export default App;

django settings.py:

WEBPACK_LOADER = {
    'DEFAULT': {
        'CACHE': not DEBUG,
        'BUNDLE_DIR_NAME': 'bundles/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'TIMEOUT': None,
        'IGNORE': ['.+\.hot-update.js', '.+\.map']
    }
}

django 模板:

{% load render_bundle from webpack_loader %}

{% block content-right %}
    <div id="react-app"></div>
    {% render_bundle 'main' %}
{% endblock content-right %}

在你的index.js

而不是:

if (module.hot) {
    module.hot.accept('./App', () => { render(App) })
}

使用:

if(module.hot) {
    module.hot.accept();
}

github 中存在问题:https://github.com/webpack/webpack-dev-server/issues/100

或将 Babel ES2015 预设更改为 ["es2015", { "modules": false }]