Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >改变渲染顺序实现按需加载,主要可以从以下几个方面入手:

改变渲染顺序实现按需加载,主要可以从以下几个方面入手:

原创
作者头像
用户1232103
修改于 2024-12-15 23:41:26
修改于 2024-12-15 23:41:26
1000
举报

当你访问http://localhost:3000/app/list/testpage时,Next.js 的处理顺序是:

代码语言:ts
AI代码解释
复制
1. 首先加载 /pages/_app.tsx(这是应用的入口文件,所有页面都会通过它包装)
   ↓
2. 加载 Layout 组件(如果有全局布局的话)
   ↓
3. 最后才加载 /pages/app/list/testpage.tsx

虽然你的 testpage.tsx看起来很简单:

但实际上它被_app.tsx包装了。让我们看看_app.tsx:

然后,应用的渲染顺序是:

代码语言:ts
AI代码解释
复制
App (_app.tsx)
  ↓
QueryClientContext
  ↓
I18nContextProvider (初始化i18n)
  ↓
ChakraUIContext
  ↓
Layout (这里调用了setUserDefaultLng)TestPage (你的测试页面)
代码语言:ts
AI代码解释
复制
Next.js 的渲染流程和相关文件如下:

入口点:
pages/_document.tsx:自定义 HTML 文档结构
pages/_app.tsx:应用的根组件,所有页面都会通过这里
next.config.js:Next.js 的配置文件,控制构建和运行时行为
页面加载顺序:
_document.tsx (如果存在)
  ↓
_app.tsx
  ↓
pages/_test/testpage.tsx
涉及的 JS 文件及其作用:
polyfills.js: 浏览器兼容性支持,来自 Next.js 核心
webpack.js: Webpack 运行时,由 Next.js 注入
main.js: Next.js 的主运行时
_app.js: 来自你的 _app.tsx 文件
testpage.js: 你的测试页面
_buildManifest.js: Next.js 的构建清单
_ssgManifest.js: 静态生成的清单

代码语言:ts
AI代码解释
复制
访问 http://localhost:3000/_test/testpage 的渲染流程:

入口文件:
/app/src/pages/_document.tsx - 基础 HTML 结构
/app/src/pages/_app.tsx - 应用入口
/app/src/pages/_test/testpage.tsx - 页面组件
构建输出:
.next/static/chunks/pages/_app.js - 客户端 app 代码
.next/server/pages/_app.js - 服务器端 app 代码
.next/server/pages/_document.js - 服务器端文档代码

所以虽然你的测试页面很简单,但它被包裹在了多层组件中:

  • _app.tsx 提供了基础框架
  • Layout 组件提供了布局
  • 各种 Context 提供了全局状态和功能

i18n 相关的错误出现是因为:

  • _app.tsx 中初始化了 i18n
  • Layout 组件尝试使用 i18n 功能
  • 但 i18n 可能没有正确初始化完成就被使用了

这就是为什么即使你的测试页面很简单,也会遇到i18n 相关的错误。因为整个应用都被包装在了这些功能组件中。

按需加载:

修改_app.tsx,移除全局包装,改为按需加载:

代码语言:ts
AI代码解释
复制
import type { AppProps } from 'next/app';
import dynamic from 'next/dynamic';

// 定义需要全局功能的路由
const needGlobalFeatures = ['/app', '/chat', '/login'];

// 动态导入全局组件
const GlobalWrapper = dynamic(() => import('@/components/GlobalWrapper'), {
  ssr: false
});

// 动态导入Layout
const Layout = dynamic(() => import('@/components/Layout'), {
  ssr: false
});

function App({ Component, pageProps, router }: AppProps) {
  // 判断当前路由是否需要全局功能
  const needsGlobal = needGlobalFeatures.some(path => 
    router.pathname.startsWith(path)
  );

  // 基础渲染
  const content = <Component {...pageProps} />;

  // 按需包装
  if (needsGlobal) {
    return (
      <GlobalWrapper>
        <Layout>{content}</Layout>
      </GlobalWrapper>
    );
  }

  // 简单页面直接返回
  return content;
}

export default App;

这部分我再详细一点:

代码语言:ts
AI代码解释
复制
// 动态导入示例
const Layout = dynamic(() => import('@/components/Layout'), {
  ssr: false  // 禁用服务端渲染
});

// 判断逻辑示例
function App({ Component, pageProps, router }: AppProps) {
  // 这里的判断逻辑需要您根据实际需求来写
  const needsLayout = router.pathname !== '/app/list/testpage';
  const needsI18n = router.pathname.startsWith('/app/');
  
  // 基础内容
  let content = <Component {...pageProps} />;
  
  // 按需包装组件
  if (needsLayout) {
    content = <Layout>{content}</Layout>;
  }
  
  if (needsI18n) {
    content = <I18nWrapper>{content}</I18nWrapper>;
  }
  
  return content;
}

具体的判断条件,我举个例子

代码语言:ts
AI代码解释
复制
// 例如:哪些页面需要什么功能
const featureRules = {
  layout: {
    include: ['/app', '/chat'],  // 需要布局的路径
    exclude: ['/app/list/testpage']  // 不需要布局的路径
  },
  i18n: {
    include: ['/app/list'],
    exclude: ['/app/list/testpage']
  }
};

判断函数

代码语言:ts
AI代码解释
复制
function needsFeature(pathname: string, feature: 'layout' | 'i18n') {
  const rules = featureRules[feature];
  
  // 如果在排除列表中,直接返回false
  if (rules.exclude.some(path => pathname.startsWith(path))) {
    return false;
  }
  
  // 检查是否在包含列表中
  return rules.include.some(path => pathname.startsWith(path));
}

动态加载逻辑

代码语言:ts
AI代码解释
复制
function App({ Component, pageProps, router }: AppProps) {
  // 使用您定义的判断逻辑
  const shouldLoadLayout = needsFeature(router.pathname, 'layout');
  const shouldLoadI18n = needsFeature(router.pathname, 'i18n');

  let content = <Component {...pageProps} />;

  // 根据判断结果动态加载
  if (shouldLoadLayout) {
    content = <Layout>{content}</Layout>;
  }

  if (shouldLoadI18n) {
    content = <I18nWrapper>{content}</I18nWrapper>;
  }

  return content;
}

这样,您可以:

1.自定义哪些路径需要哪些功能

2. 定义功能加载的优先级和顺序

  • 根据实际需求调整判断逻辑

这只是一个框架,具体的判断规则需要您根据项目需求来实现。

Completed(4 files changed)

创建一个轻量级的全局包装组件GlobalWrapper.tsx

代码语言:ts
AI代码解释
复制
import { ReactNode } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { appWithTranslation } from 'next-i18next';
import I18nContextProvider from '@/web/context/I18n';

interface Props {
  children: ReactNode;
}

function GlobalWrapper({ children }: Props) {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <I18nContextProvider>
        {children}
      </I18nContextProvider>
    </QueryClientProvider>
  );
}

export default appWithTranslation(GlobalWrapper);

在具体页面中按需导入功能:

代码语言:ts
AI代码解释
复制
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';

// 按需导入i18n
const I18nFeature = dynamic(() => import('@/components/features/I18n'), {
  ssr: false
});

export default function TestPage() {
  const [needsI18n, setNeedsI18n] = useState(false);

  useEffect(() => {
    // 根据实际需求决定是否加载i18n
    setNeedsI18n(true);
  }, []);

  return (
    <div>
      {needsI18n ? (
        <I18nFeature>
          <h1>Test Page with i18n</h1>
        </I18nFeature>
      ) : (
        <h1>Simple Test Page</h1>
      )}
    </div>
  );
}

使用路由配置来控制功能加载:

代码语言:ts
AI代码解释
复制
// routes.config.ts
export const routeConfig = {
  '/app/list/testpage': {
    needsI18n: false,
    needsLayout: false,
    needsAuth: false
  },
  '/app/list': {
    needsI18n: true,
    needsLayout: true,
    needsAuth: true
  }
  // ... 其他路由配置
};

创建自定义Hook 来管理功能加载:

代码语言:ts
AI代码解释
复制
// useFeatures.ts
import { useRouter } from 'next/router';
import { routeConfig } from './routes.config';

export function useFeatures() {
  const router = useRouter();
  const config = routeConfig[router.pathname] || {};

  return {
    needsI18n: config.needsI18n ?? false,
    needsLayout: config.needsLayout ?? false,
    needsAuth: config.needsAuth ?? false
  };
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Next.js与SSR:构建高性能服务器渲染应用
在Next.js中,每个.js或.jsx文件的组件都会被自动处理为SSR页面。例如,创建一个pages/index.js文件:
天涯学馆
2024/06/02
1970
React 应用架构实战 0x3:构建和配置页面
这一节,将学习 Next.js 中的路由工作原理以及可以使用的渲染方法,以充分利用 Next.js 的特性。然后,我们将学习如何配置每个页面的布局,使应用程序看起来和感觉像一个单页应用程序。
Cellinlab
2023/05/17
8340
React 应用架构实战 0x3:构建和配置页面
基于 Next.js 的 SSR/SSG 方案了解一下?
本文主要是讲讲如何使用 Next.js 框架实现服务端渲染,将有效提升网页的 SEO 和首屏渲染速度,说不定哪天就用上了,是吧!
小东同学
2022/07/29
5.6K0
基于 Next.js 的 SSR/SSG 方案了解一下?
手把手带你用next搭建一个完善的react服务端渲染项目(集成antd、redux、样式解决方案)
本文参考了慕课网jokcy老师的React16.8+Next.js+Koa2开发Github全栈项目,也算是做个笔记吧。
ssh_晨曦时梦见兮
2020/04/10
5.9K0
Next.js 简明教程
最近用Next.js + Editor.js 撸了一个博客系统。开发起来甚是畅滑,如果你喜欢React,又有同构的需求,不妨由此文入手。
小刀c
2022/09/21
3K0
Next.js 简明教程
React 必学SSR框架——next.js
F首先我们就回顾一下,我们到底是怎么告别了使用 php/jsp 做服务器端渲染,进入前后端分离的客户端渲染时代,又为什么重新回到了服务端渲染。
狂奔滴小马
2021/11/15
7.7K0
React 必学SSR框架——next.js
解读 React Router v7:新功能与性能优化详解
今日推荐 《掌控软件管理:详解 APT、YUM 和 DNF 的使用方法》这篇文章介绍了软件包管理器帮助我们轻松地安装、更新、卸载和管理系统中的软件包。APT、YUM 和 DNF 是当前最流行的包管理器,分别用于不同的 Linux 发行版。本文将深入解析它们的使用方法,并通过代码示例展示如何高效地管理软件包。
Front_Yue
2024/11/24
3.3K0
解读 React Router v7:新功能与性能优化详解
React服务端渲染-next.js
前台渲染-SPA应用是一个主要阵营,如果说有什么缺点,那就是SEO不好。因为默认的HTML文档只包含一个根节点,实质内容由JS渲染。并且,首屏渲染时间受JS大小和网络延迟的影响较大,因此,某些强SEO的项目,或者首屏渲染要求较高的项目,会采用服务端渲染SSR。
娜姐
2020/09/22
4K0
React服务端渲染-next.js
使用Next.js创建Blog
Next.js 已经成为 React 应用程序最重要的框架之一。它可以帮助开发人员在没有模板的情况下构建更好的服务器端渲染 React 应用程序。
用户6256742
2024/06/12
1770
使用Next.js创建Blog
如何使用 Nx、Next.js 和 TypeScript 构建 Monorepo
在本文中,我们将了解 monorepo 是什么,以及 monorepos 如何帮助以更好的开发体验更快地开发应用程序。我们将讨论使用Nx开发工具管理 monorepo 的优势,并学习如何使用这些工具构建Next.js应用程序。
玖柒的小窝
2021/09/13
6K0
如何使用 Nx、Next.js 和 TypeScript 构建 Monorepo
React 应用架构实战 0x6:实现用户认证和全局通知
目前,当涉及到管理控制台中的用户身份验证时,应用程序仍然依赖于测试数据。在本节中,我们将构建应用程序的身份验证系统,允许用户认证并访问受保护的资源在管理控制台中。我们还将创建一个 toast 通知系统,以便在发生我们希望通知用户的操作时向他们提供反馈。
Cellinlab
2023/05/17
1.6K0
React 应用架构实战 0x6:实现用户认证和全局通知
实现基于最新chrome的动态按需加载组件
chrome63 版本后支持动态import 加载js https://developers.google.com/web/updates/2017/12/nic63#dynamic
mafeifan
2018/09/10
8520
SSR服务器端渲染(Next.js总结和豆瓣电影项目)「建议收藏」
先解释一下Nuxt.js和Next.js虽然只有一个字母之差,但它们是不同的两个服务端渲染框架.
全栈程序员站长
2022/11/15
2.2K0
Nextjs任意组件数据加载
Nextjs是React生态中非常受欢迎的SSR(server side render——服务端渲染)框架,只需要几个步骤就可以搭建一个支持SSR的工程(_Nextjs_的快速搭建见Next.js入门)。 本文的案例代码来自于前端标准模板项目。
随风溜达的向日葵
2019/03/12
5.1K0
Nextjs任意组件数据加载
React第三方组件1(路由管理之Router的使用④按需加载-上)
本教程总共6篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1、React第三方组件1(路由管理之Router的使用①简单使用)---2018.01.22 2、React第三方组件1(路由管理之Router的使用②多层级跳转及重定向)---2018.01.23 3、React第三方组件1(路由管理之Router的使用③传参)---2018.01.24 4、React第三方组件1(路由管理之Router的使用④按需加载-上)---2018.01.25 5、React第
前端人人
2018/04/11
1.7K0
React第三方组件1(路由管理之Router的使用④按需加载-上)
动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)
大家好,在《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(上)》一篇文章里,我们一起了解了什么是 Next.js,并手工创建了一个简单的 Next.js 项目,学会了如何基于模板创建简单的页面,本篇文章,我们继续完善这个案例。
前端达人
2021/04/11
1.8K0
动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)
使用 React 和 ethers.js 构建DApp
scaffold-eth[2] 因为引入内容太多了,对于我来说太复杂了, 不知道大家有没有同感,找到一篇使用 React 开发 DApp 的非常简单入门教程。翻译一下.
Tiny熊
2022/11/07
5.5K0
使用 React 和 ethers.js 构建DApp
Next.js 有哪些主要功能?
Next.js 是由 Vercel 开发的一款开源 React 框架,以其丰富的高级功能和对应用性能的优化备受开发者青睐。
前端小智@大迁世界
2025/02/06
1430
React实战:使用Vite+TS+Antd构建React项目
由于我之前学过React框架,但是由于工作中没有使用它,所以我最近开始使用了Vite、TypeScript、React Router,Redux,Axios,Ant Design和SpringBoot等流行技术来搭建了一个博客项目来巩固我的学习成果。这个项目包括了博客文章列表、文章详情、标签分类、搜索功能等常用功能。通过这个项目,我将分享如何使用Vite、TypeScript、React Router和Ant Design来搭建一个博客项目,并不断分享我所遇到的问题,以及如何解决它。希望我的实战可以帮助您更好地了解React生态系统,并且能够帮助您更加高效地开发React应用程序。
Front_Yue
2024/01/03
3K0
React实战:使用Vite+TS+Antd构建React项目
Next.js 入门
当使用 React 开发系统的时候,常常需要配置很多繁琐的参数,如 Webpack 配置、Router 配置和服务器配置等。如果需要做 SEO,要考虑的事情就更多了,怎么让服务端渲染和客户端渲染保持一致是一件很麻烦的事情,需要引入很多第三方库。针对这些问题,Next.js提供了一个很好的解决方案,使开发人员可以将精力放在业务上,从繁琐的配置中解放出来。下面我们一起来看看它的一些特性。
Dickensl
2022/06/14
6.6K0
Next.js 入门
相关推荐
Next.js与SSR:构建高性能服务器渲染应用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文