【问题标题】:Installing Plaiceholder in Next.js / Webpack 5 causes: Module not found: Can't resolve 'child_process'在 Next.js / Webpack 5 中安装 Plaiceholder 导致:找不到模块:无法解析“child_process”
【发布时间】:2021-12-25 14:43:30
【问题描述】:

我正在 Next.js 应用程序上构建,当我安装/导入 Plaiceholder(用于生成占位符图像)时,我收到以下错误:Module not found: Can't resolve 'child_process'

  • 节点 v14.18.0
  • Next.js v11.1.2
  • 占位符 v2.2.0
  • 夏普 v0.29.2

我理解此错误消息意味着 webpack5 正在尝试捆绑客户端无法使用的节点包。但我不清楚它为什么这样做。我没有自定义任何 webpack 配置,并且在 Plaiceholder 文档中找不到任何提及此问题的内容。我该如何解决?

注意:我希望在构建期间创建 base64 数据 URL,以便在页面加载后立即可用(不在运行时异步获取)。

这是我的 next.config.js

module.exports = {
  reactStrictMode: true,
};

我的 package.json 只有 scriptsdependenciesdevDependencies(无需更改模块分辨率)

如果相关,这里有一个使用 Plaiceholder 的简化示例:

import Image from "next/image";
import { getPlaiceholder } from "plaiceholder";
import React, { useState } from "react";

...

const { base64 } = await getPlaiceholder(imgUrl);

...

return (<Image
            src={imgUrl}
            placeholder="blur"
            blurDataURL={base64}
          />);

【问题讨论】:

  • Plaiceholder 使用 Node.js API,不能在客户端代码中使用。您需要将其移至服务器(getStaticProps/getServerSideProps 或 API 路由)。

标签: javascript webpack next.js server-side-rendering


【解决方案1】:

似乎 plaiceholder 不适合客户端渲染。我相信该软件包适用于 Node.js 环境。这就是当您尝试在客户端呈现组件时出现此错误的原因。

要解决这个问题,您需要将import { getPlaiceholder } from 'plaiceholder' 移动到 NextJS API 部分。然后,您可以使用正文中的 URL 数据调用该 API。然后得到base64。

/api/getBase64.js

import { getPlaiceholder } from "plaiceholder";

export default async (req, res) => {
  const { body } = req;
  const { url } = body;

  const { base64 } = getPlaiceholder(url);

  res.status(200).send(base64);
};

/component.js

import Image from "next/image";
import React, { useState, useEffect } from "react";

const [base64, setBase64] = useState()

useEffect(() => {
  (async () => {
   const _base64 = await fetch.post('/api/getBase64', {url: imgUrl}); // wrote for demonstration
   setBase64(_base64);
  })()
})

return (<Image
            src={imgUrl}
            placeholder="blur"
            blurDataURL={base64}
          />);

我知道blurDataURL 在您获取数据之前是未定义的,但这是您可以使用plaiceholder 库管理图像的方式。它应该只为 NodeJS 环境导入。如果你不喜欢这种方法,你可以尝试寻找另一个同样适用于浏览器环境(客户端)的库

根据评论更新:

如果你想在构建时生成这个base64,你可以在使用这个Image组件的页面中使用getStaticProps。 NextJS 足够聪明,可以了解客户端或服务器端使用了哪些库。所以你可以这样做:

import { getPlaiceholder } from "plaiceholder";  // place it at the root of file. This will not be bundled inside of client-side code

export async function getStaticProps(context) {
  const { base64 } = await getPlaiceholder(imgUrl);

  return {
    props: { base64 }, // will be passed to the page component as props
  }
}

这样,通过使用getStaticProps,页面将在构建时创建。您可以在使用图像组件的页面内获取base64 道具并将该道具传递给blurDataURL。此外,您也可以将此方法与 getServerSideProps 一起使用。

这是来自 NextJS 网站:

注意:您可以在顶级范围内导入模块以用于 获取服务器端道具。 getServerSideProps 中使用的导入不会 为客户端捆绑。

https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering

【讨论】:

  • 谢谢!我绝对不想在客户端使用 Plaiceholder。我是 Next.js 的新手,所以我不清楚为什么我这样做的方式会导致这种情况发生。我希望在构建期间创建 base64 数据 URL,而不是在运行时异步。你对此有什么建议吗?
猜你喜欢
  • 2022-11-09
  • 1970-01-01
  • 2021-06-17
  • 2021-02-06
  • 2022-06-13
  • 2021-10-16
  • 2015-07-12
  • 2021-10-27
  • 2021-05-17
相关资源
最近更新 更多