amp-wp icon indicating copy to clipboard operation
amp-wp copied to clipboard

Could tree shaking remove unused CSS at-rules such as @keyframes and @font-face?

Open nickcernis opened this issue 4 years ago • 4 comments

Feature description

Could AMP-WP CSS optimization be extended to strip unused at-rules?

Why this would be useful

AMP-WP does not appear to strip @-webkit-keyframes, @keyframes, and @font-face at-rules from the widely used Font Awesome stylesheet in the following scenario:

  • A WordPress plugin bundles the FontAwesome icon CSS.
  • No icons are used on the page.
  • The plugin still enqueues the Font Awesome stylesheet even if no icons are in use.

Current behavior

With the Atomic Blocks plugin active but no icon blocks on a page, I see this:

The style[amp-custom] element is populated with:

2819 B (12%): link#atomic-blocks-fontawesome-css[rel=stylesheet][href=http://dev.test/wp-
content/plugins/atomic-blocks/dist/assets/fontawesome/css/all.css?ver=1578585773][media=all]
…

And this FontAwesome CSS at the top of amp-custom:

@-webkit-keyframes fa-spin {
	0% {
		-webkit-transform: rotate(0deg);
		transform: rotate(0deg)
	}
	100% {
		-webkit-transform: rotate(360deg);
		transform: rotate(360deg)
	}
}

@keyframes fa-spin {
	0% {
		-webkit-transform: rotate(0deg);
		transform: rotate(0deg)
	}
	100% {
		-webkit-transform: rotate(360deg);
		transform: rotate(360deg)
	}
}

@font-face {
	font-family: "Font Awesome 5 Brands";
	font-style: normal;
	font-weight: normal;
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.eot");
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.eot#iefix") format("embedded-opentype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.woff2") format("woff2"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.woff") format("woff"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.ttf") format("truetype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-brands-400.svg#fontawesome") format("svg")
}

@font-face {
	font-family: "Font Awesome 5 Free";
	font-style: normal;
	font-weight: 400;
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.eot");
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.eot#iefix") format("embedded-opentype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.woff2") format("woff2"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.woff") format("woff"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.ttf") format("truetype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-regular-400.svg#fontawesome") format("svg")
}

@font-face {
	font-family: "Font Awesome 5 Free";
	font-style: normal;
	font-weight: 900;
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.eot");
	src: url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.eot#iefix") format("embedded-opentype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.woff2") format("woff2"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.woff") format("woff"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.ttf") format("truetype"), url("http://dev.test/wp-content/plugins/atomic-blocks/dist/assets/fontawesome/webfonts/fa-solid-900.svg#fontawesome") format("svg")
}

None of this CSS is required as Font Awesome is not being used on the page.

Desired behavior

It would be helpful to remove the 2819 bytes if it's not in use. On block-heavy sites with long homepages or landing pages, I've seen that 3kB can put a theme over the 50kB limit.

To reproduce

  1. Activate Twenty Twenty.
  2. Deactivate all plugins except AMP.
  3. Install and activate Atomic Blocks.
  4. You'll see the above mentioned subset of the FontAwesome stylesheet in amp-custom.

Other solutions

WordPress plugins should not enqueue stylesheets if they don't intend to use those styles on a page, which would fix this issue. However, this practice is not widely followed by WordPress developers and conditional enqueues are not always desirable.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

Implementation brief

QA testing instructions

Demo

Changelog entry

nickcernis avatar Jan 13 '20 17:01 nickcernis

Thanks for opening the issue.

In regards to the keyframes, this issue would be resolved by moving them all to the style[amp-keyframes] element. See #1626. The alternative would be to also try to keep track of whether a given animation name is referenced on the page.

In regards to @font-face, the only way to address that would be indeed to keep track of whether a given font-family is used on the page, and if so, retain the @font-face.

Alternatively, I wonder why Font Awesome is being included on the page by Atomic Blocks if it is not being used? The most effective way to reduce the amount of CSS on the page would be to prevent it from being added in the first place.

westonruter avatar Jan 13 '20 17:01 westonruter

The most effective way to reduce the amount of CSS on the page would be to prevent it from being added in the first place.

Agreed (and mentioned in “other solutions” above). There is an open issue in their repo to enqueue it more effectively (and we've talked about potentially enqueing it conditionally): https://github.com/studiopress/atomic-blocks/issues/127.

Thanks for linking to https://github.com/ampproject/amp-wp/issues/1626 — I'd searched but not seen that one.

nickcernis avatar Jan 13 '20 18:01 nickcernis

To close the loop on this, in https://github.com/studiopress/atomic-blocks/pull/294 the Font Awesome stylesheet is only printed to the page the first time that it is needed by a block. This is going to be the best practice as it will improve performance for non-AMP pages as well.

Eventually we could also explore detecting usage of keyframes and fonts in the stylesheet, and strip them if they are not being used on the page.

westonruter avatar Jan 17 '20 00:01 westonruter

There's still an opportunity here to reduce CSS. We can remove unused @font-family and unused @keyframes. It's not a high priority, but it's still an opportunity.

westonruter avatar Apr 01 '20 01:04 westonruter