Class: ThemeCheck::AssetSizeJavaScript

Inherits:
LiquidCheck show all
Includes:
RegexHelpers
Defined in:
lib/theme_check/checks/asset_size_javascript.rb

Overview

Reports errors when trying to use too much JavaScript on page load Encourages the use of the Import on Interaction pattern [1]. [1]: addyosmani.com/blog/import-on-interaction/

Defined Under Namespace

Classes: Script

Constant Summary collapse

SCRIPT_TAG_SRC =
%r{
  <script
    [^>]+                              # any non closing tag character
    src=                               # src attribute start
    (?<src>#{QUOTED_LIQUID_ATTRIBUTE}) # src attribute value (may contain liquid)
    [^>]*                              # any non closing character till the end
  >
}omix

Constants inherited from LiquidCheck

LiquidCheck::ATTR, LiquidCheck::HTML_ATTRIBUTE, LiquidCheck::HTML_ATTRIBUTES, LiquidCheck::QUOTED_LIQUID_ATTRIBUTE, LiquidCheck::START_OR_END_QUOTE, LiquidCheck::TAG, LiquidCheck::VARIABLE

Constants inherited from Check

Check::CATEGORIES, Check::SEVERITIES

Instance Attribute Summary collapse

Attributes inherited from Check

#offenses, #options, #theme

Instance Method Summary collapse

Methods included from RegexHelpers

#matches

Methods inherited from LiquidCheck

#add_offense

Methods included from ChecksTracking

#inherited

Methods included from ParsingHelpers

#outside_of_strings

Methods inherited from Check

all, can_disable, #can_disable?, categories, #categories, category, #code_name, #doc, doc, docs_url, #ignore!, #ignored?, #severity, severity, #to_s, #unignore!

Methods included from JsonHelpers

#format_json_parse_error

Constructor Details

#initialize(threshold_in_bytes: 10000) ⇒ AssetSizeJavaScript

Returns a new instance of AssetSizeJavaScript.



25
26
27
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 25

def initialize(threshold_in_bytes: 10000)
  @threshold_in_bytes = threshold_in_bytes
end

Instance Attribute Details

#threshold_in_bytesObject (readonly)

Returns the value of attribute threshold_in_bytes.



23
24
25
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 23

def threshold_in_bytes
  @threshold_in_bytes
end

Instance Method Details

#on_document(node) ⇒ Object



29
30
31
32
33
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 29

def on_document(node)
  @node = node
  @source = node.template.source
  record_offenses
end

#record_offensesObject



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 35

def record_offenses
  scripts(@source).each do |script|
    file_size = src_to_file_size(script.src)
    next if file_size.nil?
    next if file_size <= threshold_in_bytes
    add_offense(
      "JavaScript on every page load exceding compressed size threshold (#{threshold_in_bytes} Bytes), consider using the import on interaction pattern.",
      node: @node,
      markup: script.src,
      line_number: @source[0...script.match.begin(:src)].count("\n") + 1
    )
  end
end

#scripts(source) ⇒ Object



49
50
51
52
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 49

def scripts(source)
  matches(source, SCRIPT_TAG_SRC)
    .map { |m| Script.new(m[:src].gsub(START_OR_END_QUOTE, ""), m) }
end

#src_to_file_size(src) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/theme_check/checks/asset_size_javascript.rb', line 54

def src_to_file_size(src)
  # We're kind of intentionally only looking at {{ 'asset' | asset_url }} or full urls in here.
  # More complicated liquid statements are not in scope.
  if src =~ /^#{VARIABLE}$/o && src =~ /asset_url/ && src =~ Liquid::QuotedString
    asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
    asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
    return if asset.nil?
    asset.gzipped_size
  elsif src =~ %r{^(https?:)?//}
    asset = RemoteAssetFile.from_src(src)
    asset.gzipped_size
  end
end