{"id":20331167,"url":"https://github.com/comcast/surf-n-perf","last_synced_at":"2025-03-31T07:09:11.471Z","repository":{"id":17067520,"uuid":"19832305","full_name":"Comcast/Surf-N-Perf","owner":"Comcast","description":"Micro-library for gathering web page performance data","archived":false,"fork":false,"pushed_at":"2022-10-23T14:25:22.000Z","size":1039,"stargazers_count":90,"open_issues_count":5,"forks_count":22,"subscribers_count":14,"default_branch":"main","last_synced_at":"2024-04-14T09:37:40.447Z","etag":null,"topics":["hacktoberfest","javascript","navigation-timing","user-timing","web-performance"],"latest_commit_sha":null,"homepage":"http://comcast.github.io/Surf-N-Perf/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Comcast.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-15T19:26:42.000Z","updated_at":"2023-07-21T09:38:06.000Z","dependencies_parsed_at":"2022-08-30T20:01:03.815Z","dependency_job_id":null,"html_url":"https://github.com/Comcast/Surf-N-Perf","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2FSurf-N-Perf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2FSurf-N-Perf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2FSurf-N-Perf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2FSurf-N-Perf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Comcast","download_url":"https://codeload.github.com/Comcast/Surf-N-Perf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246429484,"owners_count":20775807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","javascript","navigation-timing","user-timing","web-performance"],"created_at":"2024-11-14T20:19:02.796Z","updated_at":"2025-03-31T07:09:11.453Z","avatar_url":"https://github.com/Comcast.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Surf-N-Perf\n==============\n\nMicro-library for gathering frontend web page performance data.\n\nSurf-N-Perf provides a simple to use API to gather [User Timing](http://www.w3.org/TR/user-timing/) and other important performance data in any browser.\n\nTired of typing `window.performance.getEntriesByName('foo')[0].startTime;` with your User Timing Polyfill?\n\nWith Surf-N-Perf, all you need  is `surfnperf.getMark('foo')';`, and that's just the start!\n\nCheck out the [JavaScript API](https://github.com/Comcast/Surf-N-Perf/wiki/JavaScript-API) to see all of its features and the [full documentation](http://comcast.github.io/Surf-N-Perf/docs/SurfNPerf.html) for a list of methods \u0026 how to use them.\n\nAvailable as an [NPM Module](https://www.npmjs.com/package/surfnperf), [Ruby Gem](https://rubygems.org/gems/surfnperf), and a [Bower](https://bower.io/) package.\n\n![Build Status](https://github.com/Comcast/Surf-N-Perf/actions/workflows/test.yml/badge.svg)\n\n## Usage\n\n### Including the code in your project\n\nThere are 2 pieces of code that need to be included in your webpage:\n\n**1.** The following code must be included as high up in the source code of your base HTML document as possible, ideally right after the opening ```\u003chead\u003e``` tag:\n\n```html\n\u003cscript\u003e\n  var SURF_N_PERF = {\n    marks: {},\n    highResMarks: {}\n  };\n\n  SURF_N_PERF.marks.pageStart = (new Date()).getTime();\n\n  if(window.performance) {\n    if(window.performance.now) {\n      SURF_N_PERF.highResMarks.pageStart = window.performance.now();\n    }\n    if(window.performance.mark) {\n      window.performance.mark('pageStart');\n    }\n  }\n\n  SURF_N_PERF.visibility = {\n    initialState: document.visibilityState,\n    stateUpdates: [],\n    hiddenProperty: null,\n    stateProperty: null,\n    eventName: null,\n    markChange: function() {\n      var markName = 'visibility' + SURF_N_PERF.visibility.stateUpdates.length;\n\n      if (window.performance) {\n        if (window.performance.mark) {\n          window.performance.mark(markName);\n        }\n\n        if (window.performance.now) {\n          SURF_N_PERF.highResMarks[markName] = window.performance.now();\n        }\n      }\n\n      SURF_N_PERF.marks[markName] = new Date().getTime();\n\n      SURF_N_PERF.visibility.stateUpdates.push(document[SURF_N_PERF.visibility.stateProperty]);\n    },\n  };\n\n  if('hidden' in document) {\n    SURF_N_PERF.visibility.hiddenProperty = 'hidden';\n    SURF_N_PERF.visibility.stateProperty = 'visibilityState';\n    SURF_N_PERF.visibility.eventName = 'visibilitychange';\n  } else if('webkitHidden' in document) {\n    SURF_N_PERF.visibility.hiddenProperty = 'webkitHidden';\n    SURF_N_PERF.visibility.stateProperty = 'webkitVisibilityState';\n    SURF_N_PERF.visibility.eventName = 'webkitvisibilitychange';\n    SURF_N_PERF.visibility.initialState = document[SURF_N_PERF.visibility.stateProperty];\n  }\n\n  SURF_N_PERF.setPageLoad = function() {\n    SURF_N_PERF.marks.loadEventEnd = (new Date()).getTime();\n\n    if(window.performance \u0026\u0026 window.performance.now) {\n      SURF_N_PERF.highResMarks.loadEventEnd = window.performance.now();\n    }\n  };\n\n  SURF_N_PERF.setFirstPaint = function() {\n    SURF_N_PERF.marks.firstPaintFrame = (new Date()).getTime();\n\n    if(window.performance \u0026\u0026 window.performance.now) {\n      SURF_N_PERF.highResMarks.firstPaintFrame = window.performance.now();\n\n      if(window.performance.mark) {\n        window.performance.mark('firstPaintFrame');\n      }\n    }\n  };\n\n  if(window.addEventListener) {\n    if (SURF_N_PERF.visibility.stateProperty) {\n      document.addEventListener(SURF_N_PERF.visibility.eventName, SURF_N_PERF.visibility.markChange, false);\n    }\n    window.addEventListener('load', SURF_N_PERF.setPageLoad, false);\n  } else {\n    window.attachEvent('onload', SURF_N_PERF.setPageLoad);\n  }\n  if (window.requestAnimationFrame) {\n    window.requestAnimationFrame(SURF_N_PERF.setFirstPaint);\n  }\n\u003c/script\u003e\n```\n\nThat provides support for the following:\n\n- A `\"pageStart\"` mark for browsers that do not support [Navigation Timing](http://www.w3.org/TR/navigation-timing/) which can be used to compute durations from when the page first started loading (specifically, this mark falls between the [`domLoading`](http://www.w3.org/TR/navigation-timing/#dom-performancetiming-domloading) and [`domInteractive`](http://www.w3.org/TR/navigation-timing/#dom-performancetiming-dominteractive) attributes of Navigation Timing)\n- `\"pageStart\"` marks for browsers that support [High Resolution Time](http://www.w3.org/TR/hr-time/) and/or [User Timing](http://www.w3.org/TR/user-timing/) so that `\"pageStart\"` can be used as a consistent starting point for duration calculations across all browsers regardless of their supported features\n- A `\"loadEventEnd\"` mark for browsers that do not support [Navigation Timing](http://www.w3.org/TR/navigation-timing/) which can be used to compute durations from when the load event of the document is completed ([`loadEventEnd`](http://www.w3.org/TR/navigation-timing/#dom-performancetiming-loadend))\n- A `\"loadEventEnd\"` [DOMHighResTimeStamp](http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp) mark for calculating high resolution durations between a Navigation Timing mark and a user mark in browsers that support [High Resolution Time](http://www.w3.org/TR/hr-time/) but don't support [User Timing](http://www.w3.org/TR/user-timing/)\n- A `\"firstPaintFrame\"` mark (available in the best possible format for the browser, either a [User Timing Mark](http://www.w3.org/TR/user-timing/#performancemark), [DOMHighResTimeStamp](http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp), or [DOMTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMTimeStamp)) that approximates the Time To First Paint in browsers that [support `window.requestAnimationFrame`](http://caniuse.com/#feat=requestanimationframe).\n- The initial `visibilityState` as well as listeners for the `\"visibilitychange\"` event, enabling the ability to calculate how much time the page was hidden when you call `surfnperf.getHiddenTime()`. This is of particular importance as [Chrome as of version 57](https://developers.google.com/web/updates/2017/03/background_tabs) and [Firefox as of version 57](https://blog.mozilla.org/blog/2017/09/26/firefox-quantum-beta-developer-edition/) limit the resources assigned to background (hidden) tabs.\n\n**2.** Then just drop the [surfnperf.min.js](https://github.com/Comcast/Surf-N-Perf/blob/main/surfnperf.min.js) in your codebase and reference that JavaScript file in your HTML document. If you're using [RequireJS](http://requirejs.org/) or [Browserify](http://browserify.org/), it registers itself as 'surfnperf'.\n\n**3.** (Optional) If you would like access to the [Resource Timing](https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API/Using_the_Resource_Timing_API) helper functions, include [resource-timing.js](https://github.com/Comcast/Surf-N-Perf/blob/main/resource-timing.js) in your codebase and reference that JavaScript file in your HTML document. If you're using [RequireJS](http://requirejs.org/), it registers itself as 'surfnperf/resource-timing', otherwise it is available on `window` as `window.surfnperfRT`.\n\n### Storing \u0026 Retrieving Performance Data\n\nDetails in the [JavaScript API](https://github.com/Comcast/Surf-N-Perf/wiki/JavaScript-API) page in the wiki\n\n### Resource Timing Helper Functions\n\nDocumented in the [JSDoc-generated Documentation](http://comcast.github.io/Surf-N-Perf/docs/SurfNPerfRT.html)\n\n## Ruby Project Integration\n\n### Using within a Rails project\n\nThe [surfnperf Ruby Gem](https://rubygems.org/gems/surfnperf) allows you to quickly \u0026 easily integrate Surf-N-Perf into your [Rails](http://rubyonrails.org/) projects. To include the necessary files, add `surfnperf` to your `Gemfile`:\n\n```ruby\ngem 'surfnperf'\n```\n\nAfter a `$ bundle install`, you'll be able to include the [main JavaScript file](https://github.com/Comcast/Surf-N-Perf/blob/main/surfnperf.js) in your JavaScript manifest by simply adding:\n\n```\n//= require surfnperf\n```\n\nThe necessary script for the ```\u003chead\u003e``` of your HTML document is also available to you via a [partial template](http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials) that you can include in the appropriate layout file for your page, such as `app/views/layouts/application.html.erb` by simply adding this line:\n\n```erb\n\u003c%= render \"surfnperf/head\" %\u003e\n```\n\nThose 3 lines of code are all your need to get started using Surf-N-Perf in Rails!\n\n\n### Using within a Middleman project\n\nThe [surfnperf Ruby Gem](https://rubygems.org/gems/surfnperf) also allows you to quickly \u0026 easily integrate Surf-N-Perf into your [Middleman](https://middlemanapp.com/) projects. Instructions are similar to the Rails instructions above, with one extra step. Start by adding at least v1.1.0 of `surfnperf` to your Middleman project's `Gemfile`:\n\n```ruby\ngem \"surfnperf\", \"\u003e=1.1.0\"\n```\n\nAfter a `$ bundle install`, you'll be able to include the [main JavaScript file](https://github.com/Comcast/Surf-N-Perf/blob/main/surfnperf.js) in your JavaScript manifest by simply adding:\n\n```\n//= require surfnperf\n```\n\nThe necessary script for the ```\u003chead\u003e``` of your HTML document is also available to you via a [custom defined helper](https://middlemanapp.com/basics/helper_methods/#custom-defined-helpers) that you can include in the appropriate layout file for your page, such as `source/layouts/layout.erb` by adding this line:\n\n```erb\n\u003c%= surfnperf_head %\u003e\n```\n\nYou will also have to configure the extension for that helper to be recognized by Middleman by adding this line to your `config.rb`:\n\n```ruby\nactivate :surfnperf\n```\n\nYou'll want to do that **outside** of your build-specific configuration (i.e. outside the `configure :build do` block) so that it is available when you run `$ bundle exec middleman server`\n\nThose 4 lines of code are all your need to get started using Surf-N-Perf in Middleman!\n\n### Using within other Ruby projects that integrate with Sprockets\n\n[Sprockets](https://github.com/sstephenson/sprockets) is what powers the [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html) in Rails, Middleman, and other Ruby website tools. For these other Ruby projects that use [Sprockets](https://middlemanapp.com/advanced/asset_pipeline/), integration is similar to the Rails instructions above, with one extra step:\n\nAdd `surfnperf` to your `Gemfile`:\n\n```ruby\ngem 'surfnperf'\n```\n\nAfter a `$ bundle install`, include [surfnperf.js](https://github.com/Comcast/Surf-N-Perf/blob/main/surfnperf.js) in your JavaScript manifest by adding:\n\n```\n//= require surfnperf\n```\n\nFor now, you'll have to manually include the [necessary script](#including-the-code-in-your-project) for the ```\u003chead\u003e``` of your HTML document.\n\n## Running Tests \u0026 Other Development Tools\n\nTests are written in [Jasmine](http://jasmine.github.io/) and run with [Karma](http://karma-runner.github.io/)\n\nInstall the dependencies by executing this command from the root of your Surf-N-Perf project directory:\n\n```bash\n$ npm install\n```\nIf Grunt CLI has not been already installed, [go install it](http://gruntjs.com/getting-started).\n\nAnd then run the tests, JSHint, beautify your code \u0026 generate the minified file with:\n\n```bash\n$ grunt dev\n```\n\nBy default, it will run the tests using [PhantomJS](http://phantomjs.org/). You can also run the tests in any browser by going to http://localhost:9876/\n\nThe `grunt dev` process will watch for file updates, so as you modify surfnperf.js or the test files, it will automatically run jshint, jsbeautifier, uglify \u0026 the tests. To stop the watch process, press control + C\n\n## License\n\nLicensed under the [MIT License](https://github.com/Comcast/Surf-N-Perf/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fsurf-n-perf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomcast%2Fsurf-n-perf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fsurf-n-perf/lists"}