Giter Club home page Giter Club logo

micmro / performance-bookmarklet Goto Github PK

View Code? Open in Web Editor NEW
1.1K 48.0 86.0 4.38 MB

Performance-Bookmarklet helps to analyze the current page through the Resource Timing API, Navigation Timing API and User-Timing - requests by type, domain, load times, marks and more. Sort of a light live WebPageTest.

License: MIT License

JavaScript 91.49% CSS 8.51%
webperf bookmarklet navigation-timing resource-timing analyzer performance waterfall requests performance-metrics user-timing

performance-bookmarklet's Introduction

Performance-Bookmarklet

Bookmarklet, Chrome Extension and Firefox add-on to analyze the current page through the Resource Timing API, Navigation Timing API and User-Timing - requests by type, domain, load times, marks and more - sort of a light live WebPageTest.

Just add this into the URL section of a new bookmark:

javascript:(function(){var el=document.createElement('script');el.type='text/javascript';el.src='https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js';el.onerror=function(){alert("Looks like the Content Security Policy directive is blocking the use of bookmarklets\n\nYou can copy and paste the content of:\n\n\"https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js\"\n\ninto your console instead\n\n(link is in console already)");console.log("https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js");};document.getElementsByTagName('body')[0].appendChild(el);})();

You can use the Performance-Bookmarklet (renamed as Performance-Analyser since it's not a Bookmarklet) as Chrome Extension or Firefox add-on.

screenshot showing the whole bookmarklet on http://google.com

Bookmarklet Output in Detail

Navigation Timing Waterfall

alt text

  • It also displays markers and measures if you're setting marks with the User Timing API (performance.mark and performance.measure)
  • Hover over the bars to see a tooltip with the exact Milliseconds/duration
Navigation Timing API Details

Diagram of the Navigation Timing API as seen on W3C site

Domain/Resource analysis

alt text

  • Requests by domain:
    • How many requests are added by 3rd parties - green wedges represent the current TLD and subdomains
    • Avg. Duration: the mean of all request of this domain
    • Duration Parallel: actual time a domain spends on the wire - de-duping parallel request duration
    • Duration Sum: simple sum of the duration of all requests of this domain
    • Percentage: the percentage of all requests coming from this domain
  • Requests by Initiator Type
  • Requests by Type - what content type is accountable for the majority of requests
  • Internal / extenal comparison charts
    external is currently everything except the current host - exluding sub domains

Resource Timing Waterfall with Markers

alt text

  • The small bars inside the resource bar represent the different stages of the request (redirect, domainLookup, connect, secureConnect, requestToResponseStart, response), but are mostly unavailable for cross-domain requests.
  • The resource bar colours indicates the initiatorType
  • You can filter the waterfall chart by domain
Resource Timing API Details

Diagram of the Resource Timing API as seen on W3C site

Console Output

The bookmarklet also outputs various console tables (where supported) to analyze the data in detail.

alt text

Various page metrics can be persisted between page refreshes and later displayed in the console, when ticking the Persist Data? checkbox.

How to use this snippet

You can use it as bookmarklet. Mozilla has a step by step description on how to add a bookmarklet.

javascript:(function(){var el=document.createElement('script');el.type='text/javascript';el.src='https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js';el.onerror=function(){alert("Looks like the Content Security Policy directive is blocking the use of bookmarklets\n\nYou can copy and paste the content of:\n\n\"https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js\"\n\ninto your console instead\n\n(link is in console already)");console.log("https://micmro.github.io/performance-bookmarklet/dist/performanceBookmarklet.min.js");};document.getElementsByTagName('body')[0].appendChild(el);})();

Or alternatifly just copy and paste the content of performanceBookmarklet.js to your browser console.

You need to fall back to the browser extension or the copy and paste version for sites that block external scripts in their Content Security Policy directives.

Browser Extensions

performance-bookmarklet can also be used as Chrome Extension and Firefox add-on. It uses the same code, but has some usability advantages, e.g. you don't need to worry about the Content Security Policy directives.

Read more

performance-bookmarklet's People

Contributors

billthompson avatar davidbgk avatar dependabot[bot] avatar jason-cooke avatar micmro avatar mmanela avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

performance-bookmarklet's Issues

"sandbox" the performance bookmarklet

I have modified the performance bookmarklet so that it runs within an iframe with it's own security sandbox (so that the code is only loaded as needed, and so I don't need to audit your code much!). The performance data is passed from the "host" document to the "guest" iframe using sendMessage.

I have attached the code here to give an idea of the changes, although it would need a few hours work for anyone to use.

The function to show the performance metrics (e.g. connected to a button), run from the "host" document is:

function showTiming() {
	function objectify(object) {
		return JSON.parse(JSON.stringify(object));
	}
	var performance = window.performance;
	if (!performance || !performance.getEntriesByType) return;
	var perf = {
		resources: objectify(performance.getEntriesByType('resource')),
		marks: objectify(performance.getEntriesByType('mark')),
		measures: objectify(performance.getEntriesByType('measure')),
		timing: objectify(performance.timing),
		navigation: objectify(performance.navigation)
	};

	var html = '<script src="https://some.domain.here/performance-bookmarklet.js"></script>';
	var secondBody = document.createElement('body');
	secondBody.innerHTML = '<iframe class=nobox frameborder=0 src="about:blank"></iframe>';
	var iframe = secondBody.firstChild;
	if ('srcdoc' in iframe) {
		iframe.setAttribute('sandbox', 'allow-scripts');
		iframe.setAttribute('referrerpolicy', 'no-referrer');
		iframe.srcdoc = html;
	} else {	// srcdoc not IE but will be introduced in Edge 18
		setTimeout(function() {	// IE needs iframe to be in document so use postpone
			var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
			iframeDoc.open();
			iframeDoc.write(html);
			iframeDoc.close();
		}, 0);
	}
	iframe.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;z-index:10000;';
	iframe.onload = function() {
		iframe.contentWindow.postMessage(perf, '*');
		iframe.onload = null;
	};
	var closeButton = document.createElement('button');
	closeButton.textContent = 'close';
	closeButton.style.cssText = 'position:fixed;top:20px;left:20px;z-index:10001;background-color:#BBF;';
	closeButton.onclick = function() {
		document.body.style.overflow = '';
		document.documentElement.removeChild(secondBody);
	}
	secondBody.appendChild(closeButton);
	document.body.style.overflow = 'hidden';
	document.documentElement.appendChild(secondBody);	// looks odd, but html spec does allow multiple body elements
}

I edited the compiled performance-bookmarklet.js (Yes this is a very dirty technique. Done because I didn't want to edit source code as then I would need to run your build process which would have taken me more time and I needed the code to work with our custom build process).

We put the following code around the performance-bookmarklet.js code (dirty: monkey patches window.performance to read the local data)

(function () {
	function go(perf) {
		window.performance = {
			timing: perf.timing,
			navigation: perf.navigation,
			getEntriesByType: function(type){
				if (type == "resource") {
					return perf.resources;
				} else if (type == 'mark') {
					return perf.marks;
				} else if (type == "measure") {
					return perf.measures;
				}
			}
		};
		execBookmarklet(withinIframe);
		window.performance = null;
	}

	if (window.doubleLoad) {
		return;
	}
	window.doubleLoad = 1;

	var withinIframe = window.top !== window.self;
	if (withinIframe) {
		window.onmessage = function(event) {
			var perf = event.data;
			if (perf.resources) {
				go(perf);
			}
		};
	} else {	// Called by 'Timing Graph Debug'
		var objectify = function(object) {
			return JSON.parse(JSON.stringify(object));
		}
		go({
			resources: objectify(window.performance.getEntriesByType("resource")),	// JSON.parse(JSON.stringify(window.performance.getEntriesByType("resource")))
			marks: objectify(window.performance.getEntriesByType("mark")),
			measures: objectify(window.performance.getEntriesByType("measure")),
			timing: objectify(window.performance.timing),
			navigation: objectify(window.performance.navigation)
		});
	}

	// put copyright into a string stored on an object so that the copyright isn't removed during compression
	execBookmarklet.copyright = 'Copyright 2014 Michael Mrowetz. MIT License: https://github.com/micmro/performance-bookmarklet/blob/d3e037620270419521eab20bf479c51c8ea72d96/LICENSE';

function execBookmarklet(withinIframe) {
// INSERT BOOKMARKLET CODE HERE
}
})();

The BOOKMARKLET CODE itself also has a few modifications.

Don't read localStorage (causes exception):

if (!withinIframe)
	var persistanceEnabled = !!JSON.parse(localStorage.getItem(storageKey));

Change the IFrameHolder code:

iFrameHolder.getOutputIFrame = function () {
	return outputIFrame;
};

module.exports = iFrameHolder;

if (withinIframe) {
	module.exports = {
		setup: function (onIFrameReady) {
			function addComponent(domEl) {
				document.body.appendChild(domEl);
			}
			var styleTag = dom.newTag("style", {
				type: "text/css",
				text: style
			});
			document.head.appendChild(styleTag);
			var outputHolder = dom.newTag("div", { id: "perfbook-holder" });
			var outputContent = dom.newTag("div", { id: "perfbook-content" });
			outputHolder.appendChild(outputContent);
			document.body.appendChild(outputHolder);
			onIFrameReady(addComponent);
		},
		getOutputIFrame: function(){
			return document;
		}
	};
}

Add connection details (very important for HTTP2 connection versus HTTP1.1 connection):

	var connection = navigator.connection;
	if (connection) {
		createAppendixDefValue(appendix, dom.newTag("abbr", { title: "Connection", text: "navigator.connection.*" }), "");
		for (var key in connection) {
			var value = connection[key];
			if (value && typeof value != "function") {
				createAppendixDefValue(appendix, dom.newTextNode("\xa0\xa0" + key + ":"), value);
			}
		}
	}

	tilesHolder.appendChild(appendix);
	return tilesHolder;

Dont check for about: protocol:

if (withinIframe) {
	if (!data.isValid()) {
		return;
	}
} else {
	if (location.protocol === "about:" || !data.isValid()) {
		return;
	}
}

Commented out dead code:

		// window.outputContent;

The final change was to remove the negative right margins (replaced -18px and -72px with 0 in the css style).

I have written this issue so that if anyone else wants to use your code others can branch and build on these snippets. Hopefully it is useful to someone so maybe just leave the issue open?!

I really really appreciate your code - it still works beautifully (2019).

Find nicer way of showing late pings

It's bit of an edge case but doesn't look good.

  • should second lines or markers be hidden for request with more than ~30sec?
  • Should later pings be ignored (onload + debounce 2 seconds )?

screen shot 2015-03-04 at 10 17 18 pm

Summary dashboard

Summarize key measures

  • TTFB
  • domContentLoaded
  • Onload
  • Domains Total
  • Subdomains of TLD
  • Current TLD & Subdomain Requests
  • Requests to Host
  • CrossDomain Requests (document.domain)

Data store

The project is very useful for web performance, I want to use it in my project, but I need some API to save performace data for analysing user's performace, can you give me some advise?

export to html

Hi, thanks for this brilliant script!

Is there any way to export report into html file?

some typo

subDomainsOfTdl should be subDomainsOfTld?

Requests by file-type panel

  • pie chart - done
  • Table with the following
    || FileType || Count || Count Internal || count external || Count by Initiator Type || Initiator Type Internal || Initiator Type external ||
  • Table by Domain?

Way to close the window when it's scrolled to bottom?

Because when the window is scrolled to the bottom, the close button is not visible. Would be great to have an option to close it immediately. It could be clicking the toolbar button again, or having a floating button to close.

i18n

do you have plans for translating this into another languages?
I would be interested in having it in Italian...

Time by domain

List of median TTFB/Download time per domain to highlight slow 3rd parties etc.

Export as JSON

alone the same line as #42, but I believe exporting the results to PDF or Excel is much more difficult than exporting as JSON, hence a new issue request.

So, beside dumping to console as table, please provide an option to dump to console as JSON.

Thanks

ssl/tls value seems to be incorrectly calculated

Based on my research, ssl/tls value is the diff of connectEnd-secureConnectionStart. Looks like in this repo, it is calculated using connectStart.

	if(perfTimingCalc.secureConnectionStart){
		perfTimingCalc.blocks.push(waterfall.timeBlock("SSL", perfTimingCalc.connectStart, perfTimingCalc.secureConnectionStart, "block-ssl"));
	}

Let me know your thoughts. I am open to submitting a PR if this needs to be fixed.

Firefox mark label bug

Firefox bug with writing-mode: tb; for text SVG nodes.

They don't align correctly and the mouseover is just triggered for the regular horizontal area.

screen shot 2015-04-19 at 3 09 04 pm
correctly

Horizontal scrollbar for the Resource Timing Container?

Hi, would it be possible at some point to add a horizontal scrollbar to the Resource Timing container? I am experiencing some issues with seeing the full picture with certain website applications that loads a lot of content hence the viewport of the Resource Timing container need some "stretching" to be able to see the end of the performance timeline.

https://prnt.sc/VAA39st6IFOM

Thank you for all the work put into this repo already at this time. Superb. Keep up the good work.

Firefox support

Hi,
is the add on still available for firefox? The links are broken and I could not find it.
Thank you

Reset the starting point

When would performance-bookmarklet start its data collection?
Would it always start from the very beginning?
Is it possible to let performance-bookmarklet to, "forget the past, start data collection from now"?

Thanks

Support for Firefox 35a (Developer Edition)

I just tried your bookmarklet on FF35 and it just opens a white layer on top of the current page (see screenshot).

website

The devtools itself contain some console.table() formatted data, but the bookmarklet does not show up like the screenshots of your readme explain.

devtools

Is Firefox not supported? Are there any statements regarding browser support?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.