WP Front Door

Trim WordPress page weight: scripts, styles and plugins

Most of a WordPress page's weight is plugins loading files on pages that do not use them.

Written by . Updated . One of the page weight guides.

The thresholds

  • HTML over 150 KB is a warning, over 400 KB a problem.
  • More than 5 render-blocking scripts in the head is a warning, more than 10 a problem. Scripts with defer, async or type="module" are not counted.
  • More than 8 stylesheets is a warning, more than 15 a problem.
  • More than 4 outside hosts serving scripts is a warning, more than 8 a problem.
  • More than 20 plugins loading files on the page is a warning.
  • Images without width and height, the emoji script and jQuery Migrate are noted, and more than 5 undimensioned images becomes a warning.

Scripts in the head

A plain <script src> in the head stops the page drawing until the file has downloaded and run. Since WordPress 6.3 a script can ask to be deferred when it is registered:

PHP
wp_enqueue_script(
	'my-script',
	get_theme_file_uri( 'js/my-script.js' ),
	array(),
	'1.0',
	array( 'strategy' => 'defer', 'in_footer' => true )
);

For plugin scripts you cannot edit, a performance plugin's defer setting does the same job. Test the page afterwards: a script that others depend on must still load before them.

Stylesheets

Each stylesheet in the head blocks rendering. Many belong to plugins that enqueue on every page, like a form plugin whose form is only on the contact page. Find the handles in Query Monitor's Styles panel, then remove them where they are not used:

PHP
add_action( 'wp_enqueue_scripts', function () {
	if ( ! is_page( 'contact' ) ) {
		wp_dequeue_style( 'some-plugin-style' );
		wp_dequeue_script( 'some-plugin-script' );
	}
}, 100 );

Images without width and height

Without dimensions the browser does not know how much room to leave, so the text jumps as each image arrives. WordPress adds width and height to images in post content. Theme templates that print <img> by hand are the usual gap; wp_get_attachment_image() writes the dimensions for you.

The emoji script

Browsers draw emoji themselves. The script WordPress adds to support very old ones can go:

PHP
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_enqueue_scripts', 'wp_enqueue_emoji_styles' );

jQuery Migrate

A compatibility layer for code written against old jQuery. If it loads, something on the site may still need it. With it loaded, the browser console shows JQMIGRATE warnings naming the old calls; when a full click through the site shows none, remove it on the front end:

PHP
add_action( 'wp_default_scripts', function ( $scripts ) {
	if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) {
		$jquery       = $scripts->registered['jquery'];
		$jquery->deps = array_diff( $jquery->deps, array( 'jquery-migrate' ) );
	}
} );

Third-party hosts

Each outside host costs a DNS lookup and a new connection before its file even starts. Tag managers add more hosts after the page loads. Keep the ones that earn their place and remove the ones left from old campaigns.

A heavy HTML document

Large inline CSS from page builders, inline SVG icons repeated on every card, and big blocks of JSON printed into the page are the usual causes. Move shared CSS into cached files and use an SVG sprite or icon files.

Check the fix

Rerun the check. Then open the page in your browser's developer tools, Network panel, with the cache disabled, and compare the number of requests and the transferred size with before.

Check a site for this

A domain or a full address. Only public pages are fetched, the way a browser would.