使用 p5.js 在 NextJS 中刷新页面时出现 404
404 on page refresh in NextJS with p5.js
我正在使用 react-p5
库在我的 about
页面中生成 PerlinNoise 波浪动画。
当我在任何页面上使用 p5
时,它 returns 一个 404 页面,但是如果单击返回主页并使用 link 打开 about.js
它将起作用。刷新后就不行了
如果我从文件中删除 p5
组件,一切正常。我认为问题出在 p5
或 p5 import
.
about.js
import React from 'react'
// Importing Sketch
import Sketch from 'react-p5'
export default function about() {
// Setup for creating canvas
const setup = (p5, canvasParentRef) => {
p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef)
}
let inc = 0.005;
let start = 0;
// Function to draw the wave
const draw = p5 => {
p5.background('rgba(255,255,255)')
p5.stroke('rgb(0,0,0)');
p5.noFill();
p5.beginShape();
let xoff = start;
for (let x = 0; x < p5.width; x++) {
p5.stroke('#000');
let y = p5.noise(xoff) * p5.height;
p5.vertex(x, y);
xoff += inc;
}
p5.endShape();
start += inc;
}
return (
<>
// Returning Sketch Component
<Sketch setup={setup} draw={draw} />
</>
)
}
项目结构:
问题是 Sketch 组件想要访问 window
属性,但是 window 未定义,因为我们服务于服务器端呈现的关于页面。
如何解决这个问题?
最好的解决方案是创建一个单独的组件,我们可以称之为 DrawSketch
DrawSketch 组件与您的“关于”页面几乎相同,只是它是一个组件。
import React from "react";
import Sketch from "react-p5";
export default function DrawSketch() {
const setup = (p5, canvasParentRef) => {
p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef);
};
let inc = 0.005;
let start = 0;
// Function to draw the wave
const draw = (p5) => {
p5.background("rgba(255,255,255)");
p5.stroke("rgb(0,0,0)");
p5.noFill();
p5.beginShape();
let xoff = start;
for (let x = 0; x < p5.width; x++) {
p5.stroke("#000");
let y = p5.noise(xoff) * p5.height;
p5.vertex(x, y);
xoff += inc;
}
p5.endShape();
start += inc;
};
return <Sketch setup={setup} draw={draw} />;
}
接下来我们要做的是确保我们的客户端服务器是我们的 DrawSketch 组件,因此它可以访问 window
属性.
在 next.js 中您可以使用动态导入
Next.js supports ES2020 dynamic import() for JavaScript. With it you can import JavaScript modules dynamically and work with them. They also work with SSR.
下一步将导入我们在您的关于视图中创建的 DrawSketch 组件,并将其声明为动态组件,即 not server side rendered
。
import React from "react";
import dynamic from "next/dynamic";
const ClientSideSketch = dynamic(() => import("../components/DrawSketch"), {
ssr: false
});
export default function AboutPage() {
return (
<>
<ClientSideSketch />
</>
);
}
我已经编辑了 codesandbox,所以你可以看到实际的例子。
我正在使用 react-p5
库在我的 about
页面中生成 PerlinNoise 波浪动画。
当我在任何页面上使用 p5
时,它 returns 一个 404 页面,但是如果单击返回主页并使用 link 打开 about.js
它将起作用。刷新后就不行了
如果我从文件中删除 p5
组件,一切正常。我认为问题出在 p5
或 p5 import
.
about.js
import React from 'react'
// Importing Sketch
import Sketch from 'react-p5'
export default function about() {
// Setup for creating canvas
const setup = (p5, canvasParentRef) => {
p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef)
}
let inc = 0.005;
let start = 0;
// Function to draw the wave
const draw = p5 => {
p5.background('rgba(255,255,255)')
p5.stroke('rgb(0,0,0)');
p5.noFill();
p5.beginShape();
let xoff = start;
for (let x = 0; x < p5.width; x++) {
p5.stroke('#000');
let y = p5.noise(xoff) * p5.height;
p5.vertex(x, y);
xoff += inc;
}
p5.endShape();
start += inc;
}
return (
<>
// Returning Sketch Component
<Sketch setup={setup} draw={draw} />
</>
)
}
项目结构:
问题是 Sketch 组件想要访问 window
属性,但是 window 未定义,因为我们服务于服务器端呈现的关于页面。
如何解决这个问题?
最好的解决方案是创建一个单独的组件,我们可以称之为 DrawSketch
DrawSketch 组件与您的“关于”页面几乎相同,只是它是一个组件。
import React from "react";
import Sketch from "react-p5";
export default function DrawSketch() {
const setup = (p5, canvasParentRef) => {
p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef);
};
let inc = 0.005;
let start = 0;
// Function to draw the wave
const draw = (p5) => {
p5.background("rgba(255,255,255)");
p5.stroke("rgb(0,0,0)");
p5.noFill();
p5.beginShape();
let xoff = start;
for (let x = 0; x < p5.width; x++) {
p5.stroke("#000");
let y = p5.noise(xoff) * p5.height;
p5.vertex(x, y);
xoff += inc;
}
p5.endShape();
start += inc;
};
return <Sketch setup={setup} draw={draw} />;
}
接下来我们要做的是确保我们的客户端服务器是我们的 DrawSketch 组件,因此它可以访问 window
属性.
在 next.js 中您可以使用动态导入
Next.js supports ES2020 dynamic import() for JavaScript. With it you can import JavaScript modules dynamically and work with them. They also work with SSR.
下一步将导入我们在您的关于视图中创建的 DrawSketch 组件,并将其声明为动态组件,即 not server side rendered
。
import React from "react";
import dynamic from "next/dynamic";
const ClientSideSketch = dynamic(() => import("../components/DrawSketch"), {
ssr: false
});
export default function AboutPage() {
return (
<>
<ClientSideSketch />
</>
);
}
我已经编辑了 codesandbox,所以你可以看到实际的例子。