惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
MyScale Blog
MyScale Blog
量子位
月光博客
月光博客
J
Java Code Geeks
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
U
Unit 42
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
G
Google Developers Blog
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
IT之家
IT之家
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
B
Blog
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
B
Blog RSS Feed

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客
nextjs 如何不显示next_data的数据-蚊子的前端博客
author · 2022-02-19 · via 蚊子的前端博客

nextjs 提供了 getServerSideProps 方法(之前叫 getInitialProps 方法),用于在渲染页面之前请求数据,但 nextjs 框架为了能够前后端保持同步,会将请求到的数据,通过一个 script 标签传给前端:

<script id="__NEXT_DATA__" type="application/json"></script>

但有时候,我们并不想把一些原始数据暴露到前端页面中,如一些博客网站、新闻网站等,基本以展示数据为主,没有同构的需要。所以,如何隐藏掉__NEXT_DATA__中的数据,只展示构建好的 html 呢?

1. 使用方式 #

在 nextjs 的 GitHub 上,有一个 pull request: Allow disabling runtime JS in production for certain pages (experimental) #11949,讨论了这个功能。

从nextjs@9.4.0版本开始,为 pages 目录中的组件提供了一个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}>home</h1>
      <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 } };
};

最终渲染出来的 html 结构:

remove-next-data-in-nextjs

2. 副作用 #

从上图中可以看到,unstable_runtimeJS副作用很少很大的,虽不再展示 getServerSideProps 方法中返回的数据,但整个页面所有的 script 标签也都没了。这就造成该组件和它所有的子组件,均没有了前端功能。

3. 解决方案 #

若真的想在前端加载 js,也是有办法的。那就是使用 script 标签,自己加载 js 链接或者内容。

3.1 外链的方式 #

假如我们把要加载的前端 js 放在了https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.js链接中,直接通过 script 标签的 src 引入即可:

const Home = ({ nick, age }) => {
  return (
    <div>
      <h1 onClick={handleClick}>home</h1>
      <p>{nick}</p>
      <p>{age}</p>
      <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.js"></script>
    </div>
  );
};

3.2 内敛的方式 #

都是同一个项目的代码,单独把某一部分拿出去再构建,实在是不方便。这里可以把 js 代码转成字符串,写到 script 标签中。

3.2.1 dangerouslySetInnerHTML 属性 #

使用 script 标签的 dangerouslySetInnerHTML 属性:

<script
  dangerouslySetInnerHTML={{
    __html: `document.querySelector('h1')?.addEventListener('click', () => console.log(Date.now()));`,
  }}
></script>

3.2.2 script 标签的内容区 #

<script>{`document.querySelector('h1')?.addEventListener('click', () => console.log(Date.now()));`}</script>

3.2.3 利用 function 的 toString() #

方法名调用 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}>home</h1>
      <p>{nick}</p>
      <p>{age}</p>
      <script dangerouslySetInnerHTML={{ __html: `(${bootstrap.toString()})()` }}></script>
    </div>
  );
};

最终编译后的效果:

function-tostring

4. 总结 #

从上面的分析也能看到,不是特别必要的时候,最好还是不要用unstable_runtimeJS禁用 js,否则为了实现相同的功能,就要用很多的奇技淫巧来弥补。