webpack删除自定义变量或事件监听器附加到生产中的'窗口' ?



问题:

我们正面临一个问题,我们附加到window的任何事件侦听器或全局变量似乎不在我们的production构建中(但它们存在于development构建中)。

  • Webpack config: https://gist.github.com/saadq/9f2f800c88716d11410e63859382f47d
  • 构建脚本:webpack --mode=production

上下文:

我们有一个用例,我们的web应用在父应用中渲染。父应用基本上需要告诉我们什么时候需要渲染我们的应用。为了做到这一点,我们尝试使用事件监听器和全局函数。

我们的应用是如何加载到父应用中的

要在父应用中呈现我们的web应用,需要做以下事情:

  1. 父应用向myappwebsite.com/asset-manifest.json发起HTTP调用。这就像为任何create-react-appweb应用程序创建的默认asset-manifest.json
  2. 父应用程序从这个资产清单中找到主bundle.js的路径,然后使用这个路径(例如myappwebsite.com/bundle.js)进行HTTP调用来获取我们的bundle.js
  3. 他们动态地注入script标签到他们的head,并将src设置为我们的bundle.js,以加载我们应用程序捆绑的javascript。
  4. 在尝试调用任何代码或调度任何事件之前,它们会侦听这个新的script元素的onload事件。

尝试1

儿童应用:

// index.tsx
window.addEventListener('renderApp', (event) => {
console.log('This is running!'); // This only prints in `development`
const { rootId } = event.detail;
ReactDOM.render(<App />, document.getElementById(rootId));
})

父应用程序:

// index.tsx
console.log('Dispatch is running!'); // This prints in both `development` and `production`
const renderEvent = new CustomEvent('renderApp', { detail: rootId: 'root' });
// This runs in the script.onload function to wait for our app to load
window.dispatchEvent(renderEvent);

此代码在development构建中工作,但在production构建中不起作用。在production中,调度确实执行了,但由于某种原因,事件侦听器没有执行。当我们试图在缩小的生产包上设置一些断点时,我们注意到addEventListener代码在那里,但它实际上并没有执行……这很奇怪,因为addEventListener在子应用中的index.tsx的顶层,并且不是有条件添加的。


尝试2

儿童应用:

// index.tsx
window.renderApp = (rootId) => {
console.log('Child render is running'); // This only prints in `development`
ReactDOM.render(<App />, document.getElementById(rootId));
})

父应用程序:

// index.tsx
console.log('Render is running!'); // This prints in both `development` and `production`
// This runs in the script.onload function to wait for our app to load
window.renderApp(rootId);

这里同样的问题,代码在development构建中工作,但在production构建中不工作。在production中,调用通过,但全局函数似乎不在window上。我可以通过在控制台中打印出window来验证这一点。


似乎我在window上设置的任何全局变量或我设置到它的任何事件侦听器在生产构建中都会被忽略。这是Webpack的设计吗?或者你认为我的配置/构建脚本搞砸了导致这种情况发生吗?

问题最终变成了一个问题,我们的bundle的输出被分成main.jsvendor.js,但我们只将main.js加载到父应用程序中。

在配置中添加一个带有global: true的节点条目:

node: {
global: true,
__filename: false,
__dirname: false,
},

Webpack的行为确实有点奇怪,当它涉及到windows对象,我们可以找到一些关于这个问题的讨论。

根据这个答案,在webpack配置文件的output部分添加globalObject: 'this'行可能会解决这个问题。

其他引用https://github.com/webpack/webpack/issues/7112https://github.com/markdalgleish/static-site-generator-webpack-plugin/issues/130

最新更新