为什么 Nextjs Image 组件需要检查 typeof window

Why is the typeof window check needed in Nextjs Image component

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

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

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

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))}`}
 />

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

Next.js 是 React 的框架,可帮助开发人员管理 Server-Side 在 React 中呈现。

server-side 呈现有很多好处,包括:缓存特定页面(或仅缓存 public 的内容并保留 user-specific 数据或 auth-required 数据待加载在前端)。

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

这可以让开发人员在渲染代码中利用 React 的动态方面和 运行 JavaScript 功能(例如:{products.length <= 0 && <EmptyStateDiv type='products' />}),但遗憾的是您不能使用JavaScript/functionality 存在于客户端's/user 的浏览器中(相对于 JavaScript/cross-platform Node.js/Browser 的本地浏览器)。

因此,尽管 JS 中内置的所有功能(如数组原型方法)都可以毫不犹豫地使用。可以在 Node.js 和 Frontend/React 上使用 cross-platform 等其他功能,但仅由于 cross-platform 库,如 isomorphic-fetch。最后,其他功能仅存在于浏览器中,并非 JavaScript 的原生功能。这尤其包括 methods/properties 可以从特定用户的浏览器访问,就像这样做可能很棒:document.innerWidth is > 1600 但这是不可能的,因为此功能 运行s 在特定客户端呈现页面之前. Next.js 在服务器端构建页面,其中 document/window 之类的内容未定义,它们存在也没有意义。 (虽然您可以通过阅读一些客户的 headers,为移动用户和桌面用户优化和缓存不同的体验。)

虽然它 运行 在 Node.js 中的服务器上(Server-Side 呈现) window 未在 Node.js 运行 中定义时间,它可能会在渲染之前崩溃。在服务器上定义 window 也没有意义,因为 window 通常包含浏览器特定的属性,如 clientHeight/clientWidth 或允许用户使用 [=17= 进行客户端重定向] 这在服务器上是不可能的。