Skip to content

Instantly share code, notes, and snippets.

@guillaume86
Last active March 12, 2024 15:08
Show Gist options
  • Save guillaume86/8f80aef3ca52fffa77834bdecd997e73 to your computer and use it in GitHub Desktop.
Save guillaume86/8f80aef3ca52fffa77834bdecd997e73 to your computer and use it in GitHub Desktop.
Integrating MiniProfiler into a SPA (React, Angular, Vue, etc)
/**
* GET /mini-profiler-includes returns a <script> element
* Re-create it in the DOM and append it to the document.
*
* Using ES5 for maximum compatibilty.
*/
(function (window) {
if ("MiniProfiler" in window) return console.warn("MiniProfiler already imported.");
var ERROR_MESSAGE = "MiniProfiler could not be loaded: ";
function getIncludes(callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
if (this.status !== 200) return callback(ERROR_MESSAGE + "request error.")
callback(null, this.responseText);
};
xhr.onerror = function () {
callback(ERROR_MESSAGE + "request error.")
}
xhr.open("GET", "/mini-profiler-includes", true);
xhr.send();
}
function loadScript(scriptHtml) {
if (!("DOMParser" in window) || !DOMParser.prototype.parseFromString) {
console.error(ERROR_MESSAGE + "DOMParser::parseFromString not supported (IE9?)");
return;
}
try {
var parser = new DOMParser();
var doc = parser.parseFromString(scriptHtml, "text/html");
var scriptParsed = doc.querySelector("script");
if (!scriptParsed) return;
var script = document.createElement("script");
for (var i = 0; i < scriptParsed.attributes.length; i++) {
var attribute = scriptParsed.attributes[i];
script.setAttribute(attribute.name, attribute.value);
}
var target = document.getElementsByTagName("script")[0];
target.parentNode.insertBefore(script, target);
} catch (err) {
console.error(ERROR_MESSAGE + err.toString());
}
}
getIncludes(function (err, scriptHTML) {
if (err) return console.error(err);
if (!scriptHTML) return;
loadScript(scriptHTML);
});
})(window);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
namespace StackExchange.Profiling
{
public static class MiniProfilerSpaExtensions
{
public static void MapMiniProfilerIncludes(this IEndpointRouteBuilder endpoints, RenderOptions? options = null, string url = "mini-profiler-includes")
{
endpoints.MapGet(url, async (context) =>
{
context.Response.ContentType = "text/html";
var includes = MiniProfiler.Current.RenderIncludes(context, options);
if (String.IsNullOrEmpty(includes.Value))
return;
await context.Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes(includes.Value));
});
}
}
}
#nullable enable
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Profiling;
using System;
using System.Globalization;
namespace MyApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddMiniProfiler(options =>
{
// ...
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
app.UseMiniProfiler();
// ...
app.UseEndpoints(endpoints =>
{
endpoints.MapMiniProfilerIncludes(new RenderOptions
{
StartHidden = true,
PopupToggleKeyboardShortcut = "Ctrl+m",
});
// ...
});
app.UseSpa(spa =>
{
// ...
});
}
}
}
@guillaume86
Copy link
Author

Here's the code I use to import MiniProfiler into a React SPA. It should work with any other client side stack. You can import MiniProfiler.js either with a script tag in your index.html or include it in your bundle.

@aaron5670
Copy link

Thanks mate 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment