The same five components for Vue 3, built on
@artisanpack-ui/vue,
reading the same JSON endpoints through the same shared
layer, and rendering the same states as the
React and Livewire sets.
They ship as single-file components under resources/js/vue, as TypeScript
sources rather than as a build, for the same reason the React set does: they
take their styling from the host application's Tailwind and daisyUI theme.
Install
php artisan vendor:publish --tag=pagespeed-insights-js
npm install @artisanpack-ui/vue
<script setup lang="ts">
import {
ScoreCard,
CoreWebVitalsCard,
OpportunitiesTable,
TrendChart,
UrlManager,
} from '@/../js/vendor/pagespeed-insights/vue'
</script>
<template>
<ScoreCard url="https://example.com/pricing" />
<CoreWebVitalsCard url="https://example.com/pricing" />
<OpportunitiesTable url="https://example.com/pricing" />
<TrendChart url="https://example.com/pricing" />
<UrlManager />
</template>
Props
The same props as the React set, spelled as Vue props:
| Prop | Components | Type | Default |
|---|---|---|---|
url |
all but UrlManager |
string |
— |
strategy |
score card, vitals, opportunities | 'mobile' | 'desktop' |
'mobile' |
endpoint-base |
all | string |
/pagespeed |
fetch-impl |
all | typeof fetch |
window.fetch |
csrf-token |
score card, URL manager | string | null |
<meta name="csrf-token"> |
initial-metric |
trend chart | string |
'performance' |
initial-range |
trend chart | number |
90 |
allow-running-tests |
score card | boolean |
true |
One difference from React: onResultStored is a component event here, so a
finished run is heard with @result-stored rather than by passing a function
down.
<ScoreCard url="https://example.com/pricing" @result-stored="( id ) => refreshMyPanel( id )" />
Composables
The composables the components are built from are exported alongside them:
import { usePsiResource, usePsiResultStored } from '@/../js/vendor/pagespeed-insights/vue'
usePsiResource(deps, load)— the load lifecycle. It takes its dependencies as an explicit getter rather than inferring them, so a value read after anawaitinsideloadcannot silently stop being tracked.usePsiResultStored(handler)— the finished-run announcement. It unsubscribes with the surrounding effect scope.
Two things that differ beneath the surface
Neither changes what renders:
- The components import the library from
@artisanpack-ui/vuerather than from its/layout,/display, and/formsubpaths, which is where the React half imports its own. The published Vue package declares those subpaths but ships no declaration file for any of them, and losing the component props' types is a worse trade than importing a barrel a bundler will tree-shake anyway. - The library's Vue
Stattakes no colour prop, so a banded number is coloured with a written-out[&_.stat-value]:text-successclass rather than withcolor.
Shared fetch layer, events, and CSRF
Identical to the React set — the shared layer is framework-free and consumed by both. See:
- React components → Shared fetch layer
- React components → Keeping the panels in step
- React components → CSRF
Type checking
npm run type-check # vue-tsc --noEmit

