Skip to content
This repository has been archived by the owner on Jul 27, 2024. It is now read-only.

Commit

Permalink
Add AssetPreload check (#605)
Browse files Browse the repository at this point in the history
  • Loading branch information
krzksz authored Jul 14, 2022
1 parent 0a1e2d5 commit a6448ea
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
4 changes: 4 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ ParserBlockingScriptTag:
enabled: true
ignore: []

AssetPreload:
enabled: true
ignore: []

AssetSizeJavaScript:
enabled: false
threshold_in_bytes: 10_000
Expand Down
60 changes: 60 additions & 0 deletions docs/checks/asset_preload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Prevent Manual Preloading of Assets (`AssetPreload`)

_Version THEME_CHECK_VERSION+_

Preloading can be a useful way of making sure that critical assets are downloaded by the browser as soon as possible for better rendering performance.

Liquid provides multiple filters to [preload key resources][preload_key_resources] so they can be converted into `Link` headers automatically. This enables them to be discovered even faster, especially when combined with Early Hints that Shopify supports.

## Examples

The following examples contain code snippets that either fail or pass this check.

### ✗ Fail

```liquid
<link href="{{ 'script.js' | asset_url }}" rel="preload" as="script">
<link href="{{ 'style.css' | asset_url }}" rel="preload" as="style">
<link href="{{ 'image.png' | asset_url }}" rel="preload" as="image">
```

### &#x2713; Pass

```liquid
{{ 'script.js' | asset_url | preload_tag: as: 'script' }}
{{ 'style.css' | asset_url | stylesheet_tag: preload: true }}
{{
product.featured_image
| image_url: width: 600
| image_tag: preload: true
}}
```

## Options

The following example contains the default configuration for this check:

```yaml
AssetPreload:
enabled: true
severity: suggestion
```
| Parameter | Description |
| --- | --- |
| enabled | Whether the check is enabled. |
| severity | The [severity](https://shopify.dev/themes/tools/theme-check/configuration#check-severity) of the check. |
## Disabling this check
It's safe to disable this rule. You may want to do it when trying to preload assets from external domain and it is not possible
to move them to Shopify because they change frequently or are dynamically generated.
## Resources
- [Rule source][codesource]
- [Documentation source][docsource]
[codesource]: /lib/theme_check/checks/asset_preload.rb
[docsource]: /docs/checks/asset_preload.md
[preload_key_resources]: https://shopify.dev/themes/best-practices/performance#use-resource-hints-to-preload-key-resources
20 changes: 20 additions & 0 deletions lib/theme_check/checks/asset_preload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module ThemeCheck
class AssetPreload < HtmlCheck
severity :suggestion
categories :html, :performance
doc docs_url(__FILE__)

def on_link(node)
return if node.attributes["rel"]&.downcase != "preload"
case node.attributes["as"]&.downcase
when "style"
add_offense("For better performance, prefer using the preload argument of the stylesheet_tag filter", node: node)
when "image"
add_offense("For better performance, prefer using the preload argument of the image_tag filter", node: node)
else
add_offense("For better performance, prefer using the preload_tag filter", node: node)
end
end
end
end
51 changes: 51 additions & 0 deletions test/checks/asset_preload_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true
require "test_helper"

class AssetPreloadTest < Minitest::Test
def test_no_offense_with_link_element
offenses = analyze_theme(
ThemeCheck::AssetPreload.new,
"templates/index.liquid" => <<~END,
<link href="a.css" rel="stylesheet">
<link href="b.com" rel="preconnect">
END
)
assert_offenses("", offenses)
end

def test_reports_stylesheet_preloading
offenses = analyze_theme(
ThemeCheck::AssetPreload.new,
"templates/index.liquid" => <<~END,
<link href="a.css" rel="preload" as="style">
END
)
assert_offenses(<<~END, offenses)
For better performance, prefer using the preload argument of the stylesheet_tag filter at templates/index.liquid:1
END
end

def test_reports_image_preloading
offenses = analyze_theme(
ThemeCheck::AssetPreload.new,
"templates/index.liquid" => <<~END,
<link href="a.png" rel="preload" as="image">
END
)
assert_offenses(<<~END, offenses)
For better performance, prefer using the preload argument of the image_tag filter at templates/index.liquid:1
END
end

def test_reports_general_preloading
offenses = analyze_theme(
ThemeCheck::AssetPreload.new,
"templates/index.liquid" => <<~END,
<link href="a..js" rel="preload" as="script">
END
)
assert_offenses(<<~END, offenses)
For better performance, prefer using the preload_tag filter at templates/index.liquid:1
END
end
end

0 comments on commit a6448ea

Please sign in to comment.