【问题标题】:Why is the typeof window check needed in Nextjs Image component为什么 Nextjs Image 组件中需要 typeof 窗口检查
【发布时间】:2021-12-06 18:33:22
【问题描述】:

所以我制作了一个占位符图像/svg 以使用Nextjs image component,我从他们的回购中复制了这个code。 我对后端开发(主要是前端)不是很有经验,所以我不得不对缓冲区、流、window.bto 等进行研究。 我无法完全理解的是为什么需要typeof window === "undefined" 以及随后的代码行。如果我删除它,它也可以工作。

我可以理解这是一个边缘案例,例如“假设”。但我无法理解为什么需要。它总是会呈现给浏览器。为什么要检查窗口是否未定义?

提前致谢,抱歉英语不好,这不是我的主要语言。

Nextjs 代码

const shimmer = (w, h) => `
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="g">
      <stop stop-color="#333" offset="20%" />
      <stop stop-color="#222" offset="50%" />
      <stop stop-color="#333" offset="70%" />
    </linearGradient>
  </defs>
  <rect width="${w}" height="${h}" fill="#333" />
  <rect id="r" width="${w}" height="${h}" fill="url(#g)" />
  <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite"  />
</svg>`

const toBase64 = (str) =>
  typeof window === 'undefined'
    ? Buffer.from(str).toString('base64')
    : window.btoa(str)

const Shimmer = () => (
  <div>
    <ViewSource pathname="pages/shimmer.js" />
    <h1>Image Component With Shimmer Data URL</h1>
    <Image
      alt="Mountains"
      src="/mountains.jpg"
      placeholder="blur"
      blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
      width={700}
      height={475}
    />
  </div>

我在组件上的实现

 <Image
 src={props.src}
 layout={props.layout}
 width={props.width}
 height={props.height}
 placeholder="blur"
 blurDataURL={`data:image/svg+xml;base64,${toBase64(shimmer(300, 300))}`}
 />

【问题讨论】:

  • 第一次在服务器上执行代码,其中未定义浏览器窗口对象。因此它用于确保您在浏览器中运行该代码。

标签: javascript reactjs next.js nextjs-image


【解决方案1】:

Next.js 是一个 React 框架,可帮助开发人员在 react 中管理服务器端渲染。

服务器端呈现有很多好处,包括:缓存特定页面(或仅缓存公开内容,并保留用户特定数据或需要在前端加载的身份验证数据)。

由于 Next.js 进行服务器端渲染,这意味着有时他们会在 Node.js 中使用 reactDOMServer.renderToString() 函数。他们将整个页面构建为 HTML,并将其发送给正在浏览该站点的用户。 Next.js 生成页面 HTML 的目的是最大化 CDN 的功能并改善页面的 SEO。所以他们不仅将 React 页面呈现为 HTML。他们发出 API 请求,await 让他们返回,允许他们呈现 API 响应的元素列表。

这可以让开发人员利用 React 的动态方面并在渲染代码中运行 JavaScript 函数(例如:{products.length &lt;= 0 &amp;&amp; &lt;EmptyStateDiv type='products' /&gt;}),但遗憾的是您不能使用存在于客户端/用户浏览器上的 JavaScript/功能(而不是原生 JavaScript/跨平台 Node.js/Browser)。

因此,尽管 JS 中内置的所有功能(如数组原型方法)都可以不假思索地使用。诸如 fetch 之类的其他功能可以在 Node.js 和 Frontend/React 上跨平台使用,但仅限于像 isomorphic-fetch 这样的跨平台库。最后,其他功能只存在于浏览器中,不是 JavaScript 原生的。这尤其包括可从特定用户的浏览器访问的方法/属性,就像这样做可能很棒:document.innerWidth is &gt; 1600 但这是不可能的,因为此函数在特定客户端呈现页面之前运行。 Next.js 在服务器端构建页面,其中未定义 document/window 之类的内容,并且它们存在没有意义。 (尽管您可以通过阅读一些客户端的标头来优化和缓存移动和桌面用户的不同体验。)

虽然它在 Node.js 中的服务器上运行(服务器端渲染),但 Node.js 运行时中未定义窗口,它可能在渲染前崩溃。在服务器上定义窗口也是没有意义的,因为窗口通常包含浏览器特定的属性,如 clientHeight/clientWidth 或允许用户使用 window.location.assign 进行客户端重定向,这在服务器上是不可能的。

【讨论】:

  • 谢谢,我明白为什么现在需要了。
【解决方案2】:

如果此代码作为pre-rendering 的一部分在服务器上运行(服务器端渲染或静态渲染),则不会有window(因此对于base64 编码也没有window.btoa),因为有没有浏览器,但是可以使用node.js的Buffer

【讨论】:

  • 是的,我明白这是因为 Nextjs 的 ssr 部分。但我认为,那总是会在浏览器中呈现。你的意思是,当 nextjs 做的预加载和东西时,它会在 ssr 上运行?不需要 serverSideProps 和其他东西来做到这一点吗?抱歉再次询问,我试图承认这一点。感谢您的回答。
  • 如果在服务器上不是浏览器,就是node.js
猜你喜欢
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多