1- /* eslint-disable no-console */
2-
3- const fs = require ( 'fs' ) ;
4- const puppeteer = require ( 'puppeteer' ) ;
5- const pages = require ( './pages.json' ) ;
6-
1+ import { readFileSync , writeFileSync , existsSync , mkdirSync } from 'fs' ;
2+ import { chromium , type Page } from 'playwright' ;
3+ import { fetch } from 'undici' ;
4+ import pages from './pages.json' with { type : 'json' } ;
5+
6+ type InputPageData = {
7+ href : string ;
8+ tags : string [ ] ;
9+ size : 'small' | 'large' ;
10+ repo ?: string ;
11+ } ;
12+ type PageData = InputPageData & {
13+ title ?: string ;
14+ imgSrc ?: string ;
15+ perf ?: {
16+ score ?: number ;
17+ inpMs ?: number ;
18+ clsScore ?: number ;
19+ ttfbMs ?: number ;
20+ fcpDisplay ?: string ;
21+ fcpScore ?: number ;
22+ lcpDisplay ?: string ;
23+ lcpScore ?: number ;
24+ ttiDisplay ?: string ;
25+ ttiScore ?: number ;
26+ ttiTime ?: number ;
27+ } ;
28+ version ?: string ;
29+ ts : number ;
30+ } ;
731const OUTPUT_JSON = 'src/routes/(ecosystem)/showcase/generated-pages.json' ;
832async function captureMultipleScreenshots ( ) {
9- if ( ! fs . existsSync ( 'public/showcases' ) ) {
10- fs . mkdirSync ( 'public/showcases' ) ;
33+ if ( ! existsSync ( 'public/showcases' ) ) {
34+ mkdirSync ( 'public/showcases' ) ;
1135 }
1236
1337 let browser = null ;
1438 const output = [ ] ;
1539 try {
1640 // launch headless Chromium browser
17- browser = await puppeteer . launch ( {
41+ browser = await chromium . launch ( {
1842 headless : true ,
19- incognito : true ,
2043 } ) ;
21- const incognito = await browser . createBrowserContext ( ) ;
22- let existingJson = [ ] ;
44+ const context = await browser . newContext ( ) ;
45+ let existingJson : PageData [ ] = [ ] ;
2346 try {
24- const data = fs . readFileSync ( OUTPUT_JSON , 'utf8' ) ;
25- existingJson = JSON . parse ( data ) ;
47+ const data = readFileSync ( OUTPUT_JSON , 'utf8' ) ;
48+ existingJson = JSON . parse ( data ) as PageData [ ] ;
2649 } catch {
2750 // ignore
2851 }
2952
3053 for ( const pageData of pages ) {
31- let page ;
54+ let page : Page ;
3255 try {
33- page = await incognito . newPage ( ) ;
34- page . setUserAgent (
35- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
36- ) ;
56+ page = await context . newPage ( ) ;
57+ // page.setUserAgent(
58+ // 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
59+ // );
3760
3861 // set viewport width and height
39- await page . setViewport ( {
62+ await page . setViewportSize ( {
4063 width : 1440 ,
4164 height : 980 ,
4265 } ) ;
4366
4467 const href = pageData . href ;
4568 const existing = existingJson . find ( ( item ) => item . href === href ) ;
46- if ( existing ) {
69+ if ( existing && existing . ts - Date . now ( ) < 1000 * 60 * 60 * 24 * 7 ) {
4770 console . log ( 'Skipping page' , href ) ;
4871
4972 output . push ( {
@@ -58,12 +81,13 @@ async function captureMultipleScreenshots() {
5881 await page . goto ( href ) ;
5982
6083 const title = await page . title ( ) ;
61- const html = await page . $ ( 'html' ) ;
84+ const html = page . locator ( 'html' ) ;
6285 const hasContainer = await html . evaluate ( ( node ) => node . hasAttribute ( 'q:container' ) ) ;
6386 if ( ! hasContainer ) {
6487 console . warn ( '❌ Not Qwik Site' , href ) ;
6588 continue ;
6689 }
90+ const version = await html . getAttribute ( 'q:version' ) ;
6791 const filename = href
6892 . replace ( 'https://' , '' )
6993 . replace ( '/' , '_' )
@@ -72,12 +96,12 @@ async function captureMultipleScreenshots() {
7296 . toLowerCase ( ) ;
7397
7498 await wait ( 5000 ) ;
75- const path = `public/showcases/${ filename } .webp ` ;
99+ const path = `public/showcases/${ filename } .jpeg ` ;
76100 const [ pagespeedOutput , _ ] = await Promise . all ( [
77101 getPagespeedData ( href ) ,
78102 page . screenshot ( {
79103 path : path ,
80- type : 'webp ' ,
104+ type : 'jpeg ' ,
81105 quality : 50 ,
82106 } ) ,
83107 ] ) ;
@@ -119,33 +143,34 @@ async function captureMultipleScreenshots() {
119143 ttiTime,
120144 } ;
121145 output . push ( {
146+ ...pageData ,
147+ ts : Date . now ( ) ,
122148 title,
123- imgSrc : `/showcases/${ filename } .webp ` ,
149+ imgSrc : `/showcases/${ filename } .jpeg ` ,
124150 perf,
125- ... pageData ,
151+ version ,
126152 } ) ;
127153 console . log ( `✅ ${ title } - (${ href } )` ) ;
128154 } catch ( err ) {
129155 console . error ( err ) ;
130156 } finally {
131- if ( page ) {
157+ if ( page ! ) {
132158 await page . close ( ) ;
133159 }
134160 }
135161 }
136162 } catch ( err ) {
137- console . log ( `❌ Error: ${ err . message } ` ) ;
163+ console . log ( `❌ Error: ${ ( err as Error ) ? .message || err } ` ) ;
138164 } finally {
139165 if ( browser ) {
140166 await browser . close ( ) ;
141167 }
142168 console . log ( `\n🎉 ${ pages . length } screenshots captured.` ) ;
143169 }
144- fs . writeFileSync ( OUTPUT_JSON , JSON . stringify ( output , undefined , 2 ) + '\n' ) ;
170+ writeFileSync ( OUTPUT_JSON , JSON . stringify ( output , undefined , 2 ) + '\n' ) ;
145171}
146172
147- async function getPagespeedData ( url ) {
148- const { fetch } = await import ( 'undici' ) ;
173+ async function getPagespeedData ( url : string ) {
149174 const requestURL = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${ encodeURIComponent (
150175 url
151176 ) } &key=AIzaSyApBC9gblaCzWrtEBgHnZkd_B37OF49BfM&category=PERFORMANCE&strategy=MOBILE`;
@@ -157,11 +182,15 @@ async function getPagespeedData(url) {
157182 if ( ! res . ok ) {
158183 throw new Error ( await res . text ( ) ) ;
159184 }
160- return res . json ( ) ;
185+ return res . json ( ) as Promise < {
186+ lighthouseResult : any ;
187+ loadingExperience : any ;
188+ pagespeedResult : any ;
189+ } > ;
161190 } ) ;
162191}
163192captureMultipleScreenshots ( ) ;
164193
165- function wait ( ms ) {
194+ function wait ( ms : number ) {
166195 return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
167196}
0 commit comments