Performance budget for Next.js

Performance budget for Next.js

How to avoid the performance decrease in your application

When you start to improve the performance in any application, is difficult to validate this values, because new features is adding constantly. If you don't have a validation to check the current performance very often, the value is decrease, similar when you improve the accessibility, one month later the accessibility decrease.

How to validate the performance constantly

The first step is create a performance budget, is a way to prevent the application decrease the performance, it can apply to javascript, images, css, metrics of core web vitals (LCP, FID, CLS)

Libraries

Libraries for this performance budget

Adding the performance budget

  1. Create an example app using npx create-next-app basic  
  2. Install  npm i bundlesize @next/bundle-analyzer @lhci/cli --D

If you have a current application skip the step 1)

Bundle Analyzer

The first to configure is the bundle-analyzer , you need to apply the current plugin in your next.config.js file

const { ANALYZE } = process.env


const withBundleAnalyzer = require("@next/bundle-analyzer")({
     enabled: ANALYZE === "true",
});


module.exports = withBundleAnalyzer({});

This allows to apply the current plugin if the environment variable ANALYZE is true

In your package.json add the new command to execute

"analyze": "ANALYZE=true next build"

To check if is correct run the command npm run analyze

No alt text provided for this image

This plugin allows to check the current dependencies for both parts (client | server) the most important is client-side because is the code shipping to the browser, validate if you have a huge dependency.

For easy validation I recommend using https://bundlephobia.com/ to get the current size of any library, and validate if the current library has three-shaking support

Bundle Size

The second is configure the bundlesize it allows to validate the current bundle

Create a file bundlesize.config.json in the root of the project to define the max size of the current bundles / chunks

Basic configuration

  • path: The current path where is the file
  • maxSize: The maximum size to avoid the bundle increase
  • compression: The current compression brotli o gzip for the exact size for production
{ 
 "files": [
    {
      "path": ".next/static/**/main-*.js",
      "maxSize": "30 kB",
      "compression": "brotli"
    },
    {
      "path": ".next/static/chunks/pages/my-page-*.js",
      "maxSize": "8 kB",
      "compression": "brotli"
    },
    {
      "path": ".next/static/chunks/pages/_app-*.js",
      "maxSize": "65 kB",
      "compression": "brotli"
    }
  ]
}

Change the path for your pages, using the * it allows to apply in dynamic content with hash

In your package.json add the new command to execute

"bundle-check": "next build && bundlesize"

To check if is correct run the command npm run bundle-check

The validation is passed

Lighthouse

The last is configure lighthouse, is a tool to improve the performance in your web apps, it has an option to apply a custom budget to check metrics like performance, accessibility, best practices, seo

Create a file config file called lighthouserc.js at the root of your repo controls the options for Lighthouse CI.

This config is oriented for web-apps the results is uploaded temporal in a public storage

// Budget to check the mininum in each step
// 80% minimum performance

const PERFORMANCE = 0.8; 
const ACCESSIBILITY = 0.8; 
const BEST_PRACTICES = 0.8;
const SEO = 0.8;


// Extra headers
const headers = {};


// URLs to check
const URL = process.env.URL;


module.exports = {
  ci: {
    collect: {
      url: [URL],
    },
    settings: {
      maxWaitForFcp: 15 * 1000,
      maxWaitForLoad: 35 * 1000,
      skipAudits: ["uses-http2"],
      options: {
        networkQuietThresholdMs: 10 * 1000,
      },
      onlyCategories: ["performance", "accessibility", "best-practices", "seo"],
      chromeFlags: "--no-sandbox",
      extraHeaders: JSON.stringify(headers),
    },
    assert: {
      assertions: {
        "categories:performance": [
          "error",
          { minScore: PERFORMANCE, aggregationMethod: "median-run" },
        ],
        "categories:accessibility": [
          "error",
          {
            minScore: ACCESSIBILITY,
            aggregationMethod: "pessimistic",
          },
        ],
        "categories:best-practices": [
          "error",
          {
            minScore: BEST_PRACTICES,
            aggregationMethod: "pessimistic",
          },
        ],
        "categories:seo": [
          "error",
          { minScore: SEO, aggregationMethod: "pessimistic" },
        ],
      },
    },
    upload: {
      target: "temporary-public-storage",
    },
  },
};

In your package.json add the new command to execute 

"lighthouse":"URL='https://localhost:3000/my-page' lhci autorun"

To check if is correct run the server and the command npm run lighthouse

No alt text provided for this image
No alt text provided for this image

The current example is hosted in this repository

Final

The last step is integrate this commands in your CI pipeline when you create a pull request validate this steps, depends if your using github actions o CI internal in your company




要查看或添加评论,请登录

社区洞察

其他会员也浏览了