Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] Performance Dashboard (Web Vitals) #1098

Draft
wants to merge 28 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7f5371a
Optimization Detective: Store web vitals information
swissspidy Mar 28, 2024
47899b3
Adjust PHPStan annotations
swissspidy Mar 28, 2024
85982d1
Proof of concept for a performance dashboard
swissspidy Mar 28, 2024
fe77c77
Apply suggestions from code review
swissspidy Mar 28, 2024
fe45140
Color
swissspidy Mar 28, 2024
8790332
Apply suggestions from code review
swissspidy Apr 9, 2024
70fb83d
Revert debug leftover
swissspidy Apr 9, 2024
aca301e
Do isLCP check later
swissspidy Apr 9, 2024
1ad70ee
Merge branch 'trunk' into try/performance-dashboard
swissspidy Apr 9, 2024
3beeec2
Add dashboard widget POC
swissspidy Apr 10, 2024
7acba90
Merge branch 'trunk' into try/performance-dashboard
swissspidy Apr 23, 2024
c505fa5
Formatting
swissspidy Apr 23, 2024
8f22058
Merge branch 'trunk' into try/performance-dashboard
swissspidy May 7, 2024
0b70fd6
Merge branch 'trunk' into try/performance-dashboard
swissspidy May 8, 2024
14452d0
Merge branch 'trunk' into try/performance-dashboard
swissspidy Jul 9, 2024
e9b061f
Move to own plugin
swissspidy Jul 9, 2024
323b1d5
Fixes
swissspidy Jul 9, 2024
6638f32
Lint fixes
swissspidy Jul 9, 2024
d353818
More fixes
swissspidy Jul 9, 2024
75f7dfb
Use `wp_list_sort`
swissspidy Jul 9, 2024
1fc72ea
Add `array_filter`
swissspidy Jul 9, 2024
239202c
Test fixes
swissspidy Jul 9, 2024
bc81d94
Fix alignment
swissspidy Jul 9, 2024
b6b7bab
Add missing comma
swissspidy Jul 10, 2024
0759f4e
Merge branch 'trunk' into try/performance-dashboard
swissspidy Jul 10, 2024
92180a2
Begin adding stuff for custom storage
swissspidy Jul 10, 2024
9608512
Adjust todo
swissspidy Jul 15, 2024
ed3430d
Merge branch 'trunk' into try/performance-dashboard
swissspidy Jul 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,164 changes: 1,106 additions & 58 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
"npm": ">=10.2.3"
},
"dependencies": {
"react-google-charts": "^4.0.1",
"web-vitals": "3.5.0"
},
"devDependencies": {
"@octokit/rest": "^19.0.5",
"@wordpress/api-fetch": "^6.51.0",
"@wordpress/components": "^27.2.0",
"@wordpress/dom-ready": "^3.54.0",
"@wordpress/element": "^5.31.0",
"@wordpress/env": "^8.13.0",
"@wordpress/i18n": "^4.54.0",
"@wordpress/scripts": "^26.19.0",
"chalk": "^4.1.2",
"commander": "^9.4.1",
Expand All @@ -37,6 +43,7 @@
"build:plugin:optimization-detective": "webpack --mode production --env plugin=optimization-detective",
"build:plugin:speculation-rules": "webpack --mode production --env plugin=speculation-rules",
"build:plugin:webp-uploads": "webpack --mode production --env plugin=webp-uploads",
"start:plugin:optimization-detective": "webpack --mode development --watch --env plugin=optimization-detective",
"format-js": "wp-scripts format",
"lint-js": "wp-scripts lint-js",
"format-php": "composer format",
Expand Down
86 changes: 67 additions & 19 deletions plugins/optimization-detective/class-od-url-metric.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,27 @@
/**
* Representation of the measurements taken from a single client's visit to a specific URL.
*
* @phpstan-type RectData array{ width: int, height: int }
* @phpstan-type ElementData array{
* isLCP: bool,
* isLCPCandidate: bool,
* xpath: string,
* intersectionRatio: float,
* intersectionRect: RectData,
* boundingClientRect: RectData,
* }
* @phpstan-type Data array{
* url: string,
* timestamp: int,
* viewport: RectData,
* elements: ElementData[]
* }
* @phpstan-type RectData array{ width: int, height: int }
* @phpstan-type ElementData array{
* isLCP: bool,
* isLCPCandidate: bool,
* xpath: string,
* intersectionRatio: float,
* intersectionRect: RectData,
* boundingClientRect: RectData,
* }
* @phpstan-type Data array{
* url: string,
* timestamp: int,
* viewport: RectData,
* elements: ElementData[]
* }
* @phpstan-type WebVitalData array{
* LCP: int,
* CLS: int,
* INP: int,
* TTFB: int,
* }
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 0.1.0
* @access private
Expand All @@ -38,7 +44,8 @@ final class OD_URL_Metric implements JsonSerializable {
/**
* Data.
*
* @var Data
* @var array
* @phpstan-var Data
*/
private $data;

Expand Down Expand Up @@ -148,6 +155,34 @@ public static function get_json_schema(): array {
'additionalProperties' => false,
),
),
'webVitals' => array(
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
'description' => __( 'Web vitals metrics', 'optimization-detective' ),
'type' => 'object',
'required' => true,
'properties' => array(
// See the URLMetrics in detect.js.
'type' => 'object',
'properties' => array(
'LCP' => array(
'type' => 'number',
'required' => false,
),
'CLS' => array(
'type' => 'number',
'required' => false,
),
'TTFB' => array(
'type' => 'number',
'required' => false,
),
'INP' => array(
'type' => 'number',
'required' => false,
),
swissspidy marked this conversation as resolved.
Show resolved Hide resolved
),
'additionalProperties' => false,
),
),
),
'additionalProperties' => false,
);
Expand All @@ -165,7 +200,8 @@ public function get_url(): string {
/**
* Gets viewport data.
*
* @return RectData Viewport data.
* @return array Viewport data.
* @phpstan-return RectData
*/
public function get_viewport(): array {
return $this->data['viewport'];
Expand All @@ -192,16 +228,28 @@ public function get_timestamp(): float {
/**
* Gets elements.
*
* @return ElementData[] Elements.
* @return array Elements.
* @phpstan-return ElementData[]
*/
public function get_elements(): array {
return $this->data['elements'];
}

/**
* Gets web vitals.
*
* @return array Web Vitals.
* @phpstan-return WebVitalData
*/
public function get_web_vitals(): array {
return $this->data['webVitals'];
}
swissspidy marked this conversation as resolved.
Show resolved Hide resolved

/**
* Specifies data which should be serialized to JSON.
*
* @return Data Exports to be serialized by json_encode().
* @return array Exports to be serialized by json_encode().
* @phpstan-return Data
*/
public function jsonSerialize(): array {
return $this->data;
Expand Down
82 changes: 82 additions & 0 deletions plugins/optimization-detective/dashboard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* Optimizing for Optimization Detective.
*
* @package optimization-detective
* @since 0.1.0
*/

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

function od_add_submenu_page() {
add_submenu_page(
'index.php',
__( 'Performance', 'optimization-detective' ),
__( 'Performance', 'optimization-detective' ),
'manage_options',
'od-performance-dashboard',
'od_render_dashboard_page'
);
}

add_action( 'admin_menu', 'od_add_submenu_page' );

function od_render_dashboard_page() {
$asset_file = plugin_dir_path( __FILE__ ) . 'build/performance-dashboard.asset.php';

$asset = require $asset_file;

wp_enqueue_style( 'wp-components' );

wp_enqueue_script(
'od-performance-dashboard',
plugin_dir_url( __FILE__ ) . 'build/performance-dashboard.js',
$asset['dependencies'],
$asset['version'],
array(
'in_footer' => true,
'strategy' => 'defer',
)
);

$recent_entries = get_posts(
array(
'post_type' => OD_URL_Metrics_Post_Type::SLUG,
'post_status' => 'publish',
'numberposts' => 10,
'suppress_filters' => false,
'no_found_rows' => true,
'cache_results' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'lazy_load_term_meta' => false,
)
);

$options = array_map( function( $entry ) {
return array(
'value' => $entry->ID,
'label' => $entry->post_title,
);
}, $recent_entries );

wp_localize_script(
'od-performance-dashboard',
'performanceDashboard',
array(
'options' => $options,
'homeUrl' => home_url( '/' ),
'postType' => OD_URL_Metrics_Post_Type::SLUG,
)
);
?>
<div class="wrap">
<h2><?php esc_html_e( 'Performance Dashboard', 'optimization-detective' ); ?></h2>
<div id="od-performance-dashboard">
<?php esc_html_e( 'Loading…', 'optimization-detective' ); ?>
</div>
</div>
<?php
}
Loading
Loading