Un article précédent de cette série (Une introduction très douce à React) a présenté aux lecteurs l'excellent système de framework React pour développer des applications Web. SvelteKit est un framework alternatif. En quoi diffère-t-il de React et est-il meilleur ?
Fonctionnellement, je suppose qu'il n'y a pas beaucoup de différence. La plupart des choses que vous pouvez faire dans React, vous pouvez le faire dans SvelteKit. Et vice-versa. Mais quand on entre dans les détails, beaucoup de gens pensent que SvelteKit a l'avantage en termes de facilité avec laquelle vous atteignez vos objectifs « réactifs ». Svelte signifie « élégant » - et c'est exactement ce que c'est : un outil mince, hautement adaptable et pratique.
Personnellement, j'ai été attiré par SvelteKit car il a également tendance à vous pousser vers une conception côté serveur, c'est-à-dire du code qui s'exécute sur les serveurs Cloud de votre application Web plutôt que dans le navigateur Web de votre utilisateur. C'est ironique car c'est la facilité avec laquelle vous pouvez écrire et déboguer du code côté client qui m'a rendu accro au développement d'applications Web. Mais ensuite, j'ai découvert à quel point les robots d'indexation étaient réticents à investir des efforts dans "l'hydratation" du code côté client et j'ai réalisé que je devrais simplement déployer plus d'efforts ici (voir le débogage dans SvelteKit, ci-dessous, pour voir ce que cela impliquait). Mais il existe d’autres raisons pour lesquelles vous pourriez également envisager d’utiliser du code côté serveur. En voici quelques-uns :
Une fois que vous aurez commencé à utiliser des services tiers tels que Postmark (envoi d'e-mails) ou Paypal (encaissement des paiements), vous vous rendrez compte que ce n'est pas une bonne idée d'inclure leurs codes de sécurité dans le code côté client. Si vous pouvez utiliser « l'inspecteur » pour les visualiser, n'importe qui d'autre le peut aussi. Le code qui s'exécute côté serveur est inaccessible.
Le code côté serveur vit plus près de vos données et s'exécute plus rapidement ici que sur un ordinateur portable client.
SvelteKit facilite la lecture de morceaux en spécifiant quels éléments de votre application Web doivent être exécutés localement et lesquels doivent être exécutés à distance.
Passons à quelque chose d'un peu plus concret.
En externe, une application Web Sveltekit ressemblera exactement à n'importe quelle application de navigateur classique - une hiérarchie de "pages" telles que monapplication Web/faire quelque chose avec mes fichiers. C'est ainsi parce que les utilisateurs clients attendent et comptent sur ce type d'arrangement. Mais sous la surface, une application Web SvelteKit propose cet arrangement d'une manière totalement différente d'une application Web React. Dans React, ces pages sont en fait toutes des parties d'une seule tranche de code géante et les requêtes y sont acheminées par des redirections opérant sur l'interface Web (si cette phrase n'a aucun sens pour vous, jetez un œil à Qu'est-ce qu'un « Single- webapp de la page ?). SvelteKit y parvient en utilisant la structure de votre projet pour définir la structure de votre page. Donc, si vous souhaitez avoir une page mywebapp/dosomethingwithmyfiles, vous devez avoir un dossier nommé dosomethingwithmyfiles avec un fichier +page.svelte à l'intérieur. Une fois cet arrangement mis en place, votre application déployée fournit une page physique distincte pour chacune de ses URL.
Voici un exemple de structure de dossiers sources pour un projet SvelteKit :
monprojet
├───src
│ └───itinéraires
│ └───faire quelque chose avec mes fichiers
Une fois que vous aurez installé SvelteKit (voir Svelte pour les nouveaux développeurs), cette structure sera complétée par une masse de fichiers de configuration compliqués et de dossiers de construction, etc. Mais, pour le moment, l'accent est mis sur le dossier routes. C'est ici que vous stockez le code de votre page - et c'est ici que vous pourriez commencer à vous demander si SvelteKit est la bonne solution pour vous. Prenez le contrôle maintenant car c'est là que les choses se compliquent un peu.
SvelteKit vous oblige à suivre une convention de dénomination très stricte pour le contenu d'un dossier de pages. Voici une liste des noms de fichiers qui peuvent apparaître dans un dossier dosomethingwithmyfiles :
À première vue, vous pourriez penser que c’est tout simplement inacceptable. Mais notez que chaque fichier +page.svelte est qualifié dans la barre de l'éditeur par le nom de son propriétaire de dossier, faire quelque chose avec mes fichiers, ou autre. Il n'est pas si difficile de vous discipliner pour rechercher le propriétaire d'un +page.svelte avant de vous lancer et de commencer à éditer. Et une fois que vous aurez développé un ou deux projets SvelteKit, vous commencerez à apprécier la valeur de la convention pour déclarer le objectif de l'arrangement (comme vous le verrez dans un instant, il existe de nombreuses variantes )
Pendant que vous absorbez ce choc, laissez-moi vous donner un peu d'encouragement. Dans un fichier +page.svelte, vous pourriez vous attendre à trouver le même type de code que vous verriez dans un fichier React équivalent - un mélange d'appels useState exotiques pour manipuler l'état de la page et de JSX pour « réagir » à cela et générer du HTML. Bien qu'un fichier +page.svelte fasse certainement le même travail, il parvient à éliminer le bit "exotique" et utilise du javascript simple et du HTMl pur et non dilué salé avec une pincée de mots-clés spéciaux. Vous trouverez peut-être cela rafraîchissant.
Voici quelques noms de fichiers standards supplémentaires que vous pourriez trouver dans un dossier dosomethingwithmyfiles :
Fait intéressant, si vous avez déjà souffert de devoir « reprogrammer » votre cerveau javascript chaque fois que vous basculez entre l'écriture de code d'API Web à exécuter dans le navigateur et le style Node.js à exécuter côté serveur dans une fonction Firebase, vous Je serai ravi d'apprendre que, dans Sveltekit, la version de l'API Web est désormais parfaitement heureuse de fonctionner également côté serveur.
Naturellement, vous voudrez savoir comment vous organisez les choses pour que les données lues par un fichier +page.js se retrouvent dans le fichier +page.svelte associé. Permettez-moi de dire que, pour le moment, cela arrive par magie SvelteKit. Le mécanisme exact ne deviendra clair qu'une fois que j'aurai décrit les dispositions de SvelteKit pour définir les variables « réactives ». Accrochez-vous à votre chapeau pour l'instant.
Si une page +layout.svelte a besoin de données, elle peut avoir un fichier +layout.server.js associé
Par « variables réactives », j'entends les éléments de données qui entraînent le nouveau rendu de la page du navigateur lorsqu'ils changent. Par « HTML réactif », j'entends HTML instrumenté pour le faire répondre à ces changements.
Dans React, vous vous en souviendrez, les variables réactives sont déclarées à l'aide d'une expression useState qui définit les variables comme propriétés d'un objet d'état. La déclaration spécifie également les valeurs initiales des propriétés et une fonction pour les modifier.
Voici un exemple : une application Web React qui affiche une fenêtre contextuelle qui disparaît lorsque vous cliquez dessus :
import React, { useState } from "react"; const [screenState, setScreenState] = useState({popupVisible: true,}); return ( <div> <h1 style={{textAlign: "center"}} onClick = {() => {setScreenState({popupVisible: !screenState.popupVisible})}}> Main Page - Click to toggle popup </h1> {screenState.popupVisible && <div style={{ textAlign: "center", marginLeft: "auto", marginRight: "auto", height: "2rem", width: "25rem", backgroundColor: "gainsboro" }} onClick = {() => {setScreenState({popupVisible: !screenState.popupVisible})}}> <h2> Popup Window - Click to Hide popup</h2> </div> } </div> )
Dans Svelte (je parle maintenant du langage par opposition au framework dans lequel il fonctionne), vous pourriez obtenir cet effet dans un src/routes/demo/+ fichier page.svelte en déclarant simplement popupVisible comme variable javascript
<script> let popupVisible = false; </script> <div> <h1 style="text-align: center" on:click={() => (popupVisible = !popupVisible)}> Main Page - Click to toggle popup </h1> {#if popupVisible} <div style="text-align: center; margin-left: auto; margin-right: auto; height: 2rem; width: 25rem; background-color: gainsboro" on:click={() => (popupVisible = !popupVisible)} > <h2>Popup Window - Click to Hide popup</h2> </div> {/if} </div>
Voici un résumé des principales différences :
Svelte uses a standard Javascript let declaration to introduce state variables instead of the strange React useState expression
Svelte uses a down to earth #if 'logical expression' keyword to replace the awkward JSX {'logical expression' &&syntax. This makes your code much more readable. Svelte also provides associated else and each keywords.
Svelte uses plain CSS to define HTML classes rather than the perplexing JSX style objects (eg {{textAlign: "center"}}).
Note also that the demo/+pagesvelte file defined above will run directly in the browser as /demo. To run the React version you would have to put some code into an associated src/main.jsx file to define the new route.
Keyboard input in React generally uses the following pattern:
const [myState, setMyState] = useState({myProperty: "",}); function handleChange({ target }) { setMyState({ ...myState, [target.name]: target.value }); }; return ( <input name="myProperty" value={myState.myProperty} onChange={handleChange} /> )
Here, an input labelled as "myProperty" fires a general-purpose handleChange function every time you press a key. In handleChange its value is extracted and applied to the page's state to trigger a re-render.
Svelte thinks this is too complicated and introduces a "bind" keyword to its input syntax. This automatically transmits changes to an associated state variable. A Svelte version of the above thus looks like this:
<script> let myProperty = ""; </script> <input bind:value={myProperty} />
The bind keyword is also used to enable you to create two-way communication between parent and child components. This is a powerful feature.
An interesting feature of Svelte is that it encourages you to use forms and server-side processing for input handling. Thus it's perfectly permissible in Svelte to launch a client-side function like this:
<script> let myProperty = ""; function commitChange() { // Use the global myProperty variable to update server storage } </script> <span>myProperty = </span><input bind:value={myProperty} /> <button on:click={commitChange}>Commit Change</button> />
Svelte docs correctly insist that interactions like this are better handled by forms and server-side processing in a +page.server.js file. Here the validation and submission of the user input can be safely protected from the sort of interference possible in client-based code. Here also, any subsequent processing can be performed with maximum efficiency.
To implement this view, Svelte provide a neat automatic link between a form reading data on a +page.svelte and a function handling the processing of that data in the associated +page.server.js file. Here's an example:
src/routes/login/+page.svelte <form method="POST"> <span>myProperty = </span><input name="myProperty"> <button>Commit Change</button> </form> src/routes/login/+page.server.js export const actions = { default: async (event) => { // TODO handle the processing for the input read by the form on +page.svelte } };
Note that no Javascript has been used in the form - no "on click" or "on submit", for example. The linkage has been established entirely through "Svelte magic".
In practice, of course, a +page.svelte file is likely to want to be the source of multiple "actions". See Svelte Form Actions for details of how Svelte manages this. (Note that Svelte docs are organised under two URLs: kit.svelte.dev for framework topics like routing and svelte.dev for elements of the language itself)
Finally, to conclude this section, suppose you wanted users to be able to call on the service of an action by referencing it directly through a javascript "fetch" (or, at its simplest by launching a parameterised url via the browser - eg https:// mySite/myPage?param1=3 etc). This is where you would use a +server.js file to create an API "endpoint" function. Firebase users might well use such an arrangement where they had previously used a Firebase function. Not the least advantage of this would be that testing and debugging could be done in the Sveltekit server rather than the Firebase emulator.
Each +page.svelte file defines a component, and you mark variables declared here as "props" - ie make them accessible to "consumers" of the component - by adding the export keyword to their declarations. So, if you're still wondering how a +page.svelte file gets its data from +page.server.js - this is how it's done. A +page.svelte file wanting to receive "load" data from its +page.server.js (or +page.js) file just needs to put something like the following in its