nextjs 提供了 getServerSideProps 方法(之前叫 getInitialProps 方法),用于在渲染页面之前请求数据,但 nextjs 框架为了能够前后端保持同步,会将请求到的数据,通过一个 script 标签传给前端: 但有时候,我们并不想把一些原始数据暴露到前端页面中,如一些博客网站、新闻网站等,基本以展示数据为主,没有同构的需要。所以,如何隐藏掉 在 nextjs 的 GitHub 上,有一个 pull request: Allow disabling runtime JS in production for certain pages (experimental) #11949,讨论了这个功能。 从nextjs@9.4.0版本开始,为 pages 目录中的组件提供了一个 注意该设置只在 不过,它带来的副作用也很大,它会导致整个页面实现的前端功能(如点击事件等)全部失效,包括该组件引用的子组件。 最终渲染出来的 html 结构: 从上图中可以看到, 若真的想在前端加载 js,也是有办法的。那就是使用 script 标签,自己加载 js 链接或者内容。 假如我们把要加载的前端 js 放在了 都是同一个项目的代码,单独把某一部分拿出去再构建,实在是不方便。这里可以把 js 代码转成字符串,写到 script 标签中。 使用 script 标签的 dangerouslySetInnerHTML 属性: 方法名调用 toString()会该方法的函数体,这里我们封装成一个立即执行函数的形式: 最终编译后的效果: 从上面的分析也能看到,不是特别必要的时候,最好还是不要用<script id="__NEXT_DATA__" type="application/json">script>
__NEXT_DATA__
中的数据,只展示构建好的 html 呢?1. 使用方式 #
unstable_runtimeJS
的配置,当设置该参数为 false 后,则不会再展示__next_data__中的数据。process.env.NODE_ENV==='production'
时生效。// pages/home.tsx
const Home = ({ nick, age }) => {
const handleClick = () => {
console.log('home click');
};
return (
<div>
<h1 onClick={handleClick}>homeh1>
<p>{nick}p>
<p>{age}p>
div>
);
};
// 移除__next_data__,移除所有前端的js
export const config = {
unstable_runtimeJS: false,
};
// https://www.nextjs.cn/docs/basic-features/pages#%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B8%B2%E6%9F%93
export const getServerSideProps = async (context: any) => {
const { nick, age } = await fetch('api');
return { props: { nick, age } };
};
2. 副作用 #
unstable_runtimeJS
副作用很少很大的,虽不再展示 getServerSideProps 方法中返回的数据,但整个页面所有的 script 标签也都没了。这就造成该组件和它所有的子组件,均没有了前端功能。3. 解决方案 #
3.1 外链的方式 #
https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.js
链接中,直接通过 script 标签的 src 引入即可:const Home = ({ nick, age }) => {
return (
<div>
<h1 onClick={handleClick}>homeh1>
<p>{nick}p>
<p>{age}p>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.js">script>
div>
);
};
3.2 内敛的方式 #
3.2.1 dangerouslySetInnerHTML 属性 #
3.2.2 script 标签的内容区 #
3.2.3 利用 function 的 toString() #
const Home = ({ nick, age }: any) => {
// 所有前端要执行的js,放在这里面
const bootstrap = () => {
if (typeof document === 'undefined') {
return;
}
document.querySelector('h1')?.addEventListener('click', () => console.log(Date.now()));
};
return (
<div>
<h1 onClick={handleClick}>homeh1>
<p>{nick}p>
<p>{age}p>
<script dangerouslySetInnerHTML={{ __html: `(${bootstrap.toString()})()` }}>script>
div>
);
};
4. 总结 #
unstable_runtimeJS
禁用 js,否则为了实现相同的功能,就要用很多的奇技淫巧来弥补。
版权属于:
加速器之家
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
评论