创建react应用程序_创建多版本React应用程序的6个步骤

article/2025/9/27 12:13:25

创建react应用程序

The React team said that there are no new features in React 17, but react@17.0.0-rc.0 comes with the power to lazy load and deep integrate multiple versions of React. This no-feature is larger than any feature, which is a stepping stone for a paradigm that allows modern new apps to coexist with existing legacy ones.

React团队表示,React 17中没有新功能,但是react@17.0.0-rc.0具有延迟加载和深度集成多个版本的React的能力。 这种无功能大于任何功能,这是使现代新应用程序与现有旧应用程序共存的范例的垫脚石。

This hybrid approach is meant to be an escape hatch, not the norm. Using a single version of React is the best practice, which removes a lot of complexity and saves you from multiple package downloading. However, this is still a powerful alternative in an environment with legacy code.

这种混合方法是要逃脱,而不是规范。 最佳实践是使用React的单个版本,这消除了很多复杂性,并使您免于多次下载软件包的麻烦。 但是,在具有遗留代码的环境中,这仍然是一个强大的替代方案。

In 5 Steps to Turn a Random React Application Into a Micro Front-End, we have drawn the above architecture diagram that launches multiple React applications, legacy and new, that work together as one application. Does it sound like a different option for a similar problem?

在将随机React应用程序转变为微型前端的5个步骤中 ,我们绘制了以上架构图,该架构图启动了多个React应用程序(旧版和新版),它们可以作为一个应用程序一起工作。 听起来像是解决类似问题的另一种选择?

Our example is inspired by Demo of Gradual React Upgrades. We will refer to it as The Demo.

我们的示例受Demo of Gradual React Upgrades启发。 我们将其称为The Demo

Based on our tryout, there are six steps to create a multi-version React application.

根据我们的试用,有六个步骤来创建一个多版本的React应用程序。

步骤1:将新代码移至Src /现代目录 (Step 1: Move New Code to Src/Modern Directory)

As always, we start with the Create React App.

与往常一样,我们从Create React App开始 。

npx create-react-app my-app
cd my-app
npm start

Since we are going to put multiple React apps into the same repository, we need to set up namespaces. Here is the directory structure.

由于我们要将多个React应用程序放入同一个存储库,因此我们需要设置名称空间。 这是目录结构。

src
├─ modern // new code: React 17
├─ legacy // legacy code: React 16.3.1 - could be lower version
└─ shared // shared code - common source

We move everything in src to src/modern.

我们将src所有内容移动到src/modern

$ ls
App.css index.css App.js
index.js serviceWorker.js. App.test.js
logo.svg setupTests.js

In addition, copy package.json to src/modern, and make some modifications:

另外,将package.json复制到src/modern ,并进行一些修改:

{"name": "react-app-modern","version": "0.1.0","private": true,"dependencies": {"@testing-library/jest-dom": "^4.2.4","@testing-library/react": "^9.5.0","@testing-library/user-event": "^7.2.1","react": "17.0.0-rc.0","react-dom": "17.0.0-rc.0"}
}

At line 2, change it to a proper name. Keep all dependencies, and remove the rest of the sections.

在第2行,将其更改为专有名称。 保留所有依赖项 ,然后删除其余部分。

At line 9 and line 10, React versions has been upgraded to 17.0.0-rc.0.

在第9行和第10行,React版本已升级到17.0.0-rc.0

The react-scripts package is removed from the dependencies list.

react-scripts包已从依赖项列表中删除。

步骤2:将旧版代码移至src /旧版目录 (Step 2: Move Legacy Code to src/legacy Directory)

The legacy code is put under src/legacy.

遗留代码放在src/legacy

$ ls
App.css index.css App.js
index.js serviceWorker.js. App.test.js
logo.svg setupTests.js
{"name": "react-app3-modern","version": "0.1.0","private": true,"dependencies": {"@testing-library/jest-dom": "^4.2.4","@testing-library/react": "^9.5.0","@testing-library/user-event": "^7.2.1","react": "^16.13.1","react-dom": "^16.13.1"}
}

At line 2, change it to a proper name. Keep all dependencies and remove the rest of the sections.

在第2行,将其更改为专有名称。 保留所有依赖性,并删除其余部分。

At line 9 and line 10, the React versions has been kept to 16.13.1.

在第9行和第10行,React版本保持在16.13.1

Thereact-scripts package is removed from the dependencies list.

react-scripts包已从依赖项列表中删除。

步骤3:更改Root package.json (Step 3: Change Root package.json)

The following root package.json is copied and adapted from The Demo. The previously removed sections are put back here, with a lot more things.

以下根package.jsonThe Demo复制并改编而成。 先前删除的部分将放回此处,还有更多内容。

{"name": "react-app-shell","version": "0.1.0","private": true,"dependencies": {"react-scripts": "3.4.1"},"scripts": {"postinstall": "run-s install:*","install:legacy": "cd src/legacy && npm install","install:modern": "cd src/modern && npm install","copy:legacy": "cpx 'src/shared/**' 'src/legacy/shared/'","copy:modern": "cpx 'src/shared/**' 'src/modern/shared/'","watch:legacy": "cpx 'src/shared/**' 'src/legacy/shared/' --watch --no-initial","watch:modern": "cpx 'src/shared/**' 'src/modern/shared/' --watch --no-initial","prebuild": "run-p copy:*","prestart": "run-p copy:*","start": "run-p start-app watch:*","start-app": "react-scripts start","build": "react-scripts build","eject": "react-scripts eject"},"eslintConfig": {"extends": "react-app"},"browserslist": {"production": [">0.2%","not dead","not op_mini all"],"development": ["last 1 chrome version","last 1 firefox version","last 1 safari version"]},"devDependencies": {"cpx": "1.5.0","npm-run-all": "4.1.5"}
}

At line 2, change it to a proper name.

在第2行,将其更改为专有名称。

Lines 5 - 7 are dependencies which include the build dependencies (react-scripts) and possibly React-agnostic libraries (redux in The Demo).

第5-7行是依赖关系,其中包括构建依赖关系( react-scripts )以及可能与React无关的库( The Demo redux )。

Lines 38 - 41 are some help utilities for copy files (cpx) and parallel/sequentially running tools (npm-run-all).

第38至41行是一些帮助实用程序,用于复制文件( cpx )和并行/顺序运行的工具( npm-run-all )。

These utilities are used in scripts (lines 8 - 22), which copies shared files to both modern and legacy directories, and installs, builds and watches them. If you want to create a different directory structure, these scripts need to be adjusted.

这些实用程序用在scripts (第8-22行),该scriptsshared文件复制到modern目录和legacy目录中,并安装,构建和监视它们。 如果要创建其他目录结构,则需要调整这些脚本。

Lines 23 - 25 are for eslintConfig.

第23至25行用于eslintConfig

Lines 26 - 37 are for browserslist.

第26-37行用于browserslist

Run install i. It generates src/modern/node_modules and src/modern/node_modules.

运行install i 。 它生成src/modern/node_modulessrc/modern/node_modules

步骤4:设置环境文件 (Step 4: Set Up Environment Files)

As VSCode starts to show 5K changes and eslint displays errors for node_modules, we need to set up a few environment files.

至于VSCode开始显现5K变化和eslint显示错误的node_modules ,我们需要设置一些环境文件。

Configure .env to enable eslint for static code analysis:

配置.env以启用eslint进行静态代码分析:

EXTEND_ESLINT=true

Configure .eslintignore to ignore eslint errors for these directories:

配置.eslintignore以忽略以下目录的eslint错误:

node_modules
build
src/*/shared

Configure .gitignore to exclude these directories/files for source code control:

配置.gitignore以排除以下目录/文件以进行源代码控制:

node_modules
build
.DS_Store
src/*/shared

Now it shows changes of 32 files. Things are in good shape.

现在,它显示了32个文件的更改。 情况良好。

步骤5:设定src / index.js (Step 5: Set Up src/index.js)

We invoke npm start, and get the following error:

我们调用npm start ,并得到以下错误:

Could not find a required file.
Name: index.js
Searched in: /Users/fuje/app/react-app4/src

Okay, we need to set up src/index.js, which points to src/modern/index.js.

好的,我们需要设置src/index.js ,它指向src/modern/index.js

import './modern/index';

Try again with npm start. We see this familiar Create React App:

使用npm start再试一次。 我们看到了这个熟悉的Create React App:

Image for post

步骤6:在旧版应用程序和新应用程序之间架起一座桥梁 (Step 6: Build a Bridge Between Legacy and New Apps)

We have one version of React running. Since the goal is to mix legacy and new apps, the legacy app needs to be loaded into the new app.

我们有一个版本的React运行。 由于目标是混合旧应用程序和新应用程序,因此需要将旧应用程序加载到新应用程序中。

import React, { Suspense } from 'react';
import logo from './logo.svg';
import './App.css';const App2 = React.lazy(() => import('../legacy/App'));function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>This is the modern App to load legacy React.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a><Suspense fallback={() => null}><App2 /></Suspense></header></div>);
}export default App;

At line 5, the legacy app is lazy-loaded, and it is used at lines 22 - 24.

在第5行,旧版应用程序被延迟加载,并在第22-24行使用。

The text in line 13 is modified to show that it’s from the modern app.

第13行中的文本已修改为显示它来自现代应用程序。

Run npm start, we see the modern app running together with the legacy React.

运行npm start ,我们将看到现代应用程序与旧版React一起运行。

Image for post

So far, so good.

到目前为止,一切都很好。

We add useState hook into src/legacy/App.js:

我们将useState钩子添加到src/legacy/App.js

import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';const App = () => {const [value, setValue] = useState(0);return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a><button onClick={() => setValue(value + 1)}>Click me {value} times</button></header></div>);
}export default App;

Lines 22-24 create a button to be clicked.

第22-24行创建了一个要单击的按钮。

Then we encounter the following error:

然后我们遇到以下错误:

Image for post

Oh, what happened?

哦!发生了什么?

A bridge between legacy and new apps needs to be built.

需要在旧版和新版应用程序之间架起一座桥梁。

import React, { Suspense } from 'react';
import logo from './logo.svg';
import './App.css';
import lazyLegacyRoot from './lazyLegacyRoot';const App2 = lazyLegacyRoot(() => import('../legacy/App'));function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>This is the modern App to load legacy React.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a><Suspense fallback={() => null}><App2 /></Suspense></header></div>);
}export default App;

Instead of calling React.lazy, line 6 calls lazyLegacyRoot, which is defined inside src/modern/lazyLegacyRoot.js:

第6行没有调用React.lazy ,而是调用了lazyLegacyRoot ,它在src/modern/lazyLegacyRoot.js定义:

import React, {useRef, useLayoutEffect} from 'react';let rendererModule = {status: 'pending',promise: null,result: null,
};export default function lazyLegacyRoot(getLegacyComponent) {let componentModule = {status: 'pending',promise: null,result: null,};return function Wrapper(props) {const createLegacyRoot = readModule(rendererModule, () =>import('../legacy/createLegacyRoot')).default;const Component = readModule(componentModule, getLegacyComponent).default;const containerRef = useRef(null);const rootRef = useRef(null);// Create/unmount.useLayoutEffect(() => {if (!rootRef.current) {rootRef.current = createLegacyRoot(containerRef.current);}const root = rootRef.current;return () => {root.unmount();};}, [createLegacyRoot]);// Mount/update.useLayoutEffect(() => {if (rootRef.current) {rootRef.current.render(Component, props);}}, [Component, props]);return <div style={{display: 'contents'}} ref={containerRef} />;};
}// This is similar to React.lazy, but implemented manually.
// We use this to Suspend rendering of this component until
// we fetch the component and the legacy React to render it.
function readModule(record, createPromise) {if (record.status === 'fulfilled') {return record.result;}if (record.status === 'rejected') {throw record.result;}if (!record.promise) {record.promise = createPromise().then(value => {if (record.status === 'pending') {record.status = 'fulfilled';record.promise = null;record.result = value;}},error => {if (record.status === 'pending') {record.status = 'rejected';record.promise = null;record.result = error;}});}throw record.promise;
}

This is one end of the bridge. At lines 17-19, it dynamically imports createLegacyRoot from the legacy code. Then calls two useLayoutEffect (lines 25-33 are for creating, lines 36-40 are for updating) to re-render the code with the new version React.

这是桥的一端。 在第17-19行,它从旧版代码动态导入createLegacyRoot 。 然后调用两个useLayoutEffect (第25-33行用于创建,第36-40行用于更新)以使用新版本的React重新渲染代码。

useLayoutEffect’s signature is identical to useEffect, but it fires synchronously after all DOM mutations. Updates scheduled inside useLayoutEffect will be flushed synchronously before the browser has a chance to paint.

useLayoutEffect的签名与useEffect相同,但是在所有DOM突变后都会同步触发。 在浏览器有机会绘制之前,在useLayoutEffect内部计划的更新将被同步刷新。

Let’s see the other end of the bridge:

让我们看一下桥的另一端:

import React from 'react';
import ReactDOM from 'react-dom';// Note: this is a semi-private API, but it's ok to use itexport default function createLegacyRoot(container) {return {render(Component, props) {ReactDOM.render(<Component {...props} />, container);},unmount() {ReactDOM.unmountComponentAtNode(container);},};
}

Lines 8-10 defines a method to render.

第8-10行定义了一种渲染方法。

Line 11-13 defines a method to unmount.

第11-13行定义了一种卸载方法。

With the two ends of the bridge, we make the multi-version React app work properly:

通过桥接的两端,我们使多版本React应用程序能够正常工作:

Image for post

演示 (The Demo)

The demo can be downloaded and run:

The demo可以下载并运行:

git clone https://github.com/reactjs/react-gradual-upgrade-demo.git
cd react-gradual-upgrade-demo
npm i
npm start

It includes two routes:

它包括两条路线:

  • The Home route: It shows the new app only. The visible components are rendered by React 17.

    本地路线:仅显示新应用。 可见组件由React 17渲染。
Image for post
  • The About Route: It shows a UI mixed with the legacy and new app. The components outside of the dotted lines are rendered by React 17, and the components inside of the dotted lines are rendered by React 16.8.6.

    关于路线:它显示了一个界面,其中包含旧版和新版应用程序。 虚线外部的组件由React 17呈现,而虚线内部的组件由React 16.8.6呈现。
Image for post

The demo is more advanced than the example we described here. It shows how to share a theme as a global context and how to share a Redux store (for counter) between apps. It also shares useTime hook and the clock display. It is worthwhile to download The demo and take a deep dive into it.

The demo比我们在此描述的示例更高级。 它显示了如何将主题共享为全局上下文,以及如何在应用程序之间共享Redux存储(用于计数器)。 它还共享useTime挂钩和时钟显示。 值得下载The demo并进行深入研究。

Try out the six steps we summarized to create your own multi-version React application. React 17 provides the capability of lazy load and deep integration of multiple versions of React.

试试我们总结的六个步骤,以创建您自己的多版本React应用程序。 React 17提供了延迟加载和深度集成多个版本的React的功能。

结论 (Conclusion)

React 17 is here. It changes synthetic React events, as well as some other features. Read this for more information.

React 17在这里。 它更改了合成的React事件以及其他一些功能。 阅读此以获得更多信息。

React 17 is a major release. We need to move to React 17 to access the capability to not move so fast in the future. Cool?

React 17是一个主要版本。 我们需要移至React 17来获得将来不会如此快地移动的功能。 凉?

Thanks for reading. I hope this was helpful. You can see my other Medium publications here.

谢谢阅读。 我希望这可以帮到你。 您可以在这里查看我的其他Medium出版物。

翻译自: https://medium.com/better-programming/6-steps-to-create-a-multi-version-react-application-1c3e5b5df7e9

创建react应用程序


http://chatgpt.dhexx.cn/article/6fTXuBsE.shtml

相关文章

你真的懂package.json吗

点击蓝字 「前端小苑」关注我 作者 | MasonEast 编辑 | 桔子酱 前言 在Node.js中&#xff0c;模块是一个库或框架&#xff0c;也是一个Node.js项目。Node.js项目遵循模块化的架构&#xff0c;当我们创建了一个Node.js项目&#xff0c;意味着创建了一个模块&#xff0c;这个模块…

《Linux编程》上机作业 ·004【文件I/O操作】

注&#xff1a;前言、目录见 https://blog.csdn.net/qq_44220418/article/details/108428971 友情提醒&#xff1a;仅供参考理解&#xff0c;请勿直接复制粘贴 友情提醒&#xff1a;仅供参考理解&#xff0c;请勿直接复制粘贴 友情提醒&#xff1a;仅供参考理解&#xff0c;…

CPU比GPU训练神经网络快十几倍,英特尔:别用矩阵运算了

来源丨机器之心 神经网络训练通常是 GPU 大显身手的领域&#xff0c;然而莱斯大学和英特尔等机构对 GPU 的地位发起了挑战。 在深度学习与神经网络领域&#xff0c;研究人员通常离不开 GPU。得益于 GPU 极高内存带宽和较多核心数&#xff0c;研究人员可以更快地获得模型训练的结…

用于基于 CNT 的射频辐射热计开发研究的 CPX-VF 探针台

我们会不时强调我们的低温探针台如何用于有趣的研究。我们最新的应用重点是阿克伦大学领导的工作&#xff0c;并发表在上个月的IEEE 微波理论与技术汇刊上。与来自美国陆军和 Nano-C Inc.&#xff08;马萨诸塞州 Westwood 的纳米结构碳材料及其应用开发商&#xff09;的研究人员…

ProJet 3510 CPX蜡模3D打印机在珠宝行业成功应用

传统的首饰设计是一个细致和增量的过程。传统设计从设计师的构图开始&#xff0c;一旦草图被批准后,就会雕刻成模型&#xff0c;如果蜡模没有足够接近原始草图或未能满足客户的期望&#xff0c;必须重做,这样会浪费大量的时间。使用ProJet 3510 CPX专业蜡成型3 d打印机&#xf…

基于 CNT 的射频辐射热计开发研究的 CPX-VF 低温探针台

有时&#xff0c;我们喜欢强调我们的低温探针台如何用于有趣的研究。我们最新的应用重点是由阿克伦大学领导并发表在上个月的IEEE Transactions on Microwave Theory and Techniques 上的工作。UA 的 ZEN-Lab 的Michael Gasper 和 Ryan Toonen 博士与美国陆军和 Nano-C Inc.&am…

Parker驱动器维修COMPAX控制器维修CPX0200H

COMPAX控制器&#xff1a;由不同的模拟功率控制信号&#xff0c;由MOSFET IC级驱动器GND/PGND&#xff08;功率接地&#xff09;&#xff09;的信号控制&#xff0c;则应分别接地。使用IC的小信号部分的控制IC&#xff0c;SGND信号与功率地之间的连接点。合理的方法是地信号地返…

用于 CPX、CPX-VF 和 CRX-VF 探针台的新手提箱选项

如果您正在寻找一种简单的方法来将样品从手套箱、干燥箱或其他惰性气氛容器转移到高真空、低温探测环境&#xff0c;您可能会感兴趣&#xff1a;一个新的专用手提箱 (PS-SC- CPX) 与可安装在我们的CPX、CPX-VF或CRX-VF探针台上的负载锁定组件 (PS-LL-CPX) 一起使用。 该手提箱具…

GE IC697CPX935 CPU模块PDF帅

IC697CPX935 是 GE 自动化和控制公司制造的具有三个内置串行端口的单槽 PLC CPU。它能够对系统进行实时控制。使用 VMEC.1 格式&#xff0c;IC697CPX935 可以通过安装在机架上的背板与不同的“智能选项”模块进行通信。该设备通过三位运行/停止控制开关或连接到运行适当软件的计…

micropython仿真器_microbit/cpx 的 python模拟器:Device Simulator Express

Device Simulator Express是一个 VSCode 的编程扩展,使用它无需硬件就能对 Circuit Playground Express(CPX)或 BBC micro:bit 仿真和调试python程序,此外还可以通过串口观察设备的输出。Device Simulator Express 和 makecode 中的设备模拟器功能类似,但它是一个 python 程…

Win10强制更新关闭方法

Win10自动更新怎么永久关闭&#xff1f;有效的Win10强制更新关闭方法 之前小编为大家分享过一些Win10彻底关闭Windows Update自动更新的方法&#xff0c;主要是通过一些如设置流量计费或借助一些专门的小工具来实现&#xff0c;但往往会发现&#xff0c;Win10自动更新就像打不死…

Win10强制更新禁不掉的解决方法

现况 2018年8月之后安装或者更新的win10&#xff0c;现在会出现无法禁用windows update的情况&#xff0c;表现为&#xff1a; 在服务里禁用了windows update服务&#xff0c;后续服务仍能正常启动强制更新。设置“登录”和“恢复”选项卡依然无效。在设置里关闭更新选项无效…

iOS 强制更新

废话不多说&#xff0c;直接上代码 (void)getNewVersion {NSURLRequest *request [NSURLRequest requestWithURL:[NSURL URLWithString:"http://itunes.apple.com/cn/lookup?id1036152564"]];NSURLSessionDataTask *task [[NSURLSession sharedSession] dataTaskW…

uniapp APP端在线升级功能实现讲解——强制或可选升级,下载进度显示

文章目录 概要 需求分析 技术实现梳理 1.是否更新判断&#xff1a; 2.升级弹窗的展示 3.根据升级类型限制操作 4.下载APP监听下载进度 5.下载完自动安装 核心API讲解 1.plus.downloader.createDownload(url,options,completedCallback)&#xff08;下载&#xff09; 2.plus.r…

Windows如何一键永远禁止系统更新?

大家好&#xff0c;我是小寻&#xff0c;欢迎关注公众号:工具优选&#xff0c;免费领取优质项目源码和常用工具&#xff0c;还可以加入我的交流群! 一、工具介绍 想必大家也会与小编存在同样的困惑&#xff0c;为啥我电脑上的windows会频繁的强制系统升级&#xff1f;windows…

win10总强制更新?教你永久关闭

win10系统个人觉得还挺好用的&#xff0c;但是有一点非常烦人&#xff0c;就是隔三岔五强制自动更新&#xff01; 相信也是大部分用户最不喜欢的一点。 更新后&#xff0c;系统可能还会出现一些bug&#xff0c;而且每次更新都要等上一段时间。对于每天工作繁忙的用户来说&…

解决Xshell/Xftp强制升级无法进入问题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、首先创建一个Xshell.txt文件&#xff0c;用notepad打开 二、将以下代码复制入.txt文件 1.实例代码 2.保存文件&#xff0c;重命名 3.以管理员身份运行…

杰理强制升级工具4.0使用和原理解析

用那个有8个挡位的烧录工具&#xff08;4.0工具&#xff09;的话&#xff0c;默认是走USB的&#xff0c;不是走串口&#xff0c;工具的DP接芯片的DP&#xff0c;工具的DM接芯片的DM&#xff0c;工具的5V接芯片的VBAT&#xff08;要保证能控制芯片供电通断才能从mask启动&#x…

无视Win11 TPM/英特尔芯片等配置,强制升级Win11

上次我写了一个DEV强制升级的文章&#xff0c;可是DEV版本的Windows11系统很不稳定&#xff0c;软件可能无法正常使用。这篇文以适用于任何电脑。建议看这篇文章哦&#xff01; 1.下载映像 大家可以在网上找.iso映像&#xff0c;也可以点击此处。 在网站上找到[下载 Windows…