美文网首页
webpack插件在优化LCP指标上的运用

webpack插件在优化LCP指标上的运用

作者: 0月 | 来源:发表于2023-04-27 10:41 被阅读0次

前言

最近采用webpack5配置了一个项目脚手架。当项目开发完成后,采用lighthouse进行性能测试时发现有一张图片影响LCP评分,所以需要解决这个问题。

LCP

最大内容绘制 (LCP) 是核心 Web 指标中的一项指标,用于测量可视区域中最大内容元素变为可见的时间点。该项指标可用于确定页面主要内容在屏幕上完成渲染的时间点。

本项目经过实测发现以下问题:


/assets/top-8face.png

所以这个图片影响LCP需要优化,怎么做?这里给出了preload的建议,只要在html head标签内加上一句即可

  <link href="assets/top-8face.png" rel="preload" as="image">

至此完成了该项优化。

但是,事情可能没有那么简单,万一图片换了,top-[hash]变了呢?或者随着项目迭代,删除了这张图片,然后这个preload link很可能继续存在html里面,就会显得多余。万一影响LCP的不是图片,可以是p标签包裹的一大段文案或者是某个video、svg内嵌的image呢?万一项目是动态配置的多入口MPA呢?

所以此时虽然可以手动写上一句就解决当前的问题,但是为了可维护性,从工程化角度来看,更应该是用工程化的手段来解决此类问题。

先看看有没有现成的preload插件,找到一个vue官方维护的 @vue/preload-webpack-plugin, 但是这个插件默认把所有输出的资源都生成preload link,在输出资源比较多且没有开启http2时候,这其实是一种反向优化的手段。经过尝试配置和阅读它的源码,发现并不能满足我的需求,我只要一个preload link就行了,所以自己写一个吧。

webpack插件实现新增preload link插入到html文件

梳理一下本插件要做的事情:
我们希望拿到名叫top-[hash].png的图片,有则组装一个preload link插入到html里面,没有则啥也不做

在我的另外一篇文章【webpack进阶系列】plugin的原理探究 介绍过了插件原理与应用,参考官网示例现在我们可以直接在processAssets钩子里面配合stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE拿到所有资源assets,找出LCP图片和html文件,组装preload link插入到html文件,然后生成新的html。
代码如下:

preload-lcp-img-webpack-plugin.js

/**
 * 根据lighthouse的建议,有一张图片:top-[hash].png影响LCP, 所以需要预加载这张影响LCP的图片,此插件仅适用此场景
 */
const defaultOptions = {
  htmlFile: 'index.html'
}
class PreloadLCPImgWebpackPlugin {
  constructor(options = {}) {
    this.options = { ...defaultOptions, ...options }
  }

  apply(compiler) {
    const pluginName = 'PreloadLCPImgWebpackPlugin'
    const { webpack } = compiler
    const { Compilation } = webpack
    const { RawSource } = webpack.sources

    compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
      // 绑定到资源处理流水线(assets processing pipeline)
      compilation.hooks.processAssets.tap(
        {
          name: pluginName,
           // 用某个靠后的资源处理阶段, 确保所有资源已被插件添加到 compilation
          stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
        },
        (assets) => {
          const lcpImg = Object.keys(assets)
            .filter(filename => /.png$/i.test(filename)) // 图片
            .find((filename) => {
              const arr = filename.split('/')
              const name = arr[arr.length - 1]
              return /^top/.test(name) // top-[hash].png就是影响LCP的图片
            })

          if (!lcpImg) return

          const webpackPublicPath = compilation.outputOptions.publicPath
          // webpack 5 set publicPath default value 'auto'
          const publicPath = webpackPublicPath.trim() !== '' && webpackPublicPath !== 'auto' ? webpackPublicPath : ''

          const html = assets[this.options.htmlFile]._value
          const preloadLink = `<link href="${publicPath}${lcpImg}" rel="preload" as="image">`
          const newHtml = html.replace('</head>', `${preloadLink}</head>`)

          delete assets[this.options.htmlFile] // 删除,下面再重新生成
          compilation.emitAsset(
            this.options.htmlFile,
            new RawSource(newHtml)
          )
        }
      )
    })
  }
}

module.exports = PreloadLCPImgWebpackPlugin

在webpack.config.js中production环境使用插件

const PreloadLCPImgWebpackPlugin = require('./webpack-plugins/preload-lcp-img-webpack-plugin')
// ...省略其他代码
if(isProduction) {
  config.plugins.push(
    new PreloadLCPImgWebpackPlugin(), // 预加载LCP图片
  )
}

效果


优化后的LCP.png 没有LCP建议了.png

总结

webpack插件可以通过注册webpack的compiler、compilation实例的hook在特定的时机去【增加、删除、改变】内部的资源信息,最终可能影响构建输出。要写插件不难,难的是webapck里面几百个hook该用哪些hook,什么时机去做,能做什么事情,这个过程只能多参考其他插件的写法或者阅读源码。

相关文章

  • webpack plugins插件

    本节我们来学习 webpack 中的插件(plugins),插件可以让 webpack 能够执行更多任务,从优化和...

  • webpack plugins插件

    本节我们来学习 webpack 中的插件(plugins),插件可以让 webpack 能够执行更多任务,从优化和...

  • Webpack4-Plugins

    插件(Plugins) 插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack ...

  • vue项目中配置全局常量

    使用webpack插件webpack.DefinePlugin设置全局常量,可减少某些操作。 在webpack插件...

  • Vue环境下tinymce简易教程(优化图片上传+powerpa

    环境 VUE webpack tinymce4 额外插件 用于优化本地图片上传的第三方插件:tinymce-ima...

  • webpack打包优化

    记一次react项目优化的过程优化前,用uglifyjs-webpack-plugin插件压缩js后得到的大小,实...

  • 前端优化-LCP

    什么是LCP LCP是最大内容绘制的简称。LCP是用来测量感知加载速度。感知加载速度是以用户为中心的重要指标。因为...

  • UglifyJS Webpack Plugin

    UglifyJS Webpack Plugin插件用来缩小(压缩优化)js文件,至少需要Node v6.9.0和W...

  • UglifyJs打包报错:Unexpected token: k

    UglifyJS Webpack Plugin插件用来缩小(压缩优化)js文件,至少需要Node v6.9.0和W...

  • 缓存优化

    缓存优化的基本原理 Webpack 4 内置了压缩插件 TerserWebpackPlugin,且默认开启了缓存参...

网友评论

      本文标题:webpack插件在优化LCP指标上的运用

      本文链接:https://www.haomeiwen.com/subject/ujdmjdtx.html