Next.js v13(稳定,无 ./app 文件夹)在 Ubuntu WSL 中与 Node v18 一起运行。
根据 de docs ,Crypto API 自 Node v14~ish 起就已存在。
这确实已经在我的环境中的 Node 中进行了测试: 我还打印了整个对象,它看起来就像文档所说的那样。
想象一下这个简单的组件:
import crypto from 'crypto';
export default function Crypto() {
console.log(crypto);
return (
<p>
{crypto.randomUUID()}
</p>
);
}
Next.js 表示“在 397 毫秒内成功编译了客户端和服务器”。但在 UUID 在浏览器中渲染几毫秒后,Next.js 会抛出一些与 randomUUID 不是函数有关的错误。
我发现 Webpack 有点混杂在那里;没试过Turbopack。这超出了这个问题的范围。
注释掉段落中的方法调用后,console.log(crypto) 像往常一样在开发工具中运行并打印两次,如下所示:
注意一个来自“react devetools backend”,另一个来自 webkpack。这让我相信错误会在服务器端抛出,因为 console.loglog 在 UUID 方法之前被调用。
服务器端,尽管浏览器中抛出错误,Next CLI 仍会打印该对象,并且它包含方法:
客户端,在打印的对象中,找不到 randomUUID() 方法: 这确认了错误消息。我的代码无法访问该方法。此外,与 Node 文档相比,还缺少一些方法。
然而,如果直接来自 devTools
console.log(crypto)
,它的原型中确实有该方法:
此外,由于结构的原因,我倾向于相信正在打印的加密对象在某种程度上来自 Node,因为 Chrome V8 加密对象的结构完全不同。但到底为什么这些方法不见了呢?
我尝试在服务器端、客户端和中间使用 console.loging 对象。不知何故,该方法在中间丢失了。 Webpack 可能是罪魁祸首。最糟糕的是,尽管只是一眨眼的功夫,我就可以在抛出错误之前看到渲染的字符串;忽略错误卡会引发空白正文。字符串消失。
编辑 导入/需要加密的原因是它可以在 Node.js 中运行。接下来是SSR框架;简而言之,它首先在服务器上运行,尽可能地以 HTML 形式呈现并交付给客户端。如果未导入,当 Next 尝试调用 Crypto 服务器端时,Node 会抛出错误。
现在,我告诉这段代码仅在 Window 对象可用时运行(即我在浏览器中)并且它与本机 chromium V8 Crypto 对象一起运行。
// import crypto from 'crypto';
export default function Crypto() {
if (typeof window !== 'undefined') {
console.log('CLIENT: ', crypto.randomUUID());
return (
<p>
{crypto.randomUUID()}
</p>
);
}
return (
<h1>SERVER SIDE</h1>
);
}
唯一的缺点是,不知怎的,still在Next magic中运行了两次,一次是服务器端,一次是客户端,这意味着它不是React 18的bc。它准确地告诉我,是预期的UUID 函数总是返回不同的结果。
我在尝试创建一个可以在 NextJS 应用程序和非服务器端渲染的 Storybook 中使用的组件时遇到了同样的问题。 我最终在渲染中调用了这个 polyfill :
import * as cryptoServer from "crypto";
function getRandomUUID(){
if (typeof window === "undefined"){
return cryptoServer.randomBytes(16).toString('hex')
}
return crypto.randomUUID();
}
我没有收到来自 vite 的关于导入加密模块的投诉
浏览器不在安全上下文中运行时限制对某些加密 API 的访问(如此处定义)。
当页面最初加载时,将其设置为
useEffect
钩子中的状态,以便它持续存在,然后从状态渲染它。
const Crypto = () => {
const [randomUUID, setRandomUUID] = useState();
useEffect((
if (typeof window !== 'undefined' && !randomUUID) {
setRandomUUID(crypto.randomUUID());
}
),[]);
if(!randomUUID) <>No UUID</>;
return <>{randomUUID}</>
}
export default Crypto;
我在带有 NestJS 和 Next.js 的 monorepo 设置中使用名为 createUUID 的库。最近,将Next.js更新到v14.1后,遇到错误:crypto.randomUUID不是函数。 Next.js 中间件的运行时环境似乎已经改变。修改以下代码解决了该问题:
interface CryptoType {
randomUUID: () => string;
}
let cryptoUtil: CryptoType;
// for browser
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
cryptoUtil = crypto as unknown as CryptoType;
} else {
// https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation#importing-runtime-specific-code
// for next edge runtime
if (process.env.NEXT_RUNTIME === 'edge') {
cryptoUtil = crypto as unknown as CryptoType;
// for next nodejs runtime
} else if (process.env.NEXT_RUNTIME === 'nodejs') {
const nodeCrypto = require('crypto');
cryptoUtil = {
randomUUID: () => nodeCrypto.randomUUID(),
};
// for others (maybe server)
} else {
const nodeCrypto = require('crypto');
cryptoUtil = {
randomUUID: () => nodeCrypto.randomUUID(),
};
}
}
export function createUUID() {
return cryptoUtil.randomUUID().replace(/-/g, '');
}