From de4280066b2ebfccfeba93f93b90150c8068b03f Mon Sep 17 00:00:00 2001 From: ashfame Date: Tue, 1 Oct 2024 09:53:59 +0400 Subject: [PATCH 1/3] wip persistence storage --- package-lock.json | 208 +++++++++++++++++++--------------- package.json | 4 +- src/ui/preview/Playground.tsx | 68 ++++++++++- 3 files changed, 181 insertions(+), 99 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9dacddf4..b33aec7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,9 @@ "dependencies": { "@wordpress/block-library": "^9.7.0", "@wordpress/blocks": "^13.7.0", - "@wp-playground/client": "^0.9.39", + "@wp-playground/client": "^0.9.45", + "@wp-playground/common": "^0.9.45", + "@wp-playground/storage": "^0.9.45", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.1" @@ -4095,15 +4097,15 @@ "license": "MIT" }, "node_modules/@php-wasm/fs-journal": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/fs-journal/-/fs-journal-0.9.39.tgz", - "integrity": "sha512-3Dghh14h1WtGTB3Y51+EhoyHKDIBrtbkIhbt6U6DOms9/DQvQuCJ80ts/Ri2thtxTgbk2JdHMmp7gx6NPpJU/g==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/fs-journal/-/fs-journal-0.9.45.tgz", + "integrity": "sha512-+rQa4xbpQDj8XH2MdytCzFl7l8pDS2HeaAXAuIuGddi8S3zMNT4p/WVkobdVDMB7FJPDNa0OGGPaIaFbxbBmYQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/node": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", + "@php-wasm/logger": "0.9.45", + "@php-wasm/node": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", "comlink": "^4.4.1", "express": "4.19.2", "ini": "4.1.2", @@ -4116,12 +4118,12 @@ } }, "node_modules/@php-wasm/logger": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-0.9.39.tgz", - "integrity": "sha512-uTsLYBioX1yT//XGbQsXX6hrg4zKvsSGSNb4dlLdV4zgvwTVYYePyQ6zPdiMtAzn4pLJBxnnYXHnc3n2yyJrSA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/logger/-/logger-0.9.45.tgz", + "integrity": "sha512-nQaOLdtwbq82EsMGgpD+6Xo3mOiWG+0YgOJhmn9SMPrwQw+WjXviATSbmUMcHBvX+wvTucmWKKiDrZSppS11zQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/node-polyfills": "0.9.39" + "@php-wasm/node-polyfills": "0.9.45" }, "engines": { "node": ">=18.18.0", @@ -4129,17 +4131,17 @@ } }, "node_modules/@php-wasm/node": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-0.9.39.tgz", - "integrity": "sha512-pB/soBPrNiHwVop3UlDLpezvklpQNFKUIFVMQdmAulrfzSUKFC+lT/JMIHpNnQCxbZmfW7aByfO1u6sRG4tuOw==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/node/-/node-0.9.45.tgz", + "integrity": "sha512-QMekLM6zjQM9UvXOHwL47XKzPjD7KWZ5pe0WPntx30vtiQeXRXu4csGn4s0/cjrqnXyPbwt4X89gyw++9SwH7A==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/node-polyfills": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", - "@wp-playground/common": "0.9.39", - "@wp-playground/wordpress": "0.9.39", + "@php-wasm/logger": "0.9.45", + "@php-wasm/node-polyfills": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@wp-playground/common": "0.9.45", + "@wp-playground/wordpress": "0.9.45", "comlink": "^4.4.1", "express": "4.19.2", "ini": "4.1.2", @@ -4152,19 +4154,19 @@ } }, "node_modules/@php-wasm/node-polyfills": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/node-polyfills/-/node-polyfills-0.9.39.tgz", - "integrity": "sha512-WDMIEa761NzkI4Ydp83CYGPFwOwvztavMdFDyH/omcD800QpL1JDU/kT3p7MQBJLF9z+aV4CyY84HV0N7AGzUg==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/node-polyfills/-/node-polyfills-0.9.45.tgz", + "integrity": "sha512-rUUEBQjxXtMcH0Q8cWWy3isJiffjHlWOmeAdmGKYv4KKZDHcuhpib2qSZ+369JQuke0rj9NU67KO0fnnbmAYyw==", "license": "GPL-2.0-or-later" }, "node_modules/@php-wasm/progress": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-0.9.39.tgz", - "integrity": "sha512-8HHbrloXI98eRB2ZOr27nUSZvp7fE8dKbmMD2WUE814zXevzV+W8CrZCH3gqYV3rczP1MG4rifGVdn7QQESynA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/progress/-/progress-0.9.45.tgz", + "integrity": "sha512-Q7iyCi+cukH5EJ8ofNAo79UwG2I3E/EB85bo/siN9dOrXtAZwFyR4ud6zL/dvpw8VXdhBUg17mTSTUEOnw75Xg==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/node-polyfills": "0.9.39" + "@php-wasm/logger": "0.9.45", + "@php-wasm/node-polyfills": "0.9.45" }, "engines": { "node": ">=18.18.0", @@ -4172,9 +4174,9 @@ } }, "node_modules/@php-wasm/scopes": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-0.9.39.tgz", - "integrity": "sha512-6TPGsHEq9EVEPU4X1smc4N5tt1CORPISS//wlmIHaoWoHdAKCdOrlfoerbt9b3oIspaaSINATSrb3y8GgIR5nw==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/scopes/-/scopes-0.9.45.tgz", + "integrity": "sha512-I7QlgDFwYdrhI4mgENqCrt8iLVnukQ6jMNP62npegi3NlF85L0gs4lQLrOPWX86tEn3SoeyXX5GTWk6kTpsb7Q==", "license": "GPL-2.0-or-later", "engines": { "node": ">=16.15.1", @@ -4182,26 +4184,26 @@ } }, "node_modules/@php-wasm/stream-compression": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-0.9.39.tgz", - "integrity": "sha512-GBP40Fi8bOvHygFUNW3B7QjgzGW6rEq6SOIZ/t2kI7XyCWNQSHiAoDIu9BgeX7wzB5CD82Bp0Est6IAwYLnhNA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/stream-compression/-/stream-compression-0.9.45.tgz", + "integrity": "sha512-egVzCldQwxWsSLUmMGbFklmKWaVg70L8kD6x6i8rYvK+62soEKdVJNFoeGzUvOAq+RgjshzgygsrtQ1d8uO1Mg==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/node-polyfills": "0.9.39", - "@php-wasm/util": "0.9.39" + "@php-wasm/node-polyfills": "0.9.45", + "@php-wasm/util": "0.9.45" } }, "node_modules/@php-wasm/universal": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-0.9.39.tgz", - "integrity": "sha512-Hu6nPLEQbK10ZXFpSJzX0pHBr9lBfi4Kdvv7wsL7l4BQzpl25ToSKNNoqWelIq7m7xN32EqMzL68gxwXH+kd/g==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/universal/-/universal-0.9.45.tgz", + "integrity": "sha512-R+gkhn7/e0VG+SfQbEBl/3YxcsoyEEs+ditLGSwDdwxAPgv1S2iEvwQc6fad2p4cRYBHw/lowJQh3fR0275K8w==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/node-polyfills": "0.9.39", - "@php-wasm/progress": "0.9.39", - "@php-wasm/stream-compression": "0.9.39", - "@php-wasm/util": "0.9.39", + "@php-wasm/logger": "0.9.45", + "@php-wasm/node-polyfills": "0.9.45", + "@php-wasm/progress": "0.9.45", + "@php-wasm/stream-compression": "0.9.45", + "@php-wasm/util": "0.9.45", "comlink": "^4.4.1", "ini": "4.1.2" }, @@ -4211,25 +4213,25 @@ } }, "node_modules/@php-wasm/util": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-0.9.39.tgz", - "integrity": "sha512-pIniF3N5IMKgOIUpoBwo5djULIMG54cYkWQPAKopCPCun2T9McjJ8AetTrvYrbldueBWsNi06YeD8LTQU45HCg==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/util/-/util-0.9.45.tgz", + "integrity": "sha512-U1hlul8DKBF325M9UKODOfokURxffrs5TDTencnVO6W0aiLFhQZag2n2MzIfH3y9unCZOXI0oaUeuB5zonXP9w==", "engines": { "node": ">=18.18.0", "npm": ">=8.11.0" } }, "node_modules/@php-wasm/web": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/web/-/web-0.9.39.tgz", - "integrity": "sha512-F7KDGoJYnYO+CfBeUtcifDLiZj6YFoRC33YUX8xmMiYCM7Y+7kz4NToBdoONRX73MtnSaZPyS9IC535d/vPx9A==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/web/-/web-0.9.45.tgz", + "integrity": "sha512-yqPhwfVGltg13Kb4yYAna3dyUeeV5NHHmOs+Q9gLo+mwkhwRVVigblpPG786KjIJeVPJeZ3mJHBEsxRf6otnjQ==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/fs-journal": "0.9.39", - "@php-wasm/logger": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", - "@php-wasm/web-service-worker": "0.9.39", + "@php-wasm/fs-journal": "0.9.45", + "@php-wasm/logger": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@php-wasm/web-service-worker": "0.9.45", "comlink": "^4.4.1", "express": "4.19.2", "ini": "4.1.2", @@ -4242,12 +4244,12 @@ } }, "node_modules/@php-wasm/web-service-worker": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-0.9.39.tgz", - "integrity": "sha512-I4pBDAmzzCRmINthMyiZoKdek2dtP/1YWgX9arRK7JAPDlZ4se63EgaJItvmJiFLxQ00B4UpkF0HiMreBzSGKA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@php-wasm/web-service-worker/-/web-service-worker-0.9.45.tgz", + "integrity": "sha512-HmDFd/NnxTUO/yUYNbdD5E7Us0tZurf0kxGR0OyberKdtcVu73g2jjdPkN0wWPJFFyFC9GXtrPfeTe2s+Mc1DA==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/scopes": "0.9.39" + "@php-wasm/scopes": "0.9.45" }, "engines": { "node": ">=18.18.0", @@ -10081,19 +10083,19 @@ } }, "node_modules/@wp-playground/blueprints": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-0.9.39.tgz", - "integrity": "sha512-aIauzNdkYV7YCJSVFrLh3TjM+SqNgg9SElM4/2zUIwLvBa0z7KXReZps51Lx39BdYMu9uZ79Eo9u13hk1Te26A==", - "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/node": "0.9.39", - "@php-wasm/node-polyfills": "0.9.39", - "@php-wasm/progress": "0.9.39", - "@php-wasm/scopes": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", - "@wp-playground/common": "0.9.39", - "@wp-playground/wordpress": "0.9.39", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@wp-playground/blueprints/-/blueprints-0.9.45.tgz", + "integrity": "sha512-5gRY8QyBe4+bb+0N+XBOahAGImCUSGqc/uyU6u9V7wgd49a/4p67jKxZ725zF3wSEQCQQukAVg5xFTTi4j+sbw==", + "dependencies": { + "@php-wasm/logger": "0.9.45", + "@php-wasm/node": "0.9.45", + "@php-wasm/node-polyfills": "0.9.45", + "@php-wasm/progress": "0.9.45", + "@php-wasm/scopes": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@wp-playground/common": "0.9.45", + "@wp-playground/wordpress": "0.9.45", "ajv": "8.12.0", "comlink": "^4.4.1", "ini": "4.1.2" @@ -10104,17 +10106,17 @@ } }, "node_modules/@wp-playground/client": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@wp-playground/client/-/client-0.9.39.tgz", - "integrity": "sha512-GEugMN7TaeRAZjUljtafYOv2YcPf+ufqxImEfdlwBOCDxJkLoehte4LuYwGBIrfOQMgx3bf7h93nf8vN0BxNPA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@wp-playground/client/-/client-0.9.45.tgz", + "integrity": "sha512-Nr7xS4RWYKs1vgfymxkMnpBG3gI2wCgLKP45uiG51iMWk7D4BlfbHi6U/ahEOINVy+9Z1GrPpY6gR7YFbzoYnA==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/logger": "0.9.39", - "@php-wasm/progress": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", - "@php-wasm/web": "0.9.39", - "@wp-playground/blueprints": "0.9.39", + "@php-wasm/logger": "0.9.45", + "@php-wasm/progress": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@php-wasm/web": "0.9.45", + "@wp-playground/blueprints": "0.9.45", "ajv": "8.12.0", "comlink": "^4.4.1", "ini": "4.1.2", @@ -10126,13 +10128,13 @@ } }, "node_modules/@wp-playground/common": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-0.9.39.tgz", - "integrity": "sha512-Z7Co6aNnMDL2/YrAhw16AzY0jRohswmuY8rUsrm+HWrV+chMvwtJhpNXN0IPP7COW5wOU+EGo3iPCADEtKbXjQ==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@wp-playground/common/-/common-0.9.45.tgz", + "integrity": "sha512-0LeK1RLGDuD28W5OcOgxr9e8zRw+xogeorQ9a3agyV1wI+G5+hs/XotVskfDv0klHjvJA48LLqN1Z+SAGyBCYg==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", "comlink": "^4.4.1", "ini": "4.1.2" }, @@ -10141,16 +10143,34 @@ "npm": ">=8.11.0" } }, + "node_modules/@wp-playground/storage": { + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@wp-playground/storage/-/storage-0.9.45.tgz", + "integrity": "sha512-2SGzjGqLRrmitfSd7sxYxhjbob/P2OdopE+/UUi2pj6HGJdLjEbuTV8tNUqDlYYV3p0H/TvD0ai1+aMAjvfZUg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@php-wasm/node-polyfills": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@php-wasm/web": "0.9.45", + "comlink": "^4.4.1", + "express": "4.19.2", + "ini": "4.1.2", + "octokit": "3.1.1", + "ws": "8.18.0", + "yargs": "17.7.2" + } + }, "node_modules/@wp-playground/wordpress": { - "version": "0.9.39", - "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-0.9.39.tgz", - "integrity": "sha512-SVvH6P6nD3+9YZyLtJFGf2VcyitLnUVJxoqLyT4J/jX94RKIb1woQrXRz32KdR9yQ6MxnqsaYytR7an2356abA==", + "version": "0.9.45", + "resolved": "https://registry.npmjs.org/@wp-playground/wordpress/-/wordpress-0.9.45.tgz", + "integrity": "sha512-ttpHGUa826DoHACizrCokqvJtPo1MmMNcAGoMkSawo//5WIHsBF8lF7AuaqmOziBXhsW7FMWh12K5dvyFsD3/Q==", "license": "GPL-2.0-or-later", "dependencies": { - "@php-wasm/node": "0.9.39", - "@php-wasm/universal": "0.9.39", - "@php-wasm/util": "0.9.39", - "@wp-playground/common": "0.9.39", + "@php-wasm/node": "0.9.45", + "@php-wasm/universal": "0.9.45", + "@php-wasm/util": "0.9.45", + "@wp-playground/common": "0.9.45", "comlink": "^4.4.1", "express": "4.19.2", "ini": "4.1.2", diff --git a/package.json b/package.json index 299f361d..4a959ab1 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,9 @@ "dependencies": { "@wordpress/block-library": "^9.7.0", "@wordpress/blocks": "^13.7.0", - "@wp-playground/client": "^0.9.39", + "@wp-playground/client": "^0.9.45", + "@wp-playground/storage": "^0.9.45", + "@wp-playground/common": "^0.9.45", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.1" diff --git a/src/ui/preview/Playground.tsx b/src/ui/preview/Playground.tsx index eef7f0e7..1d6098f5 100644 --- a/src/ui/preview/Playground.tsx +++ b/src/ui/preview/Playground.tsx @@ -4,8 +4,12 @@ import { StartPlaygroundOptions, startPlaygroundWeb, StepDefinition, + MountDescriptor, } from '@wp-playground/client'; +// @ts-ignore +import { directoryHandleFromMountDevice } from '@wp-playground/storage'; + const playgroundIframeId = 'playground'; export function Playground( props: { @@ -51,11 +55,32 @@ async function initPlayground( slug: string, blogName: string ): Promise< PlaygroundClient > { + const mountDescriptor: MountDescriptor = { + device: { + type: 'opfs', + path: '/try-wp-' + slug, + }, + mountpoint: '/wordpress', + }; + + let isWordPressInstalled = false; + if ( mountDescriptor ) { + try { + isWordPressInstalled = await playgroundAvailableInOpfs( + await directoryHandleFromMountDevice( mountDescriptor.device ) + ); + } catch ( e ) { + console.error( e ); + } + } + + console.info( 'isWordPressInstalled', isWordPressInstalled ); + const options: StartPlaygroundOptions = { iframe, - remoteUrl: - 'https://playground.wordpress.net/remote.html?storage=browser', - siteSlug: slug, + remoteUrl: `https://playground.wordpress.net/remote.html`, + mounts: [ mountDescriptor ], + shouldInstallWordPress: ! isWordPressInstalled, blueprint: { login: true, steps: steps(), @@ -66,7 +91,7 @@ async function initPlayground( }; const client: PlaygroundClient = await startPlaygroundWeb( options ); - await client.isReady; + await client.isReady(); return client; } @@ -189,3 +214,38 @@ $post_id = wp_insert_post(array( wp_set_object_terms($post_id, $term_id, 'wp_theme'); `; } + +/** + * Copied from https://github.com/WordPress/wordpress-playground/blob/8140715a273cefc503b87604e8ae397e112bfe92/packages/playground/website/src/lib/state/redux/boot-site-client.ts#L225 + * since its currently not exported in a public npm package + * + * @param dirHandle + */ +async function playgroundAvailableInOpfs( + dirHandle: FileSystemDirectoryHandle +) { + // Run this loop just to trigger an exception if the directory handle is no good. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for await ( const _ of dirHandle.keys() ) { + break; + } + + try { + /** + * Assume it's a Playground directory if these files exist: + * - wp-config.php + * - wp-content/database/.ht.sqlite + */ + await dirHandle.getFileHandle( 'wp-config.php', { create: false } ); + const wpContent = await dirHandle.getDirectoryHandle( 'wp-content', { + create: false, + } ); + const database = await wpContent.getDirectoryHandle( 'database', { + create: false, + } ); + await database.getFileHandle( '.ht.sqlite', { create: false } ); + } catch ( e ) { + return false; + } + return true; +} From 4d27df8fd7accdfb5a8a3db744c195f9c9e7bed5 Mon Sep 17 00:00:00 2001 From: ashfame Date: Tue, 1 Oct 2024 14:15:52 +0400 Subject: [PATCH 2/3] prevent double initialization of playground --- src/ui/preview/Playground.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ui/preview/Playground.tsx b/src/ui/preview/Playground.tsx index 1d6098f5..ee5bbc13 100644 --- a/src/ui/preview/Playground.tsx +++ b/src/ui/preview/Playground.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { PlaygroundClient, StartPlaygroundOptions, @@ -20,16 +20,20 @@ export function Playground( props: { } ) { const { slug, className, blogName, onReady } = props; + const initializationRef = useRef( false ); + useEffect( () => { const iframe = document.getElementById( playgroundIframeId ); if ( ! ( iframe instanceof HTMLIFrameElement ) ) { throw Error( 'Playground container element must be an iframe' ); } - if ( iframe.src !== '' ) { - // Playground is already started. + if ( iframe.src !== '' || initializationRef.current ) { + // Playground is already started or initialization has been attempted. return; } + initializationRef.current = true; + initPlayground( iframe, slug, blogName ) .then( async ( client: PlaygroundClient ) => { const url = await client.absoluteUrl; @@ -39,7 +43,7 @@ export function Playground( props: { .catch( ( error ) => { throw error; } ); - }, [ slug, onReady ] ); + }, [ slug, onReady, blogName ] ); return (