使用 React 和 Vite 进行初始页面加载需要很长时间

Ali*_*eir 6 reactjs postcss tailwind-css vite

Vite 实际上几乎立即运行:

维特

但是,当我尝试访问该网址时,我会加载一个空白页面一段时间,之后,每次我尝试第一次加载页面时,都会发生类似的等待时间,除了已经加载的组件之外,例如导航栏和标题,不需要重新渲染:

图像

这是我的package.json

{
    "name": "myapp",
    "version": "6.1.0",
    "author": "redacted",
    "homepage": "redacted",
    "private": true,
    "scripts": {
        "dev": "vite --port 3000",
        "build": "tsc && vite build",
        "preview": "vite preview",
        "lint": "eslint . --ext .ts,.tsx"
    },
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ]
    },
    "dependencies": {
        "@auth0/auth0-spa-js": "2.0.3",
        "@aws-amplify/auth": "5.1.8",
        "@emotion/cache": "11.10.5",
        "@emotion/react": "^11.10.5",
        "@emotion/server": "11.10.0",
        "@emotion/styled": "^11.10.5",
        "@fullcalendar/core": "6.1.4",
        "@fullcalendar/daygrid": "6.1.4",
        "@fullcalendar/interaction": "6.1.4",
        "@fullcalendar/list": "6.1.4",
        "@fullcalendar/react": "6.1.4",
        "@fullcalendar/timegrid": "6.1.4",
        "@fullcalendar/timeline": "6.1.4",
        "@loadable/component": "^5.15.3",
        "@mui/icons-material": "5.11.9",
        "@mui/lab": "5.0.0-alpha.120",
        "@mui/material": "^5.11.9",
        "@mui/system": "5.11.9",
        "@mui/x-date-pickers": "5.0.18",
        "@react-pdf/renderer": "3.1.4",
        "@reduxjs/toolkit": "1.8.5",
        "@syncfusion/ej2": "^20.4.54",
        "@syncfusion/ej2-react-grids": "^20.4.54",
        "@untitled-ui/icons-react": "0.1.0",
        "apexcharts": "3.37.0",
        "aws-amplify": "5.0.14",
        "axios": "^1.3.4",
        "date-fns": "2.29.3",
        "draft-js": "0.11.7",
        "firebase": "9.17.1",
        "formik": "2.2.9",
        "framer-motion": "^10.6.0",
        "fuse": "^0.4.0",
        "fuse.js": "^6.6.2",
        "gray-matter": "4.0.3",
        "i18next": "22.4.9",
        "lodash.debounce": "4.0.8",
        "lodash.isequal": "4.5.0",
        "mapbox-gl": "2.12.1",
        "mui-one-time-password-input": "1.0.4",
        "nprogress": "0.2.0",
        "numeral": "2.0.6",
        "prop-types": "15.8.1",
        "react": "18.2.0",
        "react-apexcharts": "1.4.0",
        "react-beautiful-dnd": "13.1.1",
        "react-dom": "18.2.0",
        "react-draft-wysiwyg": "1.15.0",
        "react-dropzone": "14.2.3",
        "react-helmet-async": "1.3.0",
        "react-hot-toast": "2.4.0",
        "react-i18next": "12.1.5",
        "react-map-gl": "7.0.21",
        "react-markdown": "8.0.5",
        "react-quill": "2.0.0",
        "react-redux": "8.0.5",
        "react-router": "6.8.1",
        "react-router-dom": "6.8.1",
        "react-slick": "0.29.0",
        "react-syntax-highlighter": "15.5.0",
        "redux": "4.2.1",
        "redux-devtools-extension": "2.13.9",
        "redux-thunk": "2.4.2",
        "simplebar-react": "3.2.1",
        "styled-components": "^5.3.9",
        "stylis": "4.1.3",
        "stylis-plugin-rtl": "2.0.2",
        "yup": "1.0.0"
    },
    "devDependencies": {
        "@svgr/webpack": "6.5.1",
        "@types/lodash": "4.14.191",
        "@types/node": "18.13.0",
        "@types/nprogress": "0.2.0",
        "@types/numeral": "2.0.2",
        "@types/react": "18.0.28",
        "@types/react-beautiful-dnd": "13.1.3",
        "@types/react-dom": "18.0.11",
        "@types/react-draft-wysiwyg": "1.13.4",
        "@types/react-redux": "7.1.25",
        "@types/react-slick": "0.23.10",
        "@types/styled-components": "^5.1.26",
        "@typescript-eslint/eslint-plugin": "^5.54.0",
        "@vitejs/plugin-react": "^3.1.0",
        "autoprefixer": "^10.4.13",
        "eslint": "8.34.0",
        "eslint-config-prettier": "^8.6.0",
        "eslint-import-resolver-typescript": "^3.5.3",
        "eslint-plugin-import": "^2.27.5",
        "eslint-plugin-jsx-a11y": "^6.7.1",
        "eslint-plugin-prettier": "^4.2.1",
        "eslint-plugin-react": "^7.32.2",
        "eslint-plugin-react-hooks": "^4.6.0",
        "postcss": "^8.4.21",
        "postcss-cli": "^10.1.0",
        "prettier": "2.8.4",
        "tailwindcss": "^3.2.7",
        "typescript": "4.9.5",
        "vite": "^4.1.4",
        "vite-plugin-eslint": "^1.8.1",
        "vite-plugin-svgr": "^2.4.0",
        "vite-tsconfig-paths": "^4.0.5"
    }
}

Run Code Online (Sandbox Code Playgroud)

我的vite.config.ts

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsconfigPaths from 'vite-tsconfig-paths';
import svgrPlugin from 'vite-plugin-svgr';
import eslint from 'vite-plugin-eslint';

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react(),
        eslint({
            emitWarning: true,
            emitError: true,
            failOnError: true,
        }),
        viteTsconfigPaths(),
        svgrPlugin(),
    ],
});
Run Code Online (Sandbox Code Playgroud)

如果有帮助的话,我还将 Tailwind 与标准配置文件一起使用。

这是由 Chrome 生成的 HAR 的经过编辑的要点。

这极大地减慢了开发速度。该项目还不够大,不足以保证如此缓慢的进度。

Jis*_*ikh 3

根据有限的信息,问题似乎与应用程序的初始加载时间有关,而不是 Vite。

\n

我们知道的应用程序行为是,初始页面加载时间很长,进一步重新加载也需要很长时间来加载需要重新渲染的主页面组件。不需要重新渲染的组件不是问题(例如,标题/导航栏)。

\n

一个想法:只需在初始页面加载时加载英雄部分/主要组件,其他组件则延迟加载。

\n

不过,这里有一些想法:

\n
    \n
  1. 探索性能基准:确定主要问题是什么的唯一方法是对其进行分析、基准测试。继续:链接。它将为您提供有关如何优化它们的答案。

    \n

    例如,此外,在本地,Lighthouse (Chrome DevTools) 具有针对您的具体问题的出色功能,以及有关如何缓解这些问题的资源。初始页面加载、第一次内容绘制、总阻塞时间、关键渲染路径、图像优化、最佳实践、SEO、渐进式 Web 应用程序等。这是我的一个网站的示例基准(有关更多详细信息,\'不过这只是一个博客网站):

    \n

    在此输入图像描述

    \n
  2. \n
  3. 动态导入模块/代码分割:基于package.json,我们可以看到有很多第三方依赖项,例如Auth、Firebase、Date等,我们不需要在初始页面加载时加载这些依赖项。好消息是,Vite 支持按需导入模块(见下面的示例)。

    \n
    import(\'./myModule\').then((module) => {\n  // Use the module here\n});\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. 依赖项预捆绑(由Vite提供):它对包的依赖项进行预捆绑以优化 dev/prod 构建。运行时vite dev,它会在第一次加载时执行此操作以优化后续重新加载。您可能会在您的开发经验中发出此问题,我想说,如果它不影响您的产品应用程序,请不要担心。

    \n
    \n

    某些软件包将其 ES 模块构建为许多单独的文件\n相互导入。例如,lodash-es 有超过 600 个内部模块!当我们从“lodash-es”导入 { debounce } 时,浏览器会同时发出 600 多个 HTTP 请求!尽管服务器\n处理它们没有问题,但大量请求\n会在浏览器端造成\n网络拥塞,导致页面加载\n明显变慢。

    \n

    通过将 lodash-es 预先捆绑到单个模块中,我们现在只需要一个\nHTTP 请求!

    \n

    注意:依赖项预捆绑仅适用于开发模式,并且\使用 esbuild 将依赖项转换为 ESM。在生产版本中,\n使用@rollup/plugin-commonjs。

    \n
    \n
  6. \n
  7. 延迟加载:这是一种缩短关键渲染路径长度的方法,我们的目标就是这样做。延迟加载在屏幕上不立即可见的组件(例如,不适合浏览器窗口大小的所有其他组件,例如,仅英雄组件+标题/导航栏,或仅一行图表/图形)。

    \n

    您可以使用React.lazy()延迟加载组件。如果您的应用程序是动态且高度交互的(+巨大的第3方依赖),例如仪表板(我们在图像上看到,您的应用程序就是),建议在不可见组件上大量使用它。我想说的是添加react-suspense到所有其他组件,这样最终用户就不会看到直接的空白屏幕。请参阅lazy() 的示例:

    \n
     const MyComponent = React.lazy(() => import(\'./MyComponent\'));\n
    Run Code Online (Sandbox Code Playgroud)\n

    JS 生态系统为大多数应用程序资产提供了延迟加载策略:

    \n
      \n
    1. 代码分割。
    2. \n
    3. 脚本类型模块。
    4. \n
    5. CSS 优化:在这里我们可以看到您正在使用 Tailwind 以及 JS(x) \xe2\x80\x93情感.js 中的样式组件/CSS。我们可以考虑优化CSS文件。
    6. \n
    7. <link rel="preload">使用CSS属性预加载 Web 字体资源font-display
    8. \n
    \n
  8. \n
  9. 使第 3 方(例如 CDN)请求异步:这是一个非常有争议的问题,并且取决于用例,但如果优化得当,您可以优化页面加载时间。

    \n
  10. \n
  11. 向客户端推送更少的资产 (JavaScript):这是非常明显的表达方式,但我们可以根据具体情况思考和探索这一点。UglifyJS像or\n这样的工具Terser可以缩小和压缩您的代码。通过第三方工具优化静态\nassets(图像、CSS、JS)并将其推送到\n私有/公共 CDN。尽可能多地缓存,使用\n指纹让浏览器识别新的 JS/CS 更改。

    \n

    现在,开箱即用的 React 支持服务器组件(就像重型 Web 框架一样),我想说的是,要执行繁重的计算任务,然后将渲染的内容推送到服务器上

    \n

    HTML 到客户端。示例:构建第 3 方图表,这需要您从 API 获取数据,对其进行序列化/反序列化,然后将其渲染/重新渲染到组件上。

    \n

    此外,您还可以探索O(1) frameworks主张解决微小/关键问题的方法,例如向客户端推送更少的 JS 代码(例如HTMXAstro)。

    \n
  12. \n
\n