需要减少NextJS站点的CLS以提高站点性能

eivgtgni  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(139)

我正在使用NextJS与Mantine开发一个网站。我使用createStyles来添加样式。我也尝试使用尽可能多的mantine组件。
当我在Vercel上部署站点时,我发现除了CLS之外,所有站点性能参数都很棒,这很糟糕;如此可怕,以至于你在第一次启动网站时就能感觉到内容的转变。
仅作为示例,Header的代码如下:

import { useState } from 'react';
import {
  createStyles, Container, Anchor, Group, ActionIcon, useMantineColorScheme
} from '@mantine/core';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import Sun from '@/public/svg/sun.svg';
import MoonStars from '@/public/svg/moonStars.svg';

const useStyles = createStyles((theme) => ({
  inner: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
  },

  burger: {
    [theme.fn.largerThan('sm')]: {
      display: 'none',
    }
  },

  links: {
    fontWeight: 700,
    textTransform: 'uppercase',
    textDecoration: 'none',
    fontSize: theme.fontSizes.md,
  },

  mainLink: {
    color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6],
    borderBottom: `2px solid transparent`,
    transition: 'border-color 100ms ease, color 100ms ease',

    '&:hover': {
      color: theme.colorScheme === 'dark' ? theme.white : theme.black,
      textDecoration: 'none',
    },
  },

  mainLinkActive: {
    color: theme.colorScheme === 'dark' ? theme.white : theme.black,
    borderBottomColor: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 5 : 6],
  },

  sideText: {
    color: theme.colorScheme === 'dark' ? theme.white : theme.black,
  }
}));

export default function Component() {
  const { colorScheme, toggleColorScheme } = useMantineColorScheme();
  const { classes, cx } = useStyles();
  let pathname = usePathname();
  const [active, setActive] = useState(() => {
    if (pathname.split('/')[1] === '') return 0;
    if (pathname.split('/')[1] === 'blog') return 1;
  });

  let mainLinks = [
    { "link": "/", "label": "About" },
    { "link": "/blog", "label": "Blog" },
  ]

  const mainItems = mainLinks.map((item, index) => (
    <Anchor component={Link} href={item.link} key={item.label} py='xl' px='md'
      className={cx(classes.mainLink, { [classes.mainLinkActive]: index === active }, classes.links)}
      onClick={() => setActive(index)} >
      {item.label}
    </Anchor>
  ));

  const changeColorScheme = () => {
    toggleColorScheme();
    localStorage.setItem('color-scheme', colorScheme === 'dark' ? 'light' : 'dark');
  }

  return (
    <Container pos='relative' mb='2rem'>
      <Container pos='sticky' className={classes.inner}>
        <div className={classes.links}>
          <Group spacing={0} >
            {mainItems}
          </Group>
        </div>
        <Group position="center" my="xl">
          <ActionIcon
            onClick={() => changeColorScheme()}
            size="lg"
            sx={(theme) => ({
              backgroundColor:
                theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
              color: theme.colorScheme === 'dark' ? theme.colors.yellow[4] : theme.colors.blue[6],
            })}>
            {colorScheme === 'dark' ? <Sun /> : <MoonStars />}
          </ActionIcon>
        </Group>
        {/* <Burger opened={opened} onClick={toggle} className={classes.burger} size="sm" /> */}
      </Container>
    </Container>
  );
}

字符串
如果你想自己尝试,可以找到website deployed here
我能想到的一个主要问题是,也许mantine将所有组件都转换为JS,而发布太多的JS使其变得动态,因此所有的转换都是如此
如果使用mantine组件导致了问题,我准备转向原生HTML组件,但我需要确定是否是Mantine导致了问题。
请帮助找出究竟是什么原因导致了高CLS的高内容转移,以及如何改善/防止内容转移。

qojgxg4l

qojgxg4l1#

我能想到的一个主要问题是,也许mantine将所有组件都转换为JS,而发布太多的JS使其变得动态,因此所有的转换都是如此
这就是问题所在HTML和CSS总是比JavaScript快。由于您的Mantime组件依赖于JavaScript,您的HTML和CSS首先加载,导致未样式化的内容 Flink 。
1.最好的方法是切换到原生HTML,但这非常困难。
1.另一个很好的方法是使用像Radix UIBase UI这样的无头UI库。大多数组件不需要JavaScript,并且已经遵循WAI-ARIA可访问性标准。您仍然需要手动定义CSS样式。
1.但是,最简单的方法是在项目的根目录中创建一个loading.tsx文件,以减少CLS。这里是docs for that
最后,这里有一篇关于reduce CLS的一般提示的好文章。

ygya80vv

ygya80vv2#

要减少Next.js站点中的累积布局偏移(CLS),您可以应用以下优化:
1.设置显式维度:确保所有元素都具有明确的宽度和高度值,以防止布局偏移。在您的代码中,将尺寸应用于 Package 标头的Container组件。

<Container pos='relative' mb='2rem' style={{ width: '100%', height: '100px' }}>
  {/* ... */}
</Container>

字符串
1.预加载字体:如果您使用的是自定义字体,请在HTML的<head>部分添加preload链接,以提前加载字体。

<head>
  {/* ... */}
  <link rel="preload" href="/path/to/font.woff2" as="font" type="font/woff2" crossorigin="anonymous" />
  {/* ... */}
</head>


1.优化镜像加载:确保图像针对Web进行了优化,并使用现代图像格式(如WebP)来减小其大小。此外,对图像实现延迟加载,以推迟其加载,直到它们接近视口。您可以使用像react-lazyload这样的库来实现这一点。
1.延迟非关键JavaScript:将非关键JavaScript移动到<body>标记的末尾,或使用defer属性延迟其执行。这确保了在JavaScript执行之前呈现基本内容,减少了布局变化的机会。
1.最小化第三方脚本:限制第三方脚本的数量,只包括那些必不可少的。第三方脚本可能会引入意外的布局变化并影响性能。
1.避免在改变布局的属性上进行CSS转换:在将CSS过渡或动画应用于影响布局的属性(如宽度或高度)时要小心。如果需要设置这些属性的动画,请考虑设置不透明度或变换的动画。
1.使用Next.js Image组件:Next.js提供了一个Image组件,可以自动优化图像并处理响应式图像加载。用Image组件替换常规的<img>标记,以更好地优化图像并减少CLS。
1.保证图片尺寸明确:博客页面上的许多图像没有明确的尺寸设置。这可能会导致加载图像时布局发生变化。要解决这个问题,请将widthheight属性添加到<img>标记中,或者使用Next.js Image组件,并定义widthheight属性。
1.优化字体加载:考虑在CSS中使用font-display属性来控制字体在加载过程中的显示方式。通过设置font-display: swap,您可以确保在加载自定义字体时文本内容保持可见,从而最大限度地减少字体加载引起的布局变化。
1.压缩CSS和JavaScript:通过缩小CSS和JavaScript文件来优化它们,以减小它们的文件大小。较小的文件加载速度更快,用户体验更流畅。
1.确保平滑过渡:如果您使用的是过渡或动画,请确保它们是平滑的,并且不会导致突然的偏移或抖动。检查正在设置动画的所有布局更改属性,并确保它们具有适当的缓动和持续时间。
1.减少渲染阻塞资源:使用Google PageSpeed Insights或Lighthouse等工具分析您的网站,以识别任何渲染阻止资源。尽量减少CSS和JavaScript文件的数量,并考虑异步加载或代码拆分,以提高初始渲染速度。
通过应用这些优化,您应该能够减少CLS并提高Next.js站点的性能。请记住使用Lighthouse或Web Vitals等工具来衡量影响,以确保您的CLS改进有效。

相关问题