From 79ec6c407e11f287b8325fa743e85109955fcb61 Mon Sep 17 00:00:00 2001 From: Osama Sayegh Date: Wed, 5 Aug 2020 12:26:36 +0300 Subject: [PATCH] FEATURE: Allow assets to be precompiled with Sprockets (#456) * Allow assets to be precompiled with Sprockets * Don't create rails engine unless user opts in * Update ASSET_VERSION * Add documentation --- README.md | 10 ++++++++++ lib/html/includes.css | 13 +++++++++---- lib/html/includes.js | 7 +++++-- lib/html/profile_handler.js | 2 +- lib/html/rack-mini-profiler.css | 3 +++ lib/html/rack-mini-profiler.js | 2 ++ lib/mini_profiler/asset_version.rb | 2 +- lib/mini_profiler/config.rb | 9 +++++++++ lib/mini_profiler/profiler.rb | 12 +++++++++++- lib/mini_profiler_rails/railtie.rb | 11 +++++++++++ 10 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 lib/html/rack-mini-profiler.css create mode 100644 lib/html/rack-mini-profiler.js diff --git a/README.md b/README.md index 0349ded6..2aaa7285 100644 --- a/README.md +++ b/README.md @@ -329,6 +329,15 @@ _Note:_ The GUID (`data-version` and the `?v=` parameter on the `src`) will chan #### Using MiniProfiler's built in route for apps without HTML responses MiniProfiler also ships with a `/rack-mini-profiler/requests` route that displays the speed badge on a blank HTML page. This can be useful when profiling an application that does not render HTML. +#### Register MiniProfiler's assets in the Rails assets pipeline +MiniProfiler can be configured so it registers its assets in the assets pipeline. To do that, you'll need to provide a lambda (or proc) to the `assets_url` config (see the below section). The callback will receive 3 arguments which are: `name` represents asset name (currently it's either `rack-mini-profiling.js` or `rack-mini-profiling.css`), `assets_version` is a 32 characters long hash of MiniProfiler's assets, and `env` which is the `env` object of the request. MiniProfiler expects the `assets_url` callback to return a URL from which the asset can be loaded (the return value will be used as a `href`/`src` attribute in the DOM). If the `assets_url` callback is not set (the default) or it returns a non-truthy value, MiniProfiler will fallback to loading assets from its own middleware (`/mini-profiler-resources/*`). The following callback should work for most applications: + +```ruby +Rack::MiniProfiler.config.assets_url = ->(name, version, env) { + ActionController::Base.helpers.asset_path(name) +} +``` + ### Configuration Options You can set configuration options using the configuration accessor on `Rack::MiniProfiler`. @@ -360,6 +369,7 @@ max_traces_to_show|20|Maximum number of mini profiler timing blocks to show on o html_container|`body`|The HTML container (as a jQuery selector) to inject the mini_profiler UI into show_total_sql_count|`false`|Displays the total number of SQL executions. enable_advanced_debugging_tools|`false`|Enables sensitive debugging tools that can be used via the UI. In production we recommend keeping this disabled as memory and environment debugging tools can expose contents of memory that may contain passwords. +assets_url|`nil`|See the "Register MiniProfiler's assets in the Rails assets pipeline" section above. ### Using MiniProfiler with `Rack::Deflate` middleware diff --git a/lib/html/includes.css b/lib/html/includes.css index 62a19a02..3b283582 100644 --- a/lib/html/includes.css +++ b/lib/html/includes.css @@ -207,7 +207,8 @@ top: 0px; } .profiler-results.profiler-top.profiler-left { left: 0px; } - .profiler-results.profiler-top.profiler-left.profiler-no-controls .profiler-totals, .profiler-results.profiler-top.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button, + .profiler-results.profiler-top.profiler-left.profiler-no-controls .profiler-totals, + .profiler-results.profiler-top.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-results.profiler-top.profiler-left .profiler-controls { -webkit-border-bottom-right-radius: 10px; -moz-border-radius-bottomright: 10px; @@ -217,7 +218,8 @@ border-right: 1px solid #888; } .profiler-results.profiler-top.profiler-right { right: 0px; } - .profiler-results.profiler-top.profiler-right.profiler-no-controls .profiler-totals, .profiler-results.profiler-top.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button, + .profiler-results.profiler-top.profiler-right.profiler-no-controls .profiler-totals, + .profiler-results.profiler-top.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-results.profiler-top.profiler-right .profiler-controls { -webkit-border-bottom-left-radius: 10px; -moz-border-radius-bottomleft: 10px; @@ -229,7 +231,8 @@ bottom: 0px; } .profiler-results.profiler-bottom.profiler-left { left: 0px; } - .profiler-results.profiler-bottom.profiler-left.profiler-no-controls .profiler-totals, .profiler-results.profiler-bottom.profiler-left.profiler-no-controls .profiler-result:first-child .profiler-button, + .profiler-results.profiler-bottom.profiler-left.profiler-no-controls .profiler-totals, + .profiler-results.profiler-bottom.profiler-left.profiler-no-controls .profiler-result:first-child .profiler-button, .profiler-results.profiler-bottom.profiler-left .profiler-controls { -webkit-border-top-right-radius: 10px; -moz-border-radius-topright: 10px; @@ -239,7 +242,8 @@ border-right: 1px solid #888; } .profiler-results.profiler-bottom.profiler-right { right: 0px; } - .profiler-results.profiler-bottom.profiler-right.profiler-no-controls .profiler-totals, .profiler-results.profiler-bottom.profiler-right.profiler-no-controls .profiler-result:first-child .profiler-button, + .profiler-results.profiler-bottom.profiler-right.profiler-no-controls .profiler-totals, + .profiler-results.profiler-bottom.profiler-right.profiler-no-controls .profiler-result:first-child .profiler-button, .profiler-results.profiler-bottom.profiler-right .profiler-controls { -webkit-border-bottom-top-radius: 10px; -moz-border-radius-topleft: 10px; @@ -345,6 +349,7 @@ @media print { .profiler-results { display: none; } } + .profiler-queries-bg { z-index: 2147483642; display: none; diff --git a/lib/html/includes.js b/lib/html/includes.js index e5930d09..a9cc120d 100644 --- a/lib/html/includes.js +++ b/lib/html/includes.js @@ -980,6 +980,7 @@ var MiniProfiler = (function() { script.getAttribute("data-start-hidden") === "true" || sessionStorage["rack-mini-profiler-start-hidden"] === "true"; var htmlContainer = script.getAttribute("data-html-container"); + var cssUrl = script.getAttribute("data-css-url"); return { ids: ids, path: path, @@ -996,7 +997,8 @@ var MiniProfiler = (function() { toggleShortcut: toggleShortcut, startHidden: startHidden, collapseResults: collapseResults, - htmlContainer: htmlContainer + htmlContainer: htmlContainer, + cssUrl: cssUrl }; })(); @@ -1056,7 +1058,7 @@ var MiniProfiler = (function() { var init = function init() { if (options.authorized) { - var url = options.path + "includes.css?v=" + options.version; + var url = options.cssUrl; if (document.createStyleSheet) { document.createStyleSheet(url); @@ -1398,4 +1400,5 @@ var MiniProfiler = (function() { }; })(); +window.MiniProfiler = MiniProfiler; MiniProfiler.init(); diff --git a/lib/html/profile_handler.js b/lib/html/profile_handler.js index 59480857..d147c266 100644 --- a/lib/html/profile_handler.js +++ b/lib/html/profile_handler.js @@ -1 +1 @@ - + diff --git a/lib/html/rack-mini-profiler.css b/lib/html/rack-mini-profiler.css new file mode 100644 index 00000000..e156c7e0 --- /dev/null +++ b/lib/html/rack-mini-profiler.css @@ -0,0 +1,3 @@ +/* + *= require ./includes + */ diff --git a/lib/html/rack-mini-profiler.js b/lib/html/rack-mini-profiler.js new file mode 100644 index 00000000..37cd2247 --- /dev/null +++ b/lib/html/rack-mini-profiler.js @@ -0,0 +1,2 @@ +//= require ./includes +//= require ./vendor diff --git a/lib/mini_profiler/asset_version.rb b/lib/mini_profiler/asset_version.rb index 3d7aa2d4..1ef9a784 100644 --- a/lib/mini_profiler/asset_version.rb +++ b/lib/mini_profiler/asset_version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true module Rack class MiniProfiler - ASSET_VERSION = '015eebd28435014a417b0b8cf057054d' + ASSET_VERSION = '435a6923efca239f3ae0a09ac2d09acb' end end diff --git a/lib/mini_profiler/config.rb b/lib/mini_profiler/config.rb index 53211db2..f137c0cb 100644 --- a/lib/mini_profiler/config.rb +++ b/lib/mini_profiler/config.rb @@ -71,6 +71,15 @@ def self.default # Deprecated options attr_accessor :use_existing_jquery + attr_reader :assets_url + + def assets_url=(lmbda) + if defined?(Rack::MiniProfilerRails) + Rack::MiniProfilerRails.create_engine + end + @assets_url = lmbda + end + def vertical_position position.include?('bottom') ? 'bottom' : 'top' end diff --git a/lib/mini_profiler/profiler.rb b/lib/mini_profiler/profiler.rb index b16de3f7..97b3079d 100644 --- a/lib/mini_profiler/profiler.rb +++ b/lib/mini_profiler/profiler.rb @@ -628,10 +628,20 @@ def ids_comma_separated(env) # * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject def get_profile_script(env) path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}" + version = MiniProfiler::ASSET_VERSION + if @config.assets_url + url = @config.assets_url.call('rack-mini-profiler.js', version, env) + css_url = @config.assets_url.call('rack-mini-profiler.css', version, env) + end + + url = "#{path}includes.js?v=#{version}" if !url + css_url = "#{path}includes.css?v=#{version}" if !css_url settings = { path: path, - version: MiniProfiler::ASSET_VERSION, + url: url, + cssUrl: css_url, + version: version, verticalPosition: @config.vertical_position, horizontalPosition: @config.horizontal_position, showTrivial: @config.show_trivial, diff --git a/lib/mini_profiler_rails/railtie.rb b/lib/mini_profiler_rails/railtie.rb index 1d5b0c86..bf60aaaa 100644 --- a/lib/mini_profiler_rails/railtie.rb +++ b/lib/mini_profiler_rails/railtie.rb @@ -118,6 +118,17 @@ def self.initialize!(app) @already_initialized = true end + def self.create_engine + return if defined?(Rack::MiniProfilerRails::Engine) + klass = Class.new(::Rails::Engine) do + engine_name 'rack-mini-profiler' + config.assets.paths << File.expand_path('../../html', __FILE__) + config.assets.precompile << 'rack-mini-profiler.js' + config.assets.precompile << 'rack-mini-profiler.css' + end + Rack::MiniProfilerRails.const_set("Engine", klass) + end + def self.subscribe(event, &blk) if ActiveSupport::Notifications.respond_to?(:monotonic_subscribe) ActiveSupport::Notifications.monotonic_subscribe(event) { |*args| blk.call(*args) }