forked from ceckoslab/inp-measure-puppeteer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3dc5226
Showing
14 changed files
with
2,663 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[*] | ||
end_of_line = lf | ||
insert_final_newline = true | ||
|
||
[*.js] | ||
indent_style = space | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"es6": true | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": 8 | ||
}, | ||
"globals": { | ||
"console": false, | ||
"unescape": false | ||
}, | ||
"rules": { | ||
// | ||
// Rules that were enabled by default in pre-1.0 eslint | ||
// https://github.com/eslint/eslint/blob/master/docs/user-guide/migrating-to-1.0.0.md | ||
// re-enable all the ones we are not specifically disabling | ||
// | ||
"no-alert": 2, | ||
"no-array-constructor": 2, | ||
"no-caller": 2, | ||
"no-catch-shadow": 2, | ||
"no-eval": 2, | ||
"no-extend-native": 2, | ||
"no-extra-bind": 2, | ||
"no-implied-eval": 2, | ||
"no-iterator": 2, | ||
"no-label-var": 2, | ||
"no-labels": 2, | ||
"no-lone-blocks": 2, | ||
"no-loop-func": 2, | ||
"no-multi-str": 2, | ||
"no-native-reassign": 2, | ||
"no-new": 2, | ||
"no-new-func": 2, | ||
"no-new-object": 2, | ||
"no-new-wrappers": 2, | ||
"no-octal-escape": 2, | ||
"no-process-exit": 2, | ||
"no-proto": 2, | ||
"no-return-assign": 2, | ||
"no-script-url": 2, | ||
"no-sequences": 2, | ||
"no-shadow": 2, | ||
"no-shadow-restricted-names": 2, | ||
"no-spaced-func": 2, | ||
"no-undef-init": 2, | ||
"no-unused-expressions": 2, | ||
"no-use-before-define": [2, { "functions": false }], | ||
"no-with": 2, | ||
"comma-spacing": 2, | ||
"curly": [2, "all"], | ||
"eol-last": 2, | ||
"no-extra-parens": [2, "functions"], | ||
"eqeqeq": 2, | ||
"new-parens": 2, | ||
"semi": 2, | ||
"space-infix-ops": 2, | ||
"yoda": [2, "never"], | ||
|
||
// | ||
// Changes over defaults | ||
// | ||
"keyword-spacing": 2, | ||
"no-mixed-spaces-and-tabs": [2, true], | ||
"quotes": [2, "double", "avoid-escape"], | ||
"dot-notation": [2, {"allowKeywords": true}], | ||
"space-unary-ops": 1, | ||
"key-spacing": [1, {"beforeColon": false, "afterColon": true, "mode": "minimum"}], | ||
"no-empty": 2, | ||
"brace-style": [1, "stroustrup", { "allowSingleLine": true }], | ||
"semi-spacing": [2, {"before": false, "after": true}], | ||
"indent": [2, 2, {"VariableDeclarator": 0, "MemberExpression": "off", "CallExpression": {"arguments": "off"}, "SwitchCase": 1}], | ||
"space-before-function-paren": [2, "never"], | ||
"no-trailing-spaces": [2, { "skipBlankLines": false }], | ||
"linebreak-style": [2, "unix"], | ||
"comma-dangle": [2, "never"], | ||
"operator-linebreak": [2, "after"], | ||
"space-in-parens": [2, "never"], | ||
"no-debugger": "error", | ||
|
||
// | ||
// To enable soon | ||
// | ||
|
||
//"require-jsdoc": "error", | ||
//"valid-jsdoc": "error", | ||
|
||
// | ||
// Disabled rules | ||
// | ||
|
||
// We have a lot of variables in underscore_casing | ||
"camelcase": 0, | ||
|
||
// Not ready for strict-mode yet | ||
"strict": 0, | ||
|
||
// We have some functions like BOOMR_check_doc_domain or BOOMR. | ||
"new-cap": 0, | ||
|
||
// We use console.log for debugging | ||
"no-console": 0, | ||
|
||
// We use _s in a couple places for internal vars | ||
"no-underscore-dangle": 0, | ||
|
||
// We delete some global vars for compat with older IE versions | ||
"no-delete-var": 0, | ||
|
||
// We use spaces for alignment in many places | ||
"no-multi-spaces": 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
**/.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"editor.codeActionsOnSave": { | ||
"source.fixAll.eslint": true | ||
}, | ||
"eslint.validate": ["javascript"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# INP Measure - Puppeteer | ||
|
||
Very experimental and still in a proof of concept stage but it does the trick. | ||
|
||
Utilizes the source code available the [Web Vitals](https://github.com/GoogleChrome/web-vitals) library. | ||
|
||
## Configure | ||
|
||
Tweak the following lines in `index.js`: | ||
|
||
``` | ||
// TODO, Change here to the element you would like Puppeteer to interact with. | ||
const elementToInteractWith = "### ADD THE CSS SELECTOR HERE ###"; | ||
// TODO, Change here to the url you would like to load in Puppeteer. | ||
const navigateTo = "https://www.example.com/"; | ||
``` | ||
|
||
## How to run? | ||
|
||
1. From the root folder of the project run `npm init` | ||
2. Run `node index.js` | ||
|
||
When we run the project a browser will open and we will observe a simulation of user journey. | ||
|
||
When INP gets triggered we will see similar output in the terminal: | ||
``` | ||
Running on the original page. | ||
Failed to load resource: the server responded with a status of 404 () | ||
Failed to load resource: the server responded with a status of 404 () | ||
Unsupported namespace or locale | ||
inp: 264 | ||
``` | ||
|
||
## Measure many times after a change: | ||
|
||
We have a shell script that can run a simulation multiple times. At the moment we run a simulation 10 times. | ||
|
||
Try: | ||
|
||
``` | ||
./run.sh | ||
``` | ||
|
||
## Override resources: | ||
|
||
In `index.js` we have a code fragment that looks like this: | ||
|
||
``` | ||
// Add event listener to intercept requests | ||
page.on("request", (interceptedRequest) => { | ||
// Check if the request is for the resource you want to override | ||
if (interceptedRequest.url().endsWith("example-js-of-interest.js")) { | ||
console.log("Intercepted and overriding: " + interceptedRequest.url()); | ||
// Create a response from a local file | ||
const overrideContent = fs.readFileSync(path.join(__dirname, "overrides", "example-js-of-interest.js"), "utf8"); | ||
interceptedRequest.respond({ | ||
status: 200, | ||
contentType: "application/javascript; charset=utf-8", | ||
body: overrideContent | ||
}); | ||
return; | ||
} | ||
// Allow all other requests to continue normally | ||
interceptedRequest.continue(); | ||
}); | ||
``` | ||
|
||
This allows us to load from filesystem our own version of some of the frontend files. | ||
|
||
## CPU throttling: | ||
|
||
In `DeviceEmulation.js` tweak: | ||
``` | ||
page.emulateCPUThrottling(4) | ||
``` | ||
|
||
## User-Agent string and screen size emulation: | ||
|
||
Tweak parameters in `DeviceEmulation.js`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
|
||
const puppeteer = require("puppeteer"); | ||
const { PuppeteerScreenRecorder } = require("puppeteer-screen-recorder"); | ||
|
||
const recording = false; | ||
|
||
const Cookies = require("./src/Cookies"); | ||
const CWV = require("./src/CWV"); | ||
const DeviceEmulation = require("./src/DeviceEmulation"); | ||
|
||
// TODO, Change here to the element you would like Puppeteer to interact with. | ||
const elementToInteractWith = "### ADD THE CSS SELECTOR HERE ###"; | ||
|
||
// TODO, Change here to the url you would like to load in Puppeteer. | ||
const navigateTo = "https://www.example.com/"; | ||
|
||
var args = process.argv.slice(2); | ||
|
||
let experiment = 0; | ||
|
||
if (args[0]) { | ||
const paramParts = args[0].split("="); | ||
|
||
if (paramParts[0] === "experiment") { | ||
experiment = parseInt(paramParts[1]); | ||
} | ||
} | ||
|
||
if (experiment === 0) { | ||
console.log("Running on the original page."); | ||
} | ||
else { | ||
console.log("Running experiment {" + experiment + "} on a modified page."); | ||
} | ||
|
||
(async() => { | ||
const browser = await puppeteer.launch({ headless: false }); | ||
|
||
const page = await browser.newPage(); | ||
|
||
if (recording) { | ||
// Configure the screen recorder | ||
const recorder = new PuppeteerScreenRecorder(page, { | ||
followNewTab: true, | ||
fps: 30, | ||
videoFrame: { | ||
width: 1080, | ||
height: 2400 | ||
} | ||
// Other configurations | ||
}); | ||
|
||
await recorder.start("output.mp4"); | ||
} | ||
|
||
await DeviceEmulation.emulate(page); | ||
|
||
// Listen for console events within the page and log them in Node.js context | ||
page.on("console", (msg) => { | ||
console.log(msg.text()); | ||
}); | ||
|
||
// Enable request interception | ||
await page.setRequestInterception(true); | ||
|
||
// Add event listener to intercept requests | ||
page.on("request", (interceptedRequest) => { | ||
// Check if the request is for the resource you want to override | ||
if (interceptedRequest.url().endsWith("example-js-of-interest.js")) { | ||
console.log("Intercepted and overriding: " + interceptedRequest.url()); | ||
|
||
// Create a response from a local file | ||
const overrideContent = fs.readFileSync(path.join(__dirname, "overrides", "example-js-of-interest.js"), "utf8"); | ||
interceptedRequest.respond({ | ||
status: 200, | ||
contentType: "application/javascript; charset=utf-8", | ||
body: overrideContent | ||
}); | ||
return; | ||
} | ||
|
||
// Allow all other requests to continue normally | ||
interceptedRequest.continue(); | ||
}); | ||
|
||
// Navigate to the page | ||
await page.goto(navigateTo); | ||
|
||
await CWV.attachCWV_Lib(page); | ||
|
||
await Cookies.setOptanonConsent(page); | ||
|
||
// Wait for a specified timeout in milliseconds | ||
await page.waitForTimeout(5000); // waits for 5 seconds | ||
|
||
// Wait for the element to be present in the DOM | ||
await page.waitForSelector(elementToInteractWith); | ||
|
||
// Click the input input | ||
await page.click(elementToInteractWith); | ||
await page.focus(elementToInteractWith); | ||
|
||
await page.waitForTimeout(5); // waits for 5 seconds | ||
|
||
// Execute JS code after the timeout | ||
await page.evaluateHandle(() => { | ||
window.webVitals.getINP(function(info) { | ||
if (info.value) { | ||
console.log("inp: " + info.value); | ||
} | ||
else { | ||
console.log("inp: not measured"); | ||
} | ||
}, | ||
{ | ||
reportAllChanges: true | ||
} | ||
); | ||
}); | ||
|
||
await page.waitForTimeout(5000); // waits for 5 seconds | ||
|
||
if (recording) { | ||
// Stop recording | ||
await recorder.stop(); | ||
} | ||
|
||
// You can close the browser after a timeout, or after some specific action | ||
// that would ensure all metrics have been captured. | ||
await browser.close(); | ||
})(); |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// Override JS content |
Oops, something went wrong.