创建react应用程序_React应用程序的6个优化技巧

news/2024/7/1 22:43:23

创建react应用程序

介绍 (Introduction)

In the last few years JavaScript frameworks have completely changed the way we build apps, and React has had its fair share of the conversion process. Optimizing page load time is important because the time a page takes to load directly correlates with bounce and conversion rates. In this tutorial we will take a look at six common mistakes most developers make when building apps with React. We will also discuss how these mistakes can be avoided as well as highlight useful tips for keeping your page load time as low as possible.

在过去的几年中,JavaScript框架完全改变了我们构建应用程序的方式,而React在转换过程中占有相当大的份额。 优化页面加载时间很重要,因为页面加载所需的时间与跳出率和转化率直接相关。 在本教程中,我们将介绍大多数开发人员在使用React构建应用程序时犯的六个常见错误。 我们还将讨论如何避免这些错误,并重点介绍一些有用的技巧,以使您的页面加载时间尽可能地短。

React如何工作 (How React Works)

The image above explains what goes on each time you use a React app. Every React application begins with a root component — which in our case here is App — and is composed of “children” components — AddGrocery, GroceryList and SearchBar. These children components consist of functions that render UI to the DOM based on properties and state contained in them.

上图说明了每次使用React应用程序时发生的情况。 每个React应用程序都以根组件(在我们的示例中为App开头,并且由“子”组件( AddGroceryGroceryListSearchBar 。 这些子组件包含一些函数,这些函数根据其中包含的属性和状态将用户界面呈现给DOM。

Users interact with the rendered UI in different ways — by filling out a form or clicking a button. When this happens, events are relayed back to the parent component. These events cause a change in the state of the application thus prompting React to re-render the UI in its virtual DOM.

用户通过填写​​表单或单击按钮,以不同的方式与呈现的UI进行交互。 发生这种情况时,事件将中继回父组件。 这些事件会导致应用程序状态发生变化,从而促使React在其虚拟DOM中重新呈现UI。

For every event that gets sent back up, React’s engine has to compare the virtual DOM with the real DOM and calculate if it is necessary to update the real DOM with this new found data. Now, where things get messy is if our App is structured in a way that every click and scroll results in React repeatedly comparing and updating changes between the virtual and the real DOM. This could result in a terribly slow and inefficient application.

对于每个发送回的事件,React的引擎必须将虚拟DOM与真实DOM进行比较,并计算是否有必要使用此新发现的数据更新真实DOM。 现在,让我们感到混乱的是,我们的应用程序的结构是否使得每次单击和滚动都会导致React反复比较和更新虚拟DOM和真实DOM之间的更改。 这可能会导致极其缓慢和低效的应用程序。

常见错误以及如何避免它们 (Common Mistakes and How to Avoid Them)

Below are three poor practices developers make when building applications. These mistakes decrease efficiency and increase page load times overall, avoid them as much as you can.

以下是开发人员在构建应用程序时犯的三种不良做法。 这些错误会降低效率并总体上增加页面加载时间,请尽可能避免它们。

不必要的进口 (Unnecessary Imports)

Whenever you import an entire library in your application, it is destructured to access the module you need. One or two small libraries may do no harm but when you are importing a lot of libraries and dependencies you should just import the module you need:

每当您在应用程序中导入整个库时,该库都会被解构以访问所需的模块。 一个或两个小的库可能没有害处,但是当您导入许多库和依赖项时,您应该只导入所需的模块:

import assign from "101";
import Map from "immutable";

The code above imports the entire library and begins to destructure it to access assign and Map. Instead of doing that, let’s use a concept called “cherry picking” that only grabs the necessary parts of what your application needs:

上面的代码将导入整个库,并开始对其进行解构以访问assignMap 。 而不是这样做,我们使用一个称为“樱桃采摘”的概念,该概念仅能获取应用程序所需的必要部分:

import assign from "101/assign";
import Map from "immutable/src/map";

在JSX中嵌入函数 (Embedding Functions in JSX)

JavaScript is well known as a garbage collected language. Its garbage collector manages memory by trying to reclaim memory no longer in use by parts of the application. Defining a function in render will create a new instance of the function each time the containing component is re-rendered. When this practice occurs all over your application it eventually becomes a problem for the garbage collector in the form of memory leaks — a situation where memory used by parts of the application is not released even though it is no longer in use by those parts:

JavaScript是众所周知的垃圾收集语言。 它的垃圾收集器通过尝试回收应用程序的某些部分不再使用的内存来管理内存。 每次重新渲染包含组件时,在render中定义函数都会创建该函数的新实例。 当这种做法遍及您的应用程序时,最终将以内存泄漏的形式成为垃圾收集器的问题-这种情况下,即使应用程序的某些部分不再使用这些内存,也不会释放它们所占用的内存:

class GroceryList extends React.Component {
    state = {
        groceries: [],
        selectedGroceryId: null
    }

    render(){
        const { groceries } = this.state;
        return (
           groceries.map((grocery)=>{
               return <Grocery onClick={(e)=>{
                    this.setState({selectedGroceryId:grocery.groceryId})
               }} grocery={grocery} key={grocery.id}/>
           }) 
        )
    }
}

The right thing would be to define a new function onGroceryClick right before render:

正确的做法是在render之前在onGroceryClick上定义一个新函数:

class GroceryList extends React.Component {
    state = {
        groceries: [],
        selectedGroceryId: null
    }

    onGroceryClick = (groceryId)=>{
        this.setState({selectedGroceryId:groceryId})
    }

    render(){
        const { groceries } = this.state;
        return (
           groceries.map((grocery)=>{
               return <Grocery onClick={this.onGroceryClick} 
                grocery={grocery} key={grocery.id}/>
           }) 
        )
    }
}

在DOM元素中使用Spread运算符 (Using the Spread Operator in DOM Elements)

When building apps it is poor practice to use the spread operator in an unreserved fashion. This will have unknown attributes flying around and it is only a matter of time before things begin to get complicated. Here is a brief example:

在构建应用程序时,以无保留的方式使用传播运算符是不明智的做法。 这将具有未知的属性,并且事情开始变得复杂起来只是时间问题。 这是一个简短的示例:

const GroceriesLabel = props => {
    return (
      <div {...props}>
        {props.text}
      </div>
    );
  };

As the application you are building becomes larger, . . .props could contain anything. A better and safer practice is to identify whatever values you need:

随着您正在构建的应用程序变大, . . .props . . .props . . .props可以包含任何内容。 更好和更安全的做法是确定您需要的任何值:

const GroceriesLabel = props => {
    return (
      <div particularValue={props.particularValue}>
        {props.text}
      </div>
    );
};

性能技巧 (Performance Hacks)

使用Gzip压缩捆绑包 (Use Gzip to Compress Your Bundles)

This is very efficient and can reduce the size of your files by as much as 65%. Most of the files in your application will use a lot of repeated text and whitespace. Gzip handles this by compressing these recurrent strings thus drastically shortening your website’s first render time. Gzip pre-compresses your files by using compressionPlugin — Webpack’s local plugin for compressing files during production, first let’s create a compressed bundle using compressionPlugin:

这非常有效,并且可以将文件大小减少多达65%。 您的应用程序中的大多数文件将使用大量重复的文本和空格。 Gzip通过压缩这些重复出现的字符串来解决此问题,从而大大缩短了网站的首次渲染时间。 Gzip使用compressionPlugin (Webpack的本地插件,用于在生产过程中压缩文件)预压缩文件,首先让我们使用compressionPlugin创建一个压缩包:

plugins: [
    new CompressionPlugin({
        asset: "[path].gz[query]",
        algorithm: "gzip",
        test: /.js$|.css$|.html$/,
        threshold: 10240,
        minRatio: 0.8
    })
]

Once the file has been compressed, it can then be served using middleware:

压缩文件后,便可以使用中间件提供文件:

//this middleware serves all js files as gzip
app.use(function(req, res, next) {
    const originalPath = req.path;
    if (!originalPath.endsWith(".js")) {
        next();
        return;
    }
    try {
        const stats = fs.statSync(path.join("public", `${req.path}.gz`));
        res.append('Content-Encoding', 'gzip');
        res.setHeader('Vary', 'Accept-Encoding');
        res.setHeader('Cache-Control', 'public, max-age=512000');
        req.url = `${req.url}.gz`;

        const type = mime.lookup(path.join("public", originalPath));
        if (typeof type != 'undefined') {
            const charset = mime.charsets.lookup(type);
            res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
        }
    } catch (e) {}
    next();
})

记住React组件 (Memoizing React Components)

The concept of memoization isn’t new — it is a technique that stores expensive function calls and returns the cached result when the same input occurs again. Memoization in React works by memoizing data computation so that changes in state happen as quickly as possible. To understand how this works, take a look at the React component below:

记忆的概念并不是一个新概念,它是一种存储昂贵的函数调用并在再次出现相同输入时返回缓存结果的技术。 React中的记忆是通过记忆数据计算来进行的,因此状态变化会尽快发生。 要了解它是如何工作的,请看下面的React组件:

const GroceryDetails = ({grocery, onEdit}) => {
    const {name, price, grocery_img} = grocery;
    return (
        <div className="grocery-detail-wrapper">
            <img src={grocery_img} />
            <h3>{name}</h3>
            <p>{price}</p>
        </div>
    )
}

In the code sample above, all the children in GroceryDetails are based on props. Changing props will cause GroceryDetails to re-render. If GroceryDetails is a component that’s unlikely to change, it should be memoized. Users of earlier versions of React (< V16.6.0) would use moize, a memoization library for JavaScript. Take a look at the syntax below:

在上面的代码示例中, GroceryDetails中的所有GroceryDetails均基于道具。 更改道具会导致GroceryDetails重新渲染。 如果GroceryDetails是不太可能更改的组件,则应记住该组件。 早期版本的React(<V16.6.0)的用户将使用moize (JavaScript的记忆库)。 看一下下面的语法:

import moize from 'moize/flow-typed';

const GroceryDetails = ({grocery, onEdit}) =>{
    const {name, price, grocery_img} = grocery;

    return (
        <div className="grocery-detail-wrapper">
            <img src={grocery_img} />
            <h3>{name}</h3>
            <p>{price}</p>
        </div>
    )
}

export default moize(GroceryDetails,{
    isReact: true
});

In the code block above, moize stores any passed props and context in GroceryDetails and uses both of them to detect if there are updates to the component. As long as props and context remain unchanged, cached values will be returned. This ensures super quick rendering.

在上面的代码块中, moize将所有传递的道具和上下文存储在GroceryDetails并使用它们两者来检测组件是否有更新。 只要prop和context保持不变,就会返回缓存的值。 这样可以确保超级快速的渲染。

For users working with later versions of React (greater than V16.6.0), you can use React.memo instead of moize:

对于使用更高版本的React(高于V16.6.0)的用户,可以使用React.memo代替moize:

const GroceryDetails = ({grocery, onEdit}) =>{
    const {name, price, grocery_img} = grocery;

    return (
        <div className="grocery-detail-wrapper">
            <img src={grocery_img} />
            <h3>{name}</h3>
            <p>{price}</p>
        </div>
    )
}

export default React.memo(GroceryDetails);

考虑使用服务器端渲染 (Consider Using Server-Side Rendering)

Server-Side Rendering (SSR) is the ability of a front-end framework to render markup while running on a back-end system.

服务器端渲染(SSR)是前端框架在后端系统上运行时呈现标记的功能。

You should leverage SSR with Single Page Applications. Rather than have users wait for your JavaScript files to load, users of your application receive a fully rendered HTML page as soon as the initial request sent returns a response. Generally server-side rendered applications enable users receive content way faster than client-rendered applications. Some solutions for server-side rendering in React include Next.js and Gatsby.

您应该在单页应用程序中使用SSR。 应用程序的用户会在发送的初始请求返回响应后立即接收完整呈现HTML页面,而不是让用户等待JavaScript文件加载。 通常,服务器端渲染的应用程序使用户比客户端渲染的应用程序更快地接收内容。 React中用于服务器端渲染的一些解决方案包括Next.js和Gatsby。

结论 (Conclusion)

For the average beginner who may not be familiar with these concepts, I suggest you check out this course on getting started with React as it covers a ton — from handling state to creating components. The importance of optimising page load time in your React application cannot be underestimated. Not only will your app facilitate better SEO and command a higher conversion rate, by following best practices you will be able to detect errors more easily. These concepts may require a lot of efforts but they are worth giving a shot. Posts such as Memoize React Components by Tony Quetano and How to serve a Webpack gzipped file in production by Selva Ganesh helped in writing this.

对于可能不熟悉这些概念的普通初学者,我建议您阅读本教程以了解React入门,因为它涉及很多内容-从处理状态到创建组件。 在您的React应用程序中优化页面加载时间的重要性不可低估。 通过遵循最佳实践,您的应用程序不仅可以促进更好的SEO并获得更高的转化率,而且还可以更轻松地检测错误。 这些概念可能需要大量的努力,但值得一试。 诸如Tony Quetano的Memoize React Components和Selva Ganesh的生产中如何在Webpack中压缩Webzip文件之类的帖子有助于编写此内容。

翻译自: https://www.digitalocean.com/community/tutorials/6-quick-optimisation-tips-in-react-apps

创建react应用程序


http://www.niftyadmin.cn/n/3649535.html

相关文章

华为云鲲鹏云服务器安装MySQL 5.7.30

▣ 博主主站地址&#xff1a;微笑涛声 【www.cztcms.cn】 ▣ 博主其他平台&#xff1a; CSDN 简书 开源中国 思否 华为云博客 华为云鲲鹏云服务器搭载的是华为鲲鹏处理器&#xff08;916/920&#xff09;,华为鲲鹏处理器是基于ARM架构的处理器&#xff0c;不同于传统的X86架构…

prisma orm_Prisma与Node.js-第2部分:Prisma绑定

prisma ormOver in Part 1 we discussed how to connect our deployed Prisma API to our Node.js-based GraphQL server. Now we’re going to look into using the prisma-bindings library to start using all the superpowers that Prisma has generated for us. 在第1部分…

华为云鲲鹏云服务器安装Nginx

▣ 博主主站地址&#xff1a;微笑涛声 【www.cztcms.cn】 ▣ 博主其他平台&#xff1a; CSDN 简书 开源中国 思否 华为云博客 华为云鲲鹏云服务器搭载的是华为鲲鹏处理器&#xff08;916/920&#xff09;,华为鲲鹏处理器是基于ARM架构的处理器&#xff0c;不同于传统的X86架构…

几种常见的设计模式

--什么是设计模式&#xff1f;设计模式有哪几种分类&#xff1f;每类模式重点解决什么问题&#xff1f; 设计模式&#xff1a;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 …

使用Visual Studio Code调试Go代码

This article will go over how to debug your Go code, so it goes without saying that a prerequisite for this article is that you understand the basics of writing Go. 本文将介绍如何调试Go代码&#xff0c;因此无需多说&#xff0c;本文的前提条件是您了解编写Go的基…

[Wap]command和selectionList冲突的分析

[Wap]command和selectionList冲突的分析编写者日期关键词郑昀ultrapower2005-7-14Wap ASP.NET Opera Openwave M3Gate MME3.0现象我们的Wap页面由dotNET 编写而成&#xff0c;一个页面上使用了mobile:command和mobile:selectionlist控件。当使用Opera、Microsoft Mobile Explor…

建站分享:调整WordPress自带标签云参数

▣ 博主主站地址&#xff1a;微笑涛声 【www.cztcms.cn】 ▣ 博主其他平台&#xff1a; CSDN 简书 开源中国 思否 华为云博客 WordPress 自带的标签云是一个很实用的小工具。站长可以通过标签对具有相同关健词的文章进行检索分类,利于访客查找相关文章。 WordPress标签默认显…

golang定义一个方法_在Go中定义方法

golang定义一个方法介绍 (Introduction) Functions allow you to organize logic into repeatable procedures that can use different arguments each time they run. In the course of defining functions, you’ll often find that multiple functions might operate on the…