17、React应用的离线预缓存、性能优化与发布指南

React应用的离线预缓存、性能优化与发布指南

1. 离线预缓存(Precache: Work Offline)

渐进式Web应用(PWA)的核心功能之一是能够离线工作,我们可以使用 serviceWorker 来实现这一点。在使用Create React App(CRA)时, serviceWorker 包含在 index.tsx 文件中。

1.1 启用离线功能

默认情况下,CRA中的 serviceWorker 是未注册的,代码如下:

serviceWorker.unregister()

要启用离线功能,只需将 serviceWorker 的状态改为注册:

serviceWorker.register()

在生产环境构建时,我们可以在 index.tsx 组件中添加如下代码:

const rootElement = document.getElementById('root')
if (rootElement && rootElement!.hasChildNodes()) {
  hydrate(<AppRouter />, rootElement)
  serviceWorker.register()
} else {
  render(<AppRouter />, rootElement)
}
// serviceWorker.unregister()

再次构建项目( $ yarn build )后,会出现一个新文件: build/precache-manifest.[string].js

1.2 验证离线功能

要查看 serviceWorker 的工作情况,需要再次运行发布构建脚本:

$ yarn build:serve

打开Chrome开发者工具的Network标签,在Size列中可以看到显示为 ServiceWorker 。此时,关闭网络连接,或者在Chrome开发者工具的Network标签中勾选 Offline 复选框,刷新应用,应用仍然可以正常工作,就像在线一样。

1.3 离线工作原理

CRA的Workbox默认预缓存策略是 CacheFirst ,即静态资源首先从 service worker 缓存机制中获取,如果失败则发起网络请求。Workbox支持不同的策略,如 CacheOnly NetworkFirst 等,但如果要使用除默认策略之外的其他策略,可能需要将CRA项目弹出(eject)。更多关于此功能的信息可以查看:https://create-react-app.dev/docs/making-a-progressive-web-app/。

2. 使用useCallback记忆函数

在使用 useEffect 和自定义函数时,可能会出现无限循环的问题。例如:

useEffect(() => {
  draw()
})
const draw = () => {
  // TODO
}

useCallback() 可以帮助解决这个问题,它可以与 useEffect() 一起使用,防止函数的重新创建。示例代码如下:

useEffect(() => {
  memoizedDrawCallback()
}, [memoizedDrawCallback])
const memoizedDrawCallback = useCallback(() => {
  // TODO using data as dependency
}, [data])

通过将函数包装在 useCallback 中,并定义函数的依赖项,可以确保只有当依赖项发生变化时,函数才会重新创建。例如,可以在依赖项数组中列出所需的数据或属性:

[props.bottom, props.data, props.fill, props.height, props.left, props.right, props.top, props.width]

这样, memoizedDrawCallback 函数在每次渲染DOM周期更新时不会重新构建,从而避免了潜在的无限循环。

3. 选择启动项目

在开发React应用时,选择合适的启动项目非常重要。以下是一些需要考虑的因素:

3.1 开发阶段发布构建的原因

在开发阶段创建发布构建很重要,因为它能提供比使用已优化且准备好部署的库更真实的构建。在项目开发过程中,代码的更改可能很大,因此需要不断创建发布构建,而不是等到冲刺阶段结束的最后一刻才发现构建失败或无法按预期工作。建议快速且频繁地进行发布,甚至一天发布两次。

3.2 选择工具

在选择发布工具时,有许多付费和免费的解决方案可供选择,这可能会让人感到不知所措。以下是一些常见的选择:
| 类型 | 工具 | 说明 |
| ---- | ---- | ---- |
| 免费解决方案 | GitHub pages、Vercel、Firebase、Netlify、Heroku等 | 适用于概念验证(POC)或小型非商业项目 |
| 付费解决方案 | Amazon AWS(Lambda用于无服务器)、Azura(Azure Functions用于无服务器)、Alibaba cloud(Function Compute用于无服务器)等 | 传统的服务器解决方案或无服务器解决方案 |

需要注意的是,许多免费解决方案在扩展时通常会开始收费,因此需要仔细检查和考虑。同时,建议记录项目的设置过程,以避免被特定的解决方案束缚,因为价格和条款经常变化。

3.3 SPA vs. SSR

在决定使用React作为Web技术后,首先需要决定是将应用作为单页应用(SPA)还是使用服务器端渲染(SSR)。
- SPA :渲染在客户端进行,外部资源使用有限。
- SSR :应用能够在服务器上显示内容,而不是像单页应用那样在浏览器中渲染。

使用SSR的优点包括减轻用户机器负担和能够与后端Node.js共享代码,但缺点是会增加应用的复杂性,并且在服务器繁忙时会降低响应时间。如果已经在使用SPA或SSR,并且需要在两者之间进行转换,由于React组件的设计理念,只要组件构建正确,就可以通过移动组件来设置项目。

3.4 SPA和SSR启动项目

选择SSR或SPA后,需要选择启动库。以下是一些常见的启动项目:
- CRA :Facebook推荐的启动项目,基于SPA技术。将其转换为纯SSR应用是可能的,但需要弹出项目并自行管理配置。
- Next.js :最流行的基于SSR的React启动项目,被许多成功的公司使用,如Netflix、GitHub、Hulu和Uber。
- 其他启动库 :Gatsby(提供无服务器渲染)、React Boilerplate(专注于离线模式和可扩展性)、React Slingshot(使用一些有主见的库构建)、Razzle(基于SSR,无需配置)等。

此外,也可以从头开始创建项目,自行安装所需的库并管理配置,虽然这样需要更多的设置工作,但可以确保项目完全符合需求。

4. 创建和发布SSR应用(Next.js)

4.1 设置Next.js启动项目

使用以下命令创建一个简单的Next.js React项目,并使用D3库:

$ yarn create next-app

在终端提示输入项目名称时,可以选择自己喜欢的名称,例如 nextjs-ts-chart 。安装完成后,切换到项目目录:

$ cd nextjs-ts-chart

下载完库后,运行应用:

$ yarn run dev
$ open localhost:3000

4.2 安装TypeScript

Next.js默认使用JS,但建议为项目设置TypeScript以进行类型检查:

$ yarn add -D typescript @types/react @types/node

运行这些库后, tsconfig.json 文件会自动添加到项目中。

4.3 安装D3

安装D3的 select 模块:

$ yarn add d3-selection @types/d3-selection

4.4 创建Rectangle.tsx组件

在项目中创建一个 components 文件夹,并添加 Rectangle.tsx 组件:

// components/Rectangle/Rectangle.tsx
import React, { useEffect, RefObject } from 'react'
import { select } from 'd3-selection'

const Rectangle = () => {
  const ref: RefObject<HTMLDivElement> = React.createRef()
  useEffect(() => {
    draw()
  })
  const draw = () => {
    select(ref.current).append('p').text('Hello World')
    select('svg').append('g').attr('transform', 'translate(250, 0)').append('rect').attr('width', 500).attr('height', 500).attr('fill', 'tomato')
  }

  return (
    <div className="Rectangle" ref={ref}>
      <svg width="500" height="500">
        <g transform="translate(0, 0)">
          <rect width="500" height="500" fill="green" />
        </g>
      </svg>
    </div>
  )
}

export default Rectangle

4.5 更新index.ts

index.js 改为 index.ts ,并添加 Rectangle.tsx 组件,同时移除其他代码:

// src/component/pages/index.tsx
import Rectangle from "../components/Rectangle/Rectangle"
import styles from '../styles/Home.module.css'
import React from "react";

export default function Home() {
  return (
    <div className={styles.container}>
      <Rectangle />
    </div>
  )
}

4.6 使用Express发布Next.js应用

4.6.1 安装express库
$ yarn add -D express
4.6.2 创建server.js文件

创建一个Express服务器文件,允许传递端口或设置默认端口为9000,并允许传递 NODE_ENV 以告知应用是在开发还是生产环境中运行:

// server.js
const express = require('express')
const next = require('next')
const port = process.env.PORT || 9000;
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare()
  .then(() => {
    const server = express()
    server.get('*', (req, res) => {
      return handle(req, res)
    })
    server.listen(port, (err) => {
      if (err) throw err
      console.log(`Server Ready on http://localhost:${port}`)
    })
  })
  .catch((ex) => {
    console.error(ex.stack)
    process.exit(1)
  })
4.6.3 构建和部署应用

使用以下命令构建发布版本的应用:

$ yarn build

在本地部署应用时,需要在终端中设置环境变量:
- Windows

$ SET NODE_ENV=development
  • macOS/Linux
$ export NODE_ENV=development

通过以上步骤,我们可以实现React应用的离线预缓存、性能优化以及使用Next.js创建和发布SSR应用。这些技术可以帮助我们提高应用的性能和用户体验,同时根据不同的需求选择合适的启动项目和发布工具。

5. 选择发布工具的决策流程

为了更清晰地展示选择发布工具的决策过程,我们可以使用 mermaid 格式的流程图:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始选择发布工具]):::startend --> B{是否需要免费方案?}:::decision
    B -->|是| C{是否会大规模扩展?}:::decision
    C -->|否| D(选择GitHub pages、Vercel等):::process
    C -->|是| E(考虑付费方案):::process
    B -->|否| E
    E --> F{是否需要服务器?}:::decision
    F -->|是| G(选择传统服务器方案如Amazon AWS等):::process
    F -->|否| H(选择无服务器方案如Amazon Lambda等):::process

这个流程图展示了从开始选择发布工具到最终确定方案的决策过程。首先考虑是否需要免费方案,若需要则进一步考虑是否会大规模扩展;若不需要免费方案则直接考虑付费方案。在付费方案中,再根据是否需要服务器来选择传统服务器方案或无服务器方案。

6. 总结与最佳实践

6.1 性能优化总结

通过使用 serviceWorker 实现离线预缓存,我们可以让 React 应用在离线状态下正常工作,提高用户体验。同时,使用 useCallback 可以避免函数的不必要重新创建,防止潜在的无限循环,优化应用性能。以下是性能优化的关键步骤总结:
1. 启用离线预缓存
- 在 index.tsx 中注册 serviceWorker

serviceWorker.register()
- 构建项目:
$ yarn build
- 运行发布构建脚本:
$ yarn build:serve
  1. 使用 useCallback 记忆函数
useEffect(() => {
  memoizedDrawCallback()
}, [memoizedDrawCallback])
const memoizedDrawCallback = useCallback(() => {
  // TODO using data as dependency
}, [data])

6.2 项目选择与发布总结

在选择启动项目和发布工具时,需要综合考虑多个因素,如项目需求、团队经验、成本等。以下是项目选择与发布的关键要点总结:
| 项目类型 | 特点 | 适用场景 |
| ---- | ---- | ---- |
| SPA(单页应用) | 渲染在客户端,外部资源使用有限 | 对响应速度要求高,交互性强的应用 |
| SSR(服务器端渲染) | 在服务器上显示内容,可减轻用户机器负担 | 需要更好的 SEO,对服务器性能要求较高的应用 |

在选择启动项目时,可以根据项目需求选择 CRA、Next.js 等不同的启动库。在发布应用时,根据项目规模和预算选择免费或付费的发布工具。

6.3 最佳实践建议

  • 频繁发布 :在开发阶段频繁创建发布构建,及时发现和解决问题,避免在项目后期出现构建失败的情况。
  • 记录设置过程 :详细记录项目的设置过程,包括使用的库、配置信息等,以便在需要时进行修改和迁移。
  • 持续优化 :不断关注应用的性能指标,根据用户反馈和数据分析进行持续优化,提高应用的性能和用户体验。

通过遵循这些最佳实践,我们可以更高效地开发和发布 React 应用,为用户提供更好的服务。

总之,React 应用的开发和发布涉及多个方面的技术和决策。通过合理运用离线预缓存、性能优化技巧,选择合适的启动项目和发布工具,我们可以构建出高性能、用户体验良好的应用。同时,持续学习和实践,不断优化应用,才能跟上技术发展的步伐。

内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,涵盖正向逆向运动学求解、正向动力学控制,并采用拉格朗日-欧拉法推导逆向动力学方程,所有内容均通过Matlab代码实现。同时结合RRT路径规划B样条优化技术,提升机械臂运动轨迹的合理性平滑性。文中还涉及多种先进算法仿真技术的应用,如状态估计中的UKF、AUKF、EKF等滤波方法,以及PINN、INN、CNN-LSTM等神经网络模型在工程问题中的建模求解,展示了Matlab在机器人控制、智能算法系统仿真中的强大能力。; 适合人群:具备一定Ma六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)tlab编程基础,从事机器人控制、自动化、智能制造、人工智能等相关领域的科研人员及研究生;熟悉运动学、动力学建模或对神经网络在控制系统中应用感兴趣的工程技术人员。; 使用场景及目标:①实现六自由度机械臂的精确运动学动力学建模;②利用人工神经网络解决传统解析方法难以处理的非线性控制问题;③结合路径规划轨迹优化提升机械臂作业效率;④掌握基于Matlab的状态估计、数据融合智能算法仿真方法; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点理解运动学建模神经网络控制的设计流程,关注算法实现细节仿真结果分析,同时参考文中提及的多种优化估计方法拓展研究思路。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值