Je hoeft niet alle 800 miljoen WordPress sites op het web te beheren voordat je op zoek gaat naar manieren om nieuwe sites efficiënt te lanceren.

Het klonen van een bestaande WordPress configuratie is één manier om snel aan de slag te gaan, en klanten van Kinsta’s Managed WordPress Hosting dienst weten dat dit eenvoudig kan worden gedaan binnen ons gebruiksvriendelijke MyKinsta dashboard.

Bovendien kun je WordPress sites op schaal klonen met je favoriete technologieën voor applicatieontwikkeling en de Kinsta API. In deze tutorial gebruiken we die API en React, een van de vele populaire JavaScript bibliotheken, om te laten zien hoe dat werkt.

Wat je gaat bouwen

Dit is het scenario: Je bent een WordPress ontwikkelingsbureau met een of meer sites die gebruikt kunnen worden als starttemplates. De React applicatie voor het klonen van WordPress sites die we bouwen ziet er als volgt uit:

React applicatie voor het klonen van site met Kinsta API.
React applicatie voor het klonen van site met Kinsta API.

Vereisten

Om deze tutorial te kunnen volgen, heb je een basiskennis nodig van HTML, CSS en JavaScript en enige bekendheid met React. Ook moet je Node.js en npm (de Node Package Manager) of yarn geïnstalleerd hebben op je computer. De focus van dit project ligt meer op het bouwen van een WordPress kloonapplicatie met React en de Kinsta API dan op de details van het maken en stylen van de UI.

De ontwikkelomgeving instellen

Je kunt een React applicatie vanaf nul maken en je eigen interface ontwikkelen, of je kunt de Git starter template pakken die hierboven genoemd is door deze stappen te volgen:

  1. Bezoek de GitHub repository van dit project.
  2. Selecteer Use this template > Create a new repository om de starter code naar een repository binnen je GitHub account te kopiëren. (Vink het vakje aan om alle branches mee te nemen.)
  3. Pull het repository naar je lokale computer en schakel over naar de starter-files branch met het commando: git checkout starter-files
  1. Installeer de benodigde dependencies door het commando npm install uit te voeren.

Als de installatie voltooid is, kun je het project op je lokale computer starten met npm run start. Dit opent het project op http://localhost:3000/.

De projectbestanden begrijpen

De src-map is het hart van een React applicatie, omdat deze de JavaScript bevat die webpack nodig heeft. In de map staat App.js, waarin de twee routes voor dit project zijn geconfigureerd.

Binnen de src-map bevinden zich de submappen components en pages. De map components bevat herbruikbare componenten, zoals de Header.jsx en Footer.jsx, die worden gebruikt in de pagina’s Home.jsx en Operations.jsx .

Je concentreert je hier op het deployen van de logica in Home.jsx en Operations.jsx, omdat styling en routing te vinden zijn in onze GitHub startbestanden.

Home.jsx heeft een formulier met twee velden: de naam van de site die je aanmaakt en een selectieveld dat de WordPress sites opsomt die in je MyKinsta account staan (deze lijst wordt opgehaald via de Kinsta API).

Als er op de verzendknop van het formulier (Clone site) wordt geklikt, wordt er een object met de property operation_id geretourneerd. Deze ID en weergavenaam worden doorgegeven als routeparameters aan Operations.jsx, waar de status van de kloonoperatie wordt gerapporteerd. De interface zal ook links bevatten naar de WordPress admin login en de homepage van de site.

Operations pagina met links naar WP admin en site.
Operations pagina met links naar WP admin en site.

De Kinsta API gebruiken om een WordPress site te klonen

Binnen Home.jsx worden drie API verzoeken gedaan aan de Kinsta API. Het eerste verzoek is om een lijst van sites op je Kinsta account te krijgen. Deze wordt opgeslagen in een state en vervolgens geïtereerd naar het select veld. Dit verzoek wordt direct na het renderen van de pagina gedaan met behulp van de useEffect hook.

Het tweede en derde verzoek worden gedaan zodra op de knop Clone site wordt geklikt. Het tweede verzoek krijgt het omgevings-ID van de site die je wilt klonen. Het derde verzoek gebruikt die omgevings-ID en de weergavenaam van de site om het klonen van de site te starten.

Interactie met de Kinsta API in React

In deze tutorial heb je interactie met twee endpoints van de Kinsta API:

  • /sites: Hiermee kun je een lijst met alle sites retourneren, een site-omgevings-ID opvragen en ten slotte een bestaande site klonen.
  • /operations: Dit wordt gebruikt om de state van de operatie op te vragen. Als de site kloonoperatie bijvoorbeeld bezig is, kun je dit endpoint gebruiken om de state van de operatie programmatisch bij te houden om te bepalen wanneer deze klaar is.

Voor interactie met de Kinsta API heb je je bedrijfs-ID nodig (te vinden in MyKinsta onder Bedrijf > Factureringsgegevens > Bedrijfs-ID) en een API sleutel. Hier lees je hoe je een Kinsta API sleutel aanmaakt.

Zodra je deze gegevens hebt, kun je ze het beste veilig opslaan als omgevingsvariabelen in je React applicatie. Om de omgevingsvariabelen in te stellen, maak je een .env bestand in de hoofdmap van je project. Voeg in dit bestand de volgende regels toe:

REACT_APP_KINSTA_COMPANY_ID = 'YOUR_COMPANY_ID' 
REACT_APP_KINSTA_API_KEY = 'YOUR_API_KEY'

Om toegang te krijgen tot deze omgevingsvariabelen binnen je project, kun je de syntaxis process.env.THE_VARIABLE gebruiken. Om bijvoorbeeld toegang te krijgen tot REACT_APP_KINSTA_COMPANY_ID, gebruik je process.env.REACT_APP_KINSTA_COMPANY_ID.

Een bestaande site klonen met Kinsta API

Laten we beginnen met het ophalen van de lijst van alle sites wanneer Home.jsx rendert met behulp van de useEffect Hook en ze op te slaan in een state. Om dit te bereiken importeer je de useEffect en useState Hooks en maak je een state aan om de array van sites die worden opgehaald in op te slaan:

import { useState, useEffect } from 'react';
const [sites, setSites] = useState([]);

Gebruik vervolgens de useEffect Hook om de Kinsta API te bevragen met de JavaScript Fetch API. Maak eerst twee constante variabelen om de headers en de Kinsta API URL op te slaan. Dit wordt gedaan om herhaling te voorkomen, omdat je op deze pagina meer dan één verzoek naar de Kinsta API zult sturen:

const KinstaAPIUrl = 'https://api.kinsta.com/v2';
const headers = useMemo(() => {
    return {
        Authorization: `Bearer ${process.env.REACT_APP_KINSTA_API_KEY}`
    };
}, []);

In de bovenstaande code onthoudt de useMemo Hook het headers object zodat het niet bij elke render opnieuw geëvalueerd hoeft te worden omdat de waarde constant is. Nu kun je het API verzoek maken:

useEffect(() => {
    const fetchAllSites = async () => {
        const query = new URLSearchParams({
            company: process.env.REACT_APP_KINSTA_COMPANY_ID,
        }).toString();
        const resp = await fetch(
            `${KinstaAPIUrl}/sites?${query}`,
            {
                method: 'GET',
                headers
            }
        );
        const data = await resp.json();
        setSites(data.company.sites);
    };
    fetchAllSites();
}, [headers]);

In de bovenstaande code wordt een asynchrone functie fetchAllSites gemaakt. In deze functie definieer je eerst de parameter query (je bedrijfs-ID) die je hebt opgehaald uit je .env bestand. Vervolgens doe je een GET-verzoek naar het /sites endpoint van de Kinsta API met behulp van de query parameter. Het antwoord wordt dan opgeslagen in de sites state die je eerder hebt aangemaakt. Tot slot call je fetchAllSites om het fetchen te starten.

Laten we nu de waarden opnemen die zijn opgeslagen in de sites state door er doorheen te lopen om het select veld te vullen. De displaynaam wordt getoond aan de gebruiker, terwijl de site-ID wordt gebruikt als optiewaarde. Op deze manier kan, wanneer het formulier wordt verzonden, de ID van de geselecteerde site worden gebruikt om omgevingsdetails op te vragen:

<div className="input-div">
    <label>Select a site</label>
    <span>Select the site you want to clone</span>
    <select className="form-control">
        <option> value=""></option>
        {sites && (
            sites.map((site) => {
                return (
                    <option> key={site.id} value={site.id}>{site.display_name}</option>
                )
            })
        )}
    </select>
</div>

Laten we verder gaan met het afhandelen van het verzenden van het formulier en het ophalen van waarden uit het formulier. Hiervoor moet je voor elk invoerveld state variabelen maken:

const [selectedSiteId, setSelectedSiteId] = useState('');
const [displayName, setDisplayName] = useState('');

Vervolgens bind je de formuliervelden aan hun respectievelijke state waarden door de attributen value en onChange toe te voegen aan elk invoerelement. Zo ziet het formulier eruit:

<form>
    <div className="form-container">
        <div className="input-div">
            <label>Display name</label>
            <span>Helps you identify your site. Only used in MyKinsta and temporary domain</span>
            <input type="text" className="form-control" value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
        </div>
        <div className="input-div">
            <label>Select a site</label>
            <span>Select the site you want to clone</span>
            <select className="form-control" value={selectedSiteId} onChange={(e) => setSelectedSiteId(e.target.value)}>
                <option value=""></option>
                {sites && (
                    sites.map((site) => {
                        return (
                            <option key={site.id} value={site.id}>{site.display_name}</option>
                        )
                    })
                )}
            </select>
        </div>
        <button className='btn'>Clone Site</button>
    </div>
</form>

In de bovenstaande code heeft elk invoerelement het value attribuut ingesteld op de corresponderende toestandsvariabele, en het onChange attribuut wordt gebruikt om de state waarde bij te werken als de gebruiker interactie heeft met de invoervelden.

Om het verzenden van het formulier af te handelen, koppel je een onSubmit methode aan het formulierelement. Bijvoorbeeld:

<form> onSubmit={handleSubmission}>
    {/* form details */}
</form>

Definieer de methode handleSubmission, waarbij twee API verzoeken worden gedaan aan de Kinsta API. Het eerste verzoek vraagt de omgevings-ID op van de site die gekloond moet worden en het tweede verzoek voert de kloonbewerking uit.

Laten we beginnen met het ophalen van de omgevings-ID. Maak in de methode handleSubmission een asynchrone functie om dit verzoek af te handelen. De functie stuurt een GET verzoek naar het /sites endpoint, voegt de ID van de geselecteerde site toe, gevolgd door het /environments endpoint:

const handleSubmission = async (e) => {
    e.preventDefault();
    const fetchEnvironmentId = async (siteId) => {
        const resp = await fetch(
            `${KinstaAPIUrl}/sites/${siteId}/environments`,
            {
                method: 'GET',
                headers
            }
        );
        const data = await resp.json();
        let envId = data.site.environments[0].id;
        return envId;
    }
    let environmentId = await fetchEnvironmentId(selectedSiteId);
}

Hierboven is fetchEnvironmentId een asynchrone functie die een GET verzoek naar de Kinsta API stuurt. Het haalt de omgevingen van de geselecteerde site op en haalt de ID van de omgeving uit het antwoord. De omgevings-ID wordt opgeslagen in de variabele envId en vervolgens geretourneerd. Bij het callen van de functie wijzen we de retourwaarde toe aan de variabele envId.

Op dit punt kun je een bestaande site klonen met de Kinsta API omdat je de essentiële informatie hebt over de bronsite: bedrijfs-ID, weergavenaam en omgevings-ID.

Maak binnen de methode handleSubmission een functie genaamd cloneExistingSite om dit API verzoek af te handelen. Dit verzoek gaat naar het /sites/clone endpoint. In tegenstelling tot de vorige verzoeken zijn de headers voor dit verzoek anders, omdat je de Content-Type moet specificeren als application/json. Bovendien is dit een POST verzoek, dus je moet een verzoektekst toevoegen die de payload bevat die je naar de API wilt sturen. Dit is hoe het verzoek wordt opgebouwd:

const handleSubmission = async (e) => {
    e.preventDefault();

    // fetch environment Id

    const cloneExistingSite = async (env_Id) => {
        const resp = await fetch(
            `${KinstaAPIUrl}/sites/clone`,
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    Authorization: `Bearer ${process.env.REACT_APP_KINSTA_API_KEY}`
                },
                body: JSON.stringify({
                    company: `${process.env.REACT_APP_KINSTA_COMPANY_ID}`,
                    display_name: displayName,
                    source_env_id: env_Id,
                })
            }
        );
        const data = await resp.json();
        navigate(`/operations/${displayName}/${data.operation_id}`)
        console.log(data);
    }
    cloneExistingSite(environmentId);
}

In deze code wordt het verzoek body geconstrueerd met JSON.stringify() om het payload object om te zetten in een JSON string. Het antwoord wordt vervolgens opgeslagen in de gegevensvariabele. Met behulp van de methode useNavigate uit de bibliotheek react-router-dom worden de displayName en operation_id doorgegeven als routeparameters. Zorg ervoor dat je de methode useNaviagte importeert en installeert:

// Import the required method 
import { useNavigate } from 'react-router-dom'; 

// Instantiate the useNavigate method 
const navigate = useNavigate();

Als je nu het formulier invult en op de knop Clone site klikt, begint een nieuwe site met het kloonproces, die zichtbaar zou zijn op je MyKinsta dashboard. Maar we willen het klonen van de site programmatisch volgen binnen de custom UI. Je regelt dit in Operations.jsx met behulp van de gegevens die via de route worden verzonden.

Operationele statuscontrole gebruiken met Kinsta API

Haal in Operations.jsx de ID van de operatie op uit de route met de methode useParams van react-router-dom. Deze ID wordt gebruikt om een API verzoek te doen wanneer op de knop Check Site Status wordt geklikt.

Importeer eerst de methode useParams en gebruik deze om de variabelen displayName en operationId te instantiëren:

// Import the useParams library
import { useParams } from 'react-router-dom';

// Instantiate the paramters
const { displayName, operationId } = useParams();

Maak vervolgens een state aan om de state van de operatie op te slaan wanneer het verzoek wordt gedaan:

const [operationData, setOperationData] = useState({ message: "Operation in progress." });

In de bovenstaande code wordt de state geïnitialiseerd met een standaardbericht, dat wordt weergegeven totdat op de knop Check Site Status wordt geklikt. Voeg een onClick event toe aan de knop Check Site Status en call de methode checkOperation wanneer op de knop wordt geklikt:

<button> className='sm-btn' onClick={() => checkOperation()}>Check Site Status</button>

Maak nu de functie checkOperation om de bewerkingsaanvraag aan de Kinsta API te doen. Sla de constanten headers en KinstaAPIUrl op in variabelen en gebruik ze in het API-verzoek:

const KinstaAPIUrl = 'https://api.kinsta.com/v2';
const headers = useMemo(() => {
    return {
        Authorization: `Bearer ${process.env.REACT_APP_KINSTA_API_KEY}`
    };
}, []);

const checkOperation = async () => {
    const resp = await fetch(
        `${KinstaAPIUrl}/operations/${operationId}`,
        {
            method: 'GET',
            headers
        }
    );
    const data = await resp.json();
    setOperationData(data);
};

In de bovenstaande code wordt een GET verzoek verzonden naar het /operations endpoint met de ID van de bewerking en het antwoord wordt opgeslagen in de operationData state. Nu kun je de gegevens gebruiken in de opmaak:

<div className="services">
    <div className="details">
        <p>{operationData.message}..</p>
        <button> className='sm-btn' onClick={() => checkOperation()}>Check Site Status</button>
    </div>
</div>

Tot slot worden de displayName gegevens die via de route worden doorgegeven gebruikt om de URL voor de nieuwe site en de WordPress admin URL te construeren. Beide links worden geopend in een nieuw tabblad.

<div className="details">
    <a href={`http://${displayName}.kinsta.cloud/wp-admin/`} target="_blank" rel="noreferrer" className='detail-link'>
        <p>Open WordPress admin</p>
        <FiExternalLink />
    </a>
    <a href={`http://${displayName}.kinsta.cloud/`} target="_blank" rel="noreferrer" className='detail-link'>
        <p>Open URL</p>
        <FiExternalLink />
    </a>
</div>

Met deze wijzigingen haalt Operations.jsx de ID van de operatie op uit de route, doet een API verzoek wanneer op de knop wordt geklikt, geeft de state van de operatie weer en biedt links naar de WordPress admin en site URL op basis van de displayName gegevens.

Je applicatie deployen naar Kinsta

Om je applicatie te deployen naar Kinsta’s Applicatie Hosting platform, moet je het project pushen naar je favoriete Git provider. Als je project is gehost op GitHub, GitLab of Bitbucket, kun je verder gaan met de deployment naar Kinsta.

Om je repository naar Kinsta te deployen, volg je deze stappen:

  1. Log in of maak je Kinsta account aan op het MyKinsta dashboard.
  2. Klik in de linker zijbalk op Applicaties en vervolgens op Dienst toevoegen.
  3. Selecteer Applicatie in het vervolgkeuzemenu om een React applicatie te deployen op Kinsta.
  4. Kies in de modal die verschijnt de repository die je wilt deployen. Als je meerdere branches hebt, kun je de gewenste branch selecteren en een naam geven aan je applicatie.
  5. Selecteer een van de beschikbare datacenterlocaties uit de lijst met 25 opties.
  6. Kinsta detecteert automatisch het start commando voor je applicatie.

Tot slot is het niet veilig om API sleutels naar publieke hosts zoals je Git provider te pushen. Bij het hosten kun je ze toevoegen als omgevingsvariabelen met dezelfde variabelenaam en -waarde die zijn opgegeven in het .env bestand.

Stel omgevingsvariabelen in op MyKinsta bij het deployen.
Stel omgevingsvariabelen in op MyKinsta bij het deployen.

Zodra je de deployment van je applicatie start, begint het proces en is meestal binnen een paar minuten klaar. Een succesvolle deployment genereert een link naar je applicatie, zoals https://clone-wp-site-12teh.kinsta.app/.

Samenvatting

De Kinsta API biedt de flexibiliteit om custom gebruikersinterfaces te maken voor het beheren van WordPress sites, inclusief de mogelijkheid om bestaande sites te klonen en verschillende aspecten van je WordPress omgeving te beheren.

In dit artikel heb je geleerd hoe je een applicatie kunt ontwikkelen die het klonen van sites buiten MyKinsta mogelijk maakt.

Hoe gebruik jij de Kinsta API? Welke features en endpoints zou je graag toegevoegd zien aan de API? Deel ze in de commentsectie!

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.