PERF: Eager load Theme associations in Stylesheet Manager.

Before this change, calling `StyleSheet::Manager.stylesheet_details`
for the first time resulted in multiple queries to the database. This is
because the code was modelled in a way where each `Theme` was loaded
from the database one at a time.

This PR restructures the code such that it allows us to load all the
theme records in a single query. It also allows us to eager load the
required associations upfront. In order to achieve this, I removed the
support of loading multiple themes per request. It was initially added
to support user selectable theme components but the feature was never
completed and abandoned because it wasn't a feature that we thought was
worth building.
This commit is contained in:
Alan Guo Xiang Tan
2021-06-15 14:57:17 +08:00
parent 53dab8cf1e
commit 8e3691d537
35 changed files with 983 additions and 668 deletions

View File

@ -408,14 +408,19 @@ module ApplicationHelper
end
end
def theme_ids
def theme_id
if customization_disabled?
[nil]
nil
else
request.env[:resolved_theme_ids]
request.env[:resolved_theme_id]
end
end
def stylesheet_manager
return @stylesheet_manager if defined?(@stylesheet_manager)
@stylesheet_manager = Stylesheet::Manager.new(theme_id: theme_id)
end
def scheme_id
return @scheme_id if defined?(@scheme_id)
@ -424,12 +429,9 @@ module ApplicationHelper
return custom_user_scheme_id
end
return if theme_ids.blank?
return if theme_id.blank?
@scheme_id = Theme
.where(id: theme_ids.first)
.pluck(:color_scheme_id)
.first
@scheme_id = Theme.where(id: theme_id).pluck_first(:color_scheme_id)
end
def dark_scheme_id
@ -457,7 +459,7 @@ module ApplicationHelper
def theme_lookup(name)
Theme.lookup_field(
theme_ids,
theme_id,
mobile_view? ? :mobile : :desktop,
name,
skip_transformation: request.env[:skip_theme_ids_transformation].present?
@ -466,7 +468,7 @@ module ApplicationHelper
def theme_translations_lookup
Theme.lookup_field(
theme_ids,
theme_id,
:translations,
I18n.locale,
skip_transformation: request.env[:skip_theme_ids_transformation].present?
@ -475,7 +477,7 @@ module ApplicationHelper
def theme_js_lookup
Theme.lookup_field(
theme_ids,
theme_id,
:extra_js,
nil,
skip_transformation: request.env[:skip_theme_ids_transformation].present?
@ -483,22 +485,26 @@ module ApplicationHelper
end
def discourse_stylesheet_link_tag(name, opts = {})
if opts.key?(:theme_ids)
ids = opts[:theme_ids] unless customization_disabled?
else
ids = theme_ids
end
manager =
if opts.key?(:theme_id)
Stylesheet::Manager.new(
theme_id: customization_disabled? ? nil : opts[:theme_id]
)
else
stylesheet_manager
end
Stylesheet::Manager.stylesheet_link_tag(name, 'all', ids)
manager.stylesheet_link_tag(name, 'all')
end
def discourse_color_scheme_stylesheets
result = +""
result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(scheme_id, 'all', theme_ids)
result << stylesheet_manager.color_scheme_stylesheet_link_tag(scheme_id, 'all')
if dark_scheme_id != -1
result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)', theme_ids)
result << stylesheet_manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)')
end
result.html_safe
end
@ -525,7 +531,7 @@ module ApplicationHelper
asset_version: Discourse.assets_digest,
disable_custom_css: loading_admin?,
highlight_js_path: HighlightJs.path,
svg_sprite_path: SvgSprite.path(theme_ids),
svg_sprite_path: SvgSprite.path(theme_id),
enable_js_error_reporting: GlobalSetting.enable_js_error_reporting,
color_scheme_is_dark: dark_color_scheme?,
user_color_scheme_id: scheme_id,
@ -533,7 +539,7 @@ module ApplicationHelper
}
if Rails.env.development?
setup_data[:svg_icon_list] = SvgSprite.all_icons(theme_ids)
setup_data[:svg_icon_list] = SvgSprite.all_icons(theme_id)
if ENV['DEBUG_PRELOADED_APP_DATA']
setup_data[:debug_preloaded_app_data] = true