React JS 服务器端问题 - 找不到窗口

IT技术 javascript reactjs webpack server-side-rendering draftjs
2021-04-18 09:32:42

嗨,我正在尝试在我的 reactJS 项目中使用 react-rte。我有服务器端渲染,每次我想使用这个包时,我都会得到:

return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
                               ^
ReferenceError: window is not defined

我想问题可能出在同构工具上,但我不知道如何将导入包推迟到已经定义窗口的客户端。

6个回答

这是一个可以为您处理窗口、文档和全局对象的 npm 库:Global

然后你可以安全地写:

import window from 'global'

const mySpecialWindowFunction = () => {
    return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};
我必须在哪里添加这个?
2021-06-19 09:32:42

如果您在进行服务器端渲染,那么全局窗口对象很有可能是未定义的,因为这只是客户端会理解的内容。

注意:最初,当你启动你的项目时,它会渲染出一个完整的 DOM 字符串(此时它不会知道,window因为它是服务器端,但是然后用你的客户端代码重新渲染窗口对象将可用!

在这种情况下,我正在使用一种解决方法。这是我的 webpack 插件:

new webpack.DefinePlugin({
  'process.env.NODE_ENV': isDevelopment ? '"development"' : '"production"',
  'process.env.BROWSER': JSON.stringify(true),
  __DEV__: isDevelopment
}),

所以我利用process.env.BROWSER我的优势,因为它将被定义为undefined好像是服务器端,true如果客户端完成渲染,它将被定义

由于当服务器端没有窗口对象时一切都停止工作,我们可以添加以下内容:

const mySpecialWindowFunction = () => {

  /* START HACK */
  if (!process.env.BROWSER) {
    global.window = {}; // Temporarily define window for server-side
  }
  /* END HACK */

  return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
};

这样,您的控制台就不会对您大喊大叫,也不会停止服务器端渲染,您现在可以继续美好的一天!虽然我不得不承认这有点Hacky,但它完成了工作,因为我们想要做的就是让服务器端渲染出初始 DOM 字符串,然后让客户端接管。

另请注意:不要担心将窗口设置为空对象,一旦客户端完成渲染,它就会恢复正常。

请添加使用“mySpecialWindowFunction”的详细信息
2021-06-01 09:32:42
有人可以回答@Spacemoose 的问题吗?
2021-06-02 09:32:42
我到底会在哪里添加“mySpecialWindowFunction”?
2021-06-05 09:32:42
除了 Spacemoose 的评论之外,还可以更新答案以指定第一个片段module.exports = { plugins[ ] }位于 webpack 配置中区域
2021-06-15 09:32:42

对于任何试图弄清楚为什么他们的 SSR 失败的人,即使他们正在检查 window 对象是否未定义。

您需要检查窗口引用是否存在,而不是它的值是否为空!

  if (typeof window === 'undefined') console.log('Window is not there')

您的window && if (window)检查失败,因为在 JavaScript 中未声明和“未定义”是不同的东西。

const a = undefined;
if (a) console.log('a');  // logs nothing, since 'a' is undefined
if (b) console.log('b');  // ReferenceError: b is not defined

原始问题的答案是,无论何时访问需要“窗口”的对象,您都需要将它们设置为有条件的:

return (typeof window === 'undefined') ?
   'node' :
   /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());

我一直在使用 ReactJS.NET 目标构建到客户端和服务器,并遇到了同样的问题。

解决方法是设置output.globalObject'this'

module.exports = {
  // ...
  output: {
    // ...
    globalObject: 'this'
  }
};

如果没有设置该选项,它将退回到window仅处理客户端代码。

在进行服务器端渲染时,全局 like window,document将是未定义的。如果你想以同构的方式来做,你必须测试渲染组件时的环境。

https://github.com/DavidWells/isomorphic-react-example

github上可以找到很多示例代码,上面的链接就是其中之一,希望对您有所帮助。