Next JS : 在 dom 渲染时加载屏幕

Posted

技术标签:

【中文标题】Next JS : 在 dom 渲染时加载屏幕【英文标题】:Next JS : Loading Screen While the dom is rendeing 【发布时间】:2021-09-08 02:29:21 【问题描述】:

如何显示我自己的加载程序而不是空白的白屏? 例如,Tweeter 在页面加载时显示徽标,对于 Facebook、google AdSense 等也是如此。 看这个动图,我想在 Next Js 里有这样的东西。

我猜这与 _document.js 有关。 react js 有一个类似的问题(在 index.html 中渲染加载器) 但我不知道如何在下一个 js 中做到这一点。

【问题讨论】:

那可能不是使用 next.js,而是一个 SPA。除此之外,为什么不设置背景图片? 在这些情况下,DOM 渲染通常不是您所等待的。它非常快。通常减慢速度的实际上是获取 JS 本身或从您的服务器获取数据以填充 UI。 @evolutionxbox 你能解释一下使用背景图片的解决方案吗? 【参考方案1】:

无需安装任何库

import  useRouter  from "next/router";
import  useState, useEffect  from "react";

function MyApp() 
  const router = useRouter();
  const [loading, setLoading] = useState(false);

  useEffect(() => 
    router.events.on("routeChangeError", (e) => setLoading(false));
    router.events.on("routeChangeStart", (e) => setLoading(false));
    router.events.on("routeChangeComplete", (e) => setLoading(true));

    return () => 
      router.events.off("routeChangeError", (e) => setLoading(false));
      router.events.off("routeChangeStart", (e) => setLoading(false));
      router.events.off("routeChangeComplete", (e) => setLoading(true));
    ;
  , [router.events]);

  return <>loading ? "loading..." : <AppComponent /></>;

【讨论】:

【参考方案2】:

试试这个逻辑。创建一个状态变量并使用 NextJs 路由器事件。使用路由器事件来控制状态变量,最后使用状态变量来控制加载屏幕和其他 DOM 元素的渲染。

   function MyApp()
     const [loading, setLoading] = React.useState<boolean>(false);

     Router.events.on('routeChangeStart', (url) => 
       setLoading(true);
      );

     Router.events.on('routeChangeComplete', (url) => 
       setLoading(false);
     );
    

    return(
      <>
        loading ? (
            <PageLoader />
          ) : (
            <AppLayout>
              <Component ...pageProps />
            </AppLayout>
          )
    </>
  )

【讨论】:

【参考方案3】:

你不能。您看到的是 twitch 加载程序向您显示的自定义启动画面。它所做的是将加载过程分成两部分。第一个是标准的——浏览器请求并接收您提供的用于呈现页面的 html 和脚本文件。您无法使用传统的 Web 应用程序绕过此阶段,但是,您可以做些什么来改善用户体验,即尽量减少该时间。一个很好的例子是 index.html 包含内联 css 和 javascript 动画启动屏幕,一旦加载启动实际应用程序。这样,真正的数据交换是在浏览器呈现页面后完成的。这需要您在规划应用程序时做大量工作,但使用现代框架和工具,实现它肯定有更短和更脏的路径。但是,如果您有 SPA,这几乎是您可以去的唯一方法。

附带说明,如果您想加快网站的加载速度(这就是为什么无论如何都需要启动画面的原因),只需运行一些分析,检查优化。服务器端缓存通常会为您提供最佳的投资回报率,但它不会帮助您处理较重的负载(大图像或大量小图像)。 html 的分段是第二好的选择。然后你应该看看导入的库和东西,这些往往会增加一点。最后还有一些选项可以在服务器上压缩数据以限制数据负载。

【讨论】:

【参考方案4】:

通常这些是通过一个覆盖所有内容并默认显示的 div 来完成的,您在该 div 中放置的内容取决于您(gif、svg 等)。一旦 window.onload 被调用,只需隐藏 div,它将显示完全渲染的 dom。

这是一个基本示例(我在移动设备上,请原谅我的格式) CSS:

.loadingsScreen
        position:absolute;
        left:0;
        top:0;
        width:100%;
        height:100%;
        background-color: #whatever-color;
        z-index: 10;  /*just make sure it's the highest on the page*/

JS:

window.onload = function()
        $("#loadingScreen").fadeOut(); //just make it hide the overlaying div, I used jQuery in this example but there are many ways to do this
;

【讨论】:

【参考方案5】:

实际上这不是 Next.js 提供的“从盒子里”提供的东西,你必须自己实现这些东西,你可以使用一些全局状态(redux/context)来确定你的应用程序是否正在加载某些东西,并渲染loader 基于这个状态。

【讨论】:

【参考方案6】:

您可以使用nprogress。它适用于您的所有路线更改过程。

import React from 'react';
import Router from 'next/router';
import App,  Container  from 'next/app';
import NProgress from 'nprogress';

NProgress.configure( showSpinner: publicRuntimeConfig.NProgressShowSpinner );

Router.onRouteChangeStart = () => 
  // console.log('onRouteChangeStart triggered');
  NProgress.start();
;

Router.onRouteChangeComplete = () => 
  // console.log('onRouteChangeComplete triggered');
  NProgress.done();
;

Router.onRouteChangeError = () => 
  // console.log('onRouteChangeError triggered');
  NProgress.done();
;

export default class MyApp extends App  ... 

您还需要包含一个样式文件。如果将 css 文件放在静态目录中,则可以按如下方式访问样式: 它适用于您所有更改的路线。

<link rel="stylesheet" type="text/css" href="/static/css/nprogress.css" />

【讨论】:

这与更改路线无关。我问当我刷新页面时,我想在下一个 js (react) 创建 dom 时显示一个加载器

以上是关于Next JS : 在 dom 渲染时加载屏幕的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Next.js 中实现加载屏幕

Next.js 在下一页的 getInitialProps 完成加载时保持当前页面处于活动状态并重新渲染

在渲染到屏幕之前对内存中的视频加载做出反应

虚拟滚动技术 --- 解决加载大量列表DOM导致页面卡顿

浏览器渲染 理解终结篇

chrome浏览器渲染引擎及JS引擎