Webpack HMR引发React syntheticEvent错误,导致jsPDF出现问题。

7

系统信息:

OSX 10.12.4 Sierra
Node v7.10.0
npm v4.2.0

已测试的浏览器:

Chrome 58.0.3029.110
Safari 10.1
Firefox 53.0
问题:

我有一个正在生产中有效运行的应用程序,我已经克隆并尝试更新它,以便为构建续集做好准备。然而,在更新它/React/HMR到最新版本时,我遇到了一个奇怪的Webpack问题。

HMR将连接,并且Webpack似乎编译得很好。然而,与页面交互(例如点击)会生成以下错误:

syntheticEvent Error

显然,该应用程序此时不再可用,因为单击不会触发任何事件。有趣的是,我们还在Node控制台和浏览器上收到以下404错误:

404 (注意:这似乎是一个包含函数的巨大查询字符串,特别引用了syntheticEvent。如果您想要,我可以打印整个内容给您看)

NODE v6.3.1

相关NPM:

"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.4",

"webpack": "^2.5.1",
"webpack-dev-middleware": "^1.10.2",
"webpack-hot-middleware": "^2.18.0"

"babel-cli": "^6.11.4",
"babel-core": "^6.24.1",
"babel-eslint": "^7.2.1",
"babel-loader": "^7.0.0",
"babel-plugin-array-includes": "^2.0.0",
"babel-plugin-transform-decorators-legacy": "^1.0.0",
"babel-plugin-transform-object-assign": "^6.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-1": "^6.24.1",

WEBPACK.CONFIG.DEV.JS:

var path = require('path');
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var hotMiddlewareScript = 'webpack-hot-middleware/client';

console.log('using the dev config file');
console.log('THE PUBLIC PATH: ' + path.join(__dirname, '/CLIENTSIDE/static'));

module.exports = {
  devtool: 'eval',
  entry: {
    background: ['webpack-hot-middleware/client', path.join(__dirname, '/CLIENTSIDE/components/background')],
    uniqueShare: ['webpack-hot-middleware/client',  path.join(__dirname, '/CLIENTSIDE/components/uniqueShare')],
    starRating: ['webpack-hot-middleware/client', path.join(__dirname, '/CLIENTSIDE/components/starRating')],
    testingPage: ['webpack-hot-middleware/client', path.join(__dirname, '/CLIENTSIDE/components/testingPage')],
    style: ['webpack-hot-middleware/client', path.join(__dirname, '/CLIENTSIDE/components/style')]
  },
  output: {
    path: path.join(__dirname, '/CLIENTSIDE/static'),
    filename: '[name].js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  ],
  module: {
    loaders: [
        {
            test: /\.(js|jsx)$/,
            exclude: /(node_modules|bower_components)/,
            loader: 'babel-loader',
            query: {
              cacheDirectory: true,
              presets: ['react', 'es2015', 'stage-1'],
              plugins: ['transform-decorators-legacy', 'transform-object-assign', 'array-includes'],
            },
        },
        {
            test: /\.scss$/,
            loaders: ['style-loader', 'css-loader', 'sass-loader']
        }
      ]
    }
  };

我们加载 HMR 的位置:

  console.log('****************************** RUNNING IN DEV MODE ******************************');
  var webpack = require('webpack');
  var webpackConfig = require('./webpack.config.dev');
  var compiler = webpack(webpackConfig);

  console.log('Looking for the HMR here: ' + webpackConfig.output.publicPath);

  app.use(require('webpack-dev-middleware')(compiler, {
    noInfo: true,
    publicPath: webpackConfig.output.publicPath
  }));

  app.use(require('webpack-hot-middleware')(compiler));

现在,这是一个奇怪的部分。Babel/Webpack在生产模式下编译了所有内容,没有热重载器也没有问题。当我们把节点ENV设置为'PRODUCTION'时,应用程序运行得非常好-没有syntheticEvent错误。
此外,该应用程序在dev模式下正常运行(带有热重新加载),使用先前的堆栈,其中包括以下NPM版本:
"react": "^0.14.8",
"react-dom": "^0.14.3",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.0",

"webpack": "^1.13.1",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.0.0"

"babel": "^6.5.2",
"babel-cli": "^6.10.1",
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-plugin-transform-es2015-modules-commonjs": "^6.0.2",
"babel-plugin-transform-react-constant-elements": "^6.0.2",
"babel-preset-es2015": "^6.0.8",
"babel-preset-react": "^6.0.2",

更新 5/16/17:

我们已经将问题隔离到从 React / React DOM 0.14.8 迁移到 v15.0.0。这样做会立即引发错误,但仅在HMR/Dev模式下。

生产版本,没有HMR,在编译时可以正常工作;通过该配置引用Webpack生成的缩小文件可以让应用程序100%正常运行。

与Dev模式中的HMR一起,完全相同的构建使用React / DOM 0.14.8可以完美运行,升级仅限于Webpack / HMR / webpack-hot-middleware至最新版本不会触发错误。

我花了一些时间研究调试面板,并找到了以下信息:

Clickeventobject 这是由React本地生成的实际事件对象的一个不错的快照。 在这种情况下,“topClick”与我们创建的任何处理程序都没有关联。 我可以通过单击页面上的任何位置来触发此操作和错误。

Where the error happens 这是实际发生错误的行。它来自react-dom/lib/SyntheticUIEvent.js -似乎未能在SyntheticEvent类上初始化.call方法.... enter image description here

值得注意的是,每次重新加载时,控制台还会首先触发以下错误

GET http://localhost:3333/[object%20Object]?url=function%20SyntheticEvent(dispa…d%20%3D%20emptyFunction.thatReturnsFalse%3B%0A%20%20return%20this%3B%0A%7D 404 (Not Found)
(anonymous) @ jspdf.debug.js:17350
l @ jspdf.min.js:284
u @ jspdf.min.js:284
XHR @ jspdf.debug.js:17334
Proxy @ jspdf.debug.js:16928
(anonymous) @ SyntheticEvent.js:188
(anonymous) @ SyntheticEvent.js:268
(anonymous) @ background.js:805
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ SyntheticCompositionEvent.js:13
(anonymous) @ background.js:2110
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ BeforeInputEventPlugin.js:16
(anonymous) @ background.js:1767
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ ReactDefaultInjection.js:14
(anonymous) @ background.js:1963
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ ReactDOM.js:16
(anonymous) @ ReactDOM.js:111
(anonymous) @ background.js:1844
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ index.js:3
(anonymous) @ background.js:812
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ background.js:9
(anonymous) @ background.js:3178
__webpack_require__ @ background.js:658
fn @ background.js:86
(anonymous) @ background:2
(anonymous) @ background.js:3287
__webpack_require__ @ background.js:658
(anonymous) @ background.js:707
(anonymous) @ background.js:710

从 Node 控制台中看到相同的错误:

GET /[object%20Object]?url=function%20SyntheticEvent(dispatchConfig%2C%20targetInst%2C%20nativeEvent%2C%20nativeEventTarget)%20%7B%0A%20%20if%20(process.env.NODE_ENV%20!%3D%3D%20%27production%27)%20%7B%0A%20%20%20%20%2F%2F%20these%20have%20a%20getter%2Fsetter%20for%20warnings%0A%20%20%20%20delete%20this.nativeEvent%3B%0A%20%20%20%20delete%20this.preventDefault%3B%0A%20%20%20%20delete%20this.stopPropagation%3B%0A%20%20%7D%0A%0A%20%20this.dispatchConfig%20%3D%20dispatchConfig%3B%0A%20%20this._targetInst%20%3D%20targetInst%3B%0A%20%20this.nativeEvent%20%3D%20nativeEvent%3B%0A%0A%20%20var%20Interface%20%3D%20this.constructor.Interface%3B%0A%20%20for%20(var%20propName%20in%20Interface)%20%7B%0A%20%20%20%20if%20(!Interface.hasOwnProperty(propName))%20%7B%0A%20%20%20%20%20%20continue%3B%0A%20%20%20%20%7D%0A%20%20%20%20if%20(process.env.NODE_ENV%20!%3D%3D%20%27production%27)%20%7B%0A%20%20%20%20%20%20delete%20this%5BpropName%5D%3B%20%2F%2F%20this%20has%20a%20getter%2Fsetter%20for%20warnings%0A%20%20%20%20%7D%0A%20%20%20%20var%20normalize%20%3D%20Interface%5BpropName%5D%3B%0A%20%20%20%20if%20(normalize)%20%7B%0A%20%20%20%20%20%20this%5BpropName%5D%20%3D%20normalize(nativeEvent)%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20if%20(propName%20%3D%3D%3D%20%27target%27)%20%7B%0A%20%20%20%20%20%20%20%20this.target%20%3D%20nativeEventTarget%3B%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20this%5BpropName%5D%20%3D%20nativeEvent%5BpropName%5D%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20var%20defaultPrevented%20%3D%20nativeEvent.defaultPrevented%20!%3D%20null%20%3F%20nativeEvent.defaultPrevented%20%3A%20nativeEvent.returnValue%20%3D%3D%3D%20false%3B%0A%20%20if%20(defaultPrevented)%20%7B%0A%20%20%20%20this.isDefaultPrevented%20%3D%20emptyFunction.thatReturnsTrue%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20this.isDefaultPrevented%20%3D%20emptyFunction.thatReturnsFalse%3B%0A%20%20%7D%0A%20%20this.isPropagationStopped%20%3D%20emptyFunction.thatReturnsFalse%3B%0A%20%20return%20this%3B%0A%7D 404 4.745 ms - 35162

更新: 进一步挖掘后,似乎升级到React v15+才是导致问题的原因 - 但我完全不确定为什么。v14.8运行良好,并且似乎没有发生任何关于通过Webpack 2 / webpack-hot-middleware实现HMR的更改。这是我们在React中的热重载处理程序: if (module.hot) { module.hot.accept(); } - Zfalen
你能分享一下出现错误的代码吗?你在哪里使用事件对象?你是否尝试在某种异步操作中使用事件对象? - Dayan Moreno Leon
我不认为这仅仅是由React升级引起的。该错误基本上意味着一个点击事件对象被传递给了一个期望它具有“call”方法的函数。您必须显示引发异常的代码以及package.json的所有更改。 - Anthony Kong
谢谢大家的回复!我真的很想给你们看一下导致问题的代码,但我们实在不知道它在哪里。我们没有手动使用任何事件对象,只是基本的处理程序函数。简单明了。我们知道的是,我们已经将问题隔离到从React / DOM 14.8移动到15.0 - 这样做会立即触发错误,并且仅在HMR / dev模式下出现。没有特定的组件会触发错误,在着陆页面上任何地方单击都会触发它... 我不明白为什么生产构建可以编译而不触发相同的错误。 - Zfalen
更新了原帖以反映最新信息。 - Zfalen
更新:今天我进行了一些开发环境的维护,执行了brew doctorbrew uninstall --force nodebrew install nodebrew link node --overwritebrew prune - 清理了所有内容。我还将依赖管理切换到了yarn并重新构建了node_modules。仍然没有运气,出现了相同的错误。我会在原帖中更新系统信息。 - Zfalen
1个回答

2
更新于5/24/17:

我们终于找到了问题 - 一个经典的错误!

在重新调整我们的整个技术栈以更符合create-react-app的标准后,我将我们之前的React应用程序迁移到了开发服务器索引文件中。虽然没有正确的HTML包装和样式等,但工作正常。

然而,当我将完整的HTML页面迁移到我们呈现应用程序的<div id="root>元素时,它又开始输出SyntheticEvent错误了!经过大量的工作和重构,最终将问题隔离到HTML文件中(实际上,这原本是一个EJS文件,主要包含基本骨架和SEO跟踪)。

问题在于:我们有一个过时的<script/>标签,它在调用jsPDF v1.2.61https://github.com/MrRio/jsPDF)。我们实际上不再使用此插件,而且由于合并冲突,该脚本似乎已经悄悄地回到了我们的代码中。

回顾起来,OP中发布的代码确实引用了jsPDF插件,但堆栈跟踪并没有真正提供任何关于错误源的指示。由于自从应用程序开始以来我们就没有碰过这个插件,并且采用了另一种方法,所以名称并没有引起任何警觉 - 鉴于后来对React脚本的调用,我简单地假设堆栈跟踪的前三行或者更多行指示jspdf是React库的某个晦涩部分。

此问题有两种解决方案:

  1. 完全删除脚本 - 这就是我们所做的,因为我们不再在应用程序中使用jsPDF。
  2. 更新jsPDF - 插件现在已经升级到v1.3.4。之前的版本v1.2.61React v15.0.0+原生库脚本产生了破坏性冲突。新版本不会产生冲突。

希望这能帮助未来的某些人!

仅供参考;之前未起作用并提示我们进行了上述修复的解决方案:

为了推进我们的项目,我们选择了使用create-react-appcustom-react-scripts的替代技术栈。

https://github.com/facebookincubator/create-react-app

https://github.com/kitze/custom-react-scripts

最终,我们(宽泛地)遵循此模式同时运行CRA Stack和我们的Node / Express内容:

https://www.fullstackreact.com/articles/using-create-react-app-with-a-server/

这最终实现了我们将新技术堆栈推向最新技术的目标。而且,与以前运行的内容相比,这可能要干净一些。

但是,我仍然完全不知道以上错误的起源。我已经在其他测试堆栈中移动了一些东西,并且似乎无法复制具有Webpack 2React 15+的问题 - 并且从原始堆栈设置它们的方式没有本质差异。

无论发生了什么,都非常奇怪。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接