0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-04 10:39:43 +08:00
discourse/app/helpers/qunit_helper.rb
Alan Guo Xiang Tan a43c0bddf8
PERF: Avoid HTML escaping preloaded JSON (#41978)
Large preloaded JSON was stored inside an HTML attribute. Because JSON
contains quotation marks that could end the attribute early, Rails had
to convert those characters into HTML-safe text. Processing every
character made the response larger and slower to generate.

This change places the preloaded JSON in a non-executable
`application/json` script element and reads it from the element's text
content.

On a site with 11K categories, the escaping was showing up as a hotspot where we spend ~400ms escaping the massive preloaded JSON.
2026-07-24 09:25:06 +08:00

51 lines
1.4 KiB
Ruby
Vendored

# frozen_string_literal: true
module QunitHelper
def theme_tests
theme = Theme.find_by(id: request.env[:resolved_theme_id])
return "" if theme.blank?
_, digest = theme.baked_js_tests_with_digest
src =
"#{GlobalSetting.cdn_url}" \
"#{Discourse.base_path}" \
"/theme-javascripts/tests/#{theme.id}-#{digest}.js" \
"?__ws=#{Discourse.current_hostname}"
"<link rel='modulepreload' href='#{src}' data-theme-id='#{theme.id}' data-theme-name='#{Rack::Utils.escape_html(theme.name)}' nonce='#{ThemeField::CSP_NONCE_PLACEHOLDER}' />".html_safe
end
def fake_preload_data
preloaded = {}
preloaded.merge!(theme_settings_preload_data)
preloaded.merge!(site_settings_preload_data)
return "" if preloaded.empty?
tag.script(
raw(ERB::Util.json_escape(preloaded.to_json)),
type: "application/json",
id: "data-preloaded",
)
end
private
def theme_settings_preload_data
theme = Theme.find_by(id: request.env[:resolved_theme_id])
activated_themes =
if theme
{ theme.id => { name: theme.name, settings: theme.cached_default_settings } }
else
{}
end
{ "activatedThemes" => activated_themes.to_json }
end
def site_settings_preload_data
{
"siteSettings" => SiteSetting.client_settings_json_uncached(return_defaults: true),
"themeSiteSettingOverrides" => SiteSetting.theme_site_settings_json_uncached(nil),
}
end
end