三、前端性能优化:首屏加载时间LCP降低77%
嗯,用户让我总结一下这篇文章的内容,控制在100字以内,而且不需要特定的开头。首先,我得仔细阅读文章内容,找出主要的信息。 文章主要讲的是优化网页首屏加载时间。作者提到了几个关键指标,比如FCP、DCL和LCP,这些指标都显示加载时间过长。然后,作者详细介绍了两个优化方法:SVG动态导入和WebP格式转换。 SVG动态导入之前是全量加载,导致首屏时间增加。优化后改为按需加载,只加载需要的SVG图标,这样LCP从13秒多降到了5.8秒左右。另一个优化是将大于5KB的图片转换为WebP格式,并且保留原格式作为降级方案。这样可以减少图片体积,提升加载速度。 总结下来,文章主要讲述了通过这两种技术手段有效缩短了网页的首屏加载时间。所以,在总结的时候需要涵盖这两个优化点以及它们带来的效果提升。 接下来要控制在100字以内,所以得简洁明了。确保包括优化目标、方法和结果。避免使用复杂的术语,让读者一目了然。 最后检查一下是否符合用户的要求:中文、100字以内、直接描述内容。没问题的话就可以提交了。 </think> 文章介绍了一种优化网页首屏加载时间的方法,通过动态导入SVG图标和将大于5KB的图片转换为WebP格式来提升性能。动态导入SVG避免全量加载未使用的图标,而WebP格式则减少了图片体积。这些优化措施显著降低了页面的首屏加载时间。 2025-12-18 08:16:18 Author: www.freebuf.com(查看原文) 阅读量:4 收藏

freeBuf

主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

阶段三:首屏加载时间优化

1764144184_6926b4383da861b6ebe21.png!small?1764144183846

当前(阶段二优化未应用)项目的项目首屏加载时间,加载时间较长:

  • FCP (首次内容绘制):13.76s(正常应 < 3s)
  • DCL (DOMContentLoaded): 13.68s(正常应 < 4s)
  • LCP (最大内容绘制): 13.76s(正常应 < 2.5s)
  • L(资源完全加载): 18.21s(正常应 < 8s)

SVG动态导入优化

将 SvgIcon 组件从全量导入改为动态导入,不在模块加载时就导入所有SVG文件,影响首屏加载时间,实现按需加载SVG图标。

优化前:

const importAll = (requireContext) =>
  requireContext.keys().forEach(requireContext)
try {
  importAll(require.context('xxx/assets/svg', true, /\.svg$/))
} catch (error) {}

export const SvgIcon = ({ name, ...props }) => {
  return (
    <svg {...props}>
      <use href={`#${name}`} />
    </svg>
  )
}
  • 模块加载时就导入所有SVG文件
  • 即使不使用的SVG也会被加载
  • 初始bundle包含所有SVG
  • 无法按需加载

优化后:

const loadSvgIcon = (iconName: string): void => {
  if (loadedIcons.has(iconName)) {
    return // 已加载,直接返回
  }
  // 动态导入指定的SVG文件
  svgContextCache(path)
  loadedIcons.add(iconName)
}

export const SvgIcon = ({ name, preload = true, ...props }) => {
  useEffect(() => {
    // 按需加载图标
    loadSvgIcon(name)
  }, [name, preload])
  
  return (
    <svg {...props}>
      <use href={`#${name}`} />
    </svg>
  )
}
  • 按需加载,只加载使用的SVG
  • 避免重复导入

这个问题是导致LCP过高的主要原因,每次都会先拉190多张图片,无论当前页面是否使用,按需加载后LCP降至5.8s左右。

WebP转换(> 5KB)

我这边是增加 generator 来做webp的转换,参考包括阶段二上文的配置,我的图片处理规则是:

  • < 2KB:内联为 Base64
  • 2KB - 5KB:使用 Sharp 压缩优化
  • > 5KB:转换为 WebP 格式
getImageMinimizerPlugin: (IS_PRO) => {
  if (!IS_PRO) {
    return null;
  }

  return new ImageMinimizerPlugin({
    deleteOriginalAssets: false,
    test: /\.(png|jpg|jpeg)$/i,
    // 错误处理:遇到错误时只警告,不中断构建
    severityError: 'warning',
    minimizer: {
      implementation: ImageMinimizerPlugin.sharpMinify,
      filter: (source, filename) => {
        try {
          return source.length < 5 * 1024; // 5KB
        } catch (error) {
          console.error('[Minimizer Filter] 错误:', error.message, '文件:', filename);
          return false;
        }
      },
      options: {
        encodeOptions: {
          // PNG 压缩配置
          png: {
            quality: 80,
            compressionLevel: 9,
            palette: true,
          },
          // JPEG 压缩配置
          jpeg: {
            quality: 80,
            mozjpeg: false,
          },
        },
      },
    },
    generator: [
                {
                    type: 'asset',
                    implementation: ImageMinimizerPlugin.sharpGenerate,
                    // 只转换大于5kb的图片为webp
                    filter: (source, filename) => {
                        try {
                            return source.length > 5 * 1024; // 5KB
                        } catch (error) {
                            console.error('[WebP Filter] 错误:', error.message, '文件:', filename);
                            return false;
                        }
                    },
                    options: {
                        encodeOptions: {
                            webp: {
                                quality: 80,
                                lossless: false,
                            },
                        },
                    },
                    filename: 'assets/images/[name][ext].webp',
                }
            ],
  });
},

/**
 * 获取优化的图片loader配置
 */
getImageLoaders: () => {
  return [
    {
      test: /\.(png|jpg|jpeg)$/,
      type: 'asset/resource',
      exclude: /node_modules/,
      parser: {
        dataUrlCondition: {
          maxSize: 2 * 1024, 
        },
      },
      generator: {
        filename: 'assets/images/[name].[contenthash:8][ext]',
      },
    },
    {
      test: /\.svg$/,
      exclude: /node_modules/,
      use: [
        {
          loader: 'svg-sprite-loader',
          options: {
            symbolId: '[name]',
            extract: false,
          },
        },
        {
          loader: 'svgo-loader',
          options: {
            plugins: [
              { name: 'removeViewBox', active: false },
              { name: 'removeDimensions', active: true },
              { name: 'removeUselessStrokeAndFill', active: true },
              'moveElemsAttrsToGroup',
              'convertPathData',
            ],
          },
        },
      ],
    },
  ];
},

我这边保留了原类型文件做降级方案。如要生成不用尺寸的图片,或者想全部图片转webp,配置简单一点,可以使用 responsive-loader+sharp,自动为每个PNG/JPG图片生成对应的WebP版本:

{
                test: /\.(png|jpg|jpeg)$/,
                // include: /[\\/]assets[\\/]imges[\\/]/i,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'responsive-loader',
                        options: {
                       

已在FreeBuf发表 0 篇文章

本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)


文章来源: https://www.freebuf.com/articles/others-articles/462684.html
如有侵权请联系:admin#unsafe.sh