Module: RailsOnboarding::CdnSupport

Extended by:
ActiveSupport::Concern
Defined in:
lib/rails_onboarding/cdn_support.rb

Overview

CDN Support module for serving assets from a CDN

This module provides helpers and configuration for serving onboarding assets (JavaScript, CSS, images) from a CDN to improve performance through better caching and geographic distribution

Class Method Summary collapse

Class Method Details

.cdn_asset_url(asset_path, asset_type: :stylesheet) ⇒ String

Get asset URL with CDN support

Parameters:

  • asset_path (String)

    The asset path (e.g., 'rails_onboarding/application.css')

  • asset_type (Symbol) (defaults to: :stylesheet)

    Asset type (:stylesheet, :javascript, :image)

Returns:

  • (String)

    Full URL to the asset



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rails_onboarding/cdn_support.rb', line 47

def self.cdn_asset_url(asset_path, asset_type: :stylesheet)
  if cdn_enabled?
    case asset_type
    when :stylesheet
      "#{cdn_host}/assets/#{asset_path}"
    when :javascript
      "#{cdn_host}/assets/#{asset_path}"
    when :image
      "#{cdn_host}/assets/#{asset_path}"
    else
      "#{cdn_host}/assets/#{asset_path}"
    end
  else
    # Fall back to local asset path
    "/assets/#{asset_path}"
  end
end

.cdn_cache_headers(max_age: 31_536_000) ⇒ Hash

Configure CDN headers for optimal caching

Parameters:

  • max_age (Integer) (defaults to: 31_536_000)

    Cache max age in seconds (default: 1 year)

Returns:

  • (Hash)

    Headers for CDN caching



187
188
189
190
191
192
193
# File 'lib/rails_onboarding/cdn_support.rb', line 187

def cdn_cache_headers(max_age: 31_536_000)
  {
    "Cache-Control" => "public, max-age=#{max_age}, immutable",
    "Expires" => max_age.seconds.from_now.httpdate,
    "Vary" => "Accept-Encoding"
  }
end

.cdn_enabled?Boolean

Check if CDN is enabled

Returns:

  • (Boolean)


38
39
40
# File 'lib/rails_onboarding/cdn_support.rb', line 38

def self.cdn_enabled?
  cdn_host.present? && !Rails.env.development?
end

.cdn_hostString?

Get the CDN host URL

Returns:

  • (String, nil)

    CDN host URL or nil if not configured



17
18
19
20
21
22
23
24
25
26
# File 'lib/rails_onboarding/cdn_support.rb', line 17

def self.cdn_host
  @cdn_host ||= begin
    # Check Rails configuration first
    if defined?(Rails.application) && Rails.application.config.action_controller.asset_host
      Rails.application.config.action_controller.asset_host
    else
      ENV["RAILS_ONBOARDING_CDN_HOST"]
    end
  end
end

.cdn_host=(host) ⇒ Object

Set the CDN host URL

Parameters:

  • host (String)

    CDN host URL



31
32
33
# File 'lib/rails_onboarding/cdn_support.rb', line 31

def self.cdn_host=(host)
  @cdn_host = host
end

.cdn_resource_hintsString

Generate resource hints for DNS prefetch and preconnect

Returns:

  • (String)

    HTML meta tags for resource hints



163
164
165
166
167
168
169
170
171
172
# File 'lib/rails_onboarding/cdn_support.rb', line 163

def cdn_resource_hints
  return "" unless CdnSupport.cdn_enabled?

  cdn_host = ERB::Util.html_escape(CdnSupport.cdn_host)
  <<~HTML.html_safe
    <!-- DNS Prefetch and Preconnect for CDN -->
    <link rel="dns-prefetch" href="#{cdn_host}" />
    <link rel="preconnect" href="#{cdn_host}" crossorigin />
  HTML
end

.cdn_tag_attributes(attributes) ⇒ Object

Render tag attributes with every value HTML-escaped, so a CDN host or asset path containing a quote or angle bracket can't break out of the attribute it's placed in. Used in place of ActionView's tag helpers because these methods are also called as CdnSupport module functions, outside any view context where tag/content_tag would be available.



179
180
181
# File 'lib/rails_onboarding/cdn_support.rb', line 179

def cdn_tag_attributes(attributes)
  attributes.map { |key, value| "#{key}=\"#{ERB::Util.html_escape(value)}\"" }.join(" ")
end

.javascript_include_tag_with_cdn(asset_path, **options) ⇒ String

Helper method for JavaScript tags with CDN support

Parameters:

  • asset_path (String)

    Asset path

  • options (Hash)

    Additional options

Returns:

  • (String)

    HTML script tag



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rails_onboarding/cdn_support.rb', line 136

def javascript_include_tag_with_cdn(asset_path, **options)
  url = CdnSupport.versioned_asset_url(asset_path, asset_type: :javascript)

  preload = options.delete(:preload)
  defer = options.delete(:defer) { true } # Default to defer
  async = options.delete(:async)

  tag_options = {
    src: url,
    type: "text/javascript"
  }.merge(options)

  tag_options[:defer] = "defer" if defer && !async
  tag_options[:async] = "async" if async

  tags = [ "<script #{cdn_tag_attributes(tag_options)}></script>" ]

  if preload
    tags.unshift("<link #{cdn_tag_attributes(rel: 'preload', href: url, as: 'script')} />")
  end

  tags.join("\n").html_safe
end

.preload_assetsArray<Hash>

Preload critical onboarding assets

Returns:

  • (Array<Hash>)

    Array of asset preload hints



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rails_onboarding/cdn_support.rb', line 68

def self.preload_assets
  [
    {
      href: cdn_asset_url("rails_onboarding/application.css", asset_type: :stylesheet),
      as: "style",
      type: "text/css"
    },
    {
      href: cdn_asset_url("rails_onboarding/application.js", asset_type: :javascript),
      as: "script",
      type: "text/javascript"
    }
  ]
end

Helper method for view templates Generates link tags with CDN support and preload hints

Parameters:

  • asset_path (String)

    Asset path

  • options (Hash)

    Additional options

Returns:

  • (String)

    HTML link tag



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rails_onboarding/cdn_support.rb', line 109

def stylesheet_link_tag_with_cdn(asset_path, **options)
  url = CdnSupport.versioned_asset_url(asset_path, asset_type: :stylesheet)

  preload = options.delete(:preload)
  crossorigin = options.delete(:crossorigin)

  tag_options = {
    rel: "stylesheet",
    href: url
  }.merge(options)

  tag_options[:crossorigin] = crossorigin if crossorigin

  tags = [ "<link #{cdn_tag_attributes(tag_options)} />" ]

  if preload
    tags.unshift("<link #{cdn_tag_attributes(rel: 'preload', href: url, as: 'style')} />")
  end

  tags.join("\n").html_safe
end

.versioned_asset_url(asset_path, version: nil, asset_type: :stylesheet) ⇒ String

Generate cache-busting URL with versioning

Parameters:

  • asset_path (String)

    The asset path

  • version (String) (defaults to: nil)

    Asset version (defaults to gem version)

  • asset_type (Symbol) (defaults to: :stylesheet)

    Asset type (:stylesheet, :javascript, :image)

Returns:

  • (String)

    URL with version parameter



89
90
91
92
93
# File 'lib/rails_onboarding/cdn_support.rb', line 89

def self.versioned_asset_url(asset_path, version: nil, asset_type: :stylesheet)
  version ||= RailsOnboarding::VERSION
  url = cdn_asset_url(asset_path, asset_type: asset_type)
  "#{url}?v=#{version}"
end