如何将dom-操纵脚本包含到SSR Next.js App中
How to include dom-manipulating scripts into SSR Next.js App
我遇到以下错误:
Warning: Text content did not match. Server: "But I want to be altered by the client" Client: "Test"
in div (at pages/index.tsx:17)
in div (at pages/index.tsx:6)
in HomePage (at _app.tsx:5)
in MyApp
in Container (created by AppContainer)
in AppContainer
...具有以下设置:
一个 NextJS 应用程序组件:
function HomePage() {
return (
<>
<div id="test-div">I am rendered on the server.</div>
<script src="http://localhost:8080/bundle.js"></script>
</>
);
}
export default HomePage;
(注意:URL http://localhost:8080/bundle.js
假定 webpack-dev-server 是 运行 并提供该资源)
包含的 "example" 脚本:
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
在一个简单的设置中,我将只有一个静态 html 文件,声明一个 div 元素并包含 "example" 脚本。
但我想使用 NextJS,因为我想将动态 (SSR) 内容呈现到页面中(例如来自 cms 的文本内容)。
我注意到,有时(如果脚本执行需要更多时间)没有错误。只是在示例脚本中做一些耗时的事情。
另一种 hacky 方法是在示例脚本中使用 setTimeout
。
在我知道为什么会这样之前,我不想这样做:
setTimeout(function() {
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
}, 20);
Next.js 11.0.0 及以上
您可以使用Next.js Script component加载第三方脚本。
// pages/index.js
import Script from 'next/script'
function Home() {
return (
<>
<Script src="https://www.google-analytics.com/analytics.js" />
</>
)
}
使用 next/script
,您可以定义 strategy
属性 并且 Next.js 将优化脚本的加载。
之前 Next.js 11.0.0
浏览器和 document
、window
对象在服务器端呈现期间不可用。
您可以在 React 组件挂载后初始化操作 DOM 的脚本。
useEffect(() => init(), [])
要添加外部脚本,您可以执行以下操作:
useEffect(() => require('../babylon.js'), [])
要包含来自其他服务器的脚本,您可以添加 script
标签:
useEffect(() => {
const script = document.createElement("script");
script.src = "http://localhost:8080/bundle.js";
script.async = true;
document.body.appendChild(script);
},[])
如果您要添加 DOM 个侦听器,您还需要进行清理。
您也可以使用动态导入
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
我遇到以下错误:
Warning: Text content did not match. Server: "But I want to be altered by the client" Client: "Test"
in div (at pages/index.tsx:17)
in div (at pages/index.tsx:6)
in HomePage (at _app.tsx:5)
in MyApp
in Container (created by AppContainer)
in AppContainer
...具有以下设置:
一个 NextJS 应用程序组件:
function HomePage() {
return (
<>
<div id="test-div">I am rendered on the server.</div>
<script src="http://localhost:8080/bundle.js"></script>
</>
);
}
export default HomePage;
(注意:URL http://localhost:8080/bundle.js
假定 webpack-dev-server 是 运行 并提供该资源)
包含的 "example" 脚本:
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
在一个简单的设置中,我将只有一个静态 html 文件,声明一个 div 元素并包含 "example" 脚本。
但我想使用 NextJS,因为我想将动态 (SSR) 内容呈现到页面中(例如来自 cms 的文本内容)。
我注意到,有时(如果脚本执行需要更多时间)没有错误。只是在示例脚本中做一些耗时的事情。
另一种 hacky 方法是在示例脚本中使用 setTimeout
。
在我知道为什么会这样之前,我不想这样做:
setTimeout(function() {
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
}, 20);
Next.js 11.0.0 及以上
您可以使用Next.js Script component加载第三方脚本。
// pages/index.js
import Script from 'next/script'
function Home() {
return (
<>
<Script src="https://www.google-analytics.com/analytics.js" />
</>
)
}
使用 next/script
,您可以定义 strategy
属性 并且 Next.js 将优化脚本的加载。
之前 Next.js 11.0.0
浏览器和 document
、window
对象在服务器端呈现期间不可用。
您可以在 React 组件挂载后初始化操作 DOM 的脚本。
useEffect(() => init(), [])
要添加外部脚本,您可以执行以下操作:
useEffect(() => require('../babylon.js'), [])
要包含来自其他服务器的脚本,您可以添加 script
标签:
useEffect(() => {
const script = document.createElement("script");
script.src = "http://localhost:8080/bundle.js";
script.async = true;
document.body.appendChild(script);
},[])
如果您要添加 DOM 个侦听器,您还需要进行清理。
您也可以使用动态导入
https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr