Ein früherer Beitrag in dieser Reihe (Eine sehr sanfte Einführung in React) führte die Leser in das hervorragende React-Framework-System für die Entwicklung von Webanwendungen ein. SvelteKit ist ein alternatives Framework. Wie unterscheidet es sich von React und ist es besser?
Funktionell gibt es wohl keinen großen Unterschied. Die meisten Dinge, die Sie in React tun können, können Sie auch in SvelteKit tun. Und umgekehrt. Aber wenn man auf die Details eingeht, haben viele Leute das Gefühl, dass SvelteKit die Nase vorn hat, wenn es um die Leichtigkeit geht, mit der Sie Ihre „reaktiven“ Ziele erreichen. Svelte bedeutet „elegant“ – und genau das ist es – ein schlankes, äußerst anpassungsfähiges und praktisches Werkzeug.
Persönlich hat mich SvelteKit angezogen, weil es Sie auch tendenziell in Richtung serverseitiges Design drängt – also Code, der auf den Cloud-Servern Ihrer Webanwendung und nicht im Webbrowser Ihres Benutzers ausgeführt wird. Das ist ironisch, denn es war die Leichtigkeit, mit der man clientseitigen Code schreiben und debuggen konnte, die mich ursprünglich für die Entwicklung von Webanwendungen begeistert hat. Aber dann entdeckte ich, wie zögerlich Indizierungs-Spider sind, sich Mühe zu geben, um clientseitigen Code zu „hydrieren“, und mir wurde klar, dass ich hier einfach mehr Aufwand betreiben müsste (siehe Debugging in SvelteKit unten, um zu sehen, was dazu gehört). Es gibt aber auch andere Gründe, warum Sie die Verwendung von serverseitigem Code in Betracht ziehen könnten. Hier sind ein paar:
Sobald Sie anfangen, Dienste von Drittanbietern wie Postmark (E-Mail-Versand) oder Paypal (Zahlungseinzug) zu nutzen, werden Sie feststellen, dass es keine gute Idee ist, deren Sicherheitscodes in den clientseitigen Code aufzunehmen. Wenn Sie den „Inspektor“ verwenden können, um diese anzuzeigen, kann das auch jeder andere. Auf serverseitig ausgeführten Code kann nicht zugegriffen werden.
Serverseitiger Code befindet sich näher an Ihren Daten und läuft hier schneller als auf einem Client-Laptop.
Mit SvelteKit können Sie ganz einfach festlegen, welche Teile Ihrer Webanwendung lokal und welche remote ausgeführt werden sollen.
Lass uns etwas Konkreteres angehen.
Äußerlich sieht eine Sveltekit-Webanwendung genauso aus wie jede klassische Browseranwendung – eine Hierarchie von „Seiten“ wie mywebapp/dosomethingwithmyfiles. Dies liegt daran, dass Kundenbenutzer eine solche Vereinbarung erwarten und sich darauf verlassen. Aber unter der Oberfläche liefert eine SvelteKit-Webanwendung dieses Arrangement auf eine völlig andere Art und Weise als eine React-Webanwendung. In React sind diese Seiten tatsächlich alle Teile eines riesigen Codeblocks, und Anfragen werden durch Weiterleitungen, die auf der Weboberfläche ausgeführt werden, dorthin weitergeleitet (wenn dieser Satz für Sie keinen Sinn ergibt, schauen Sie sich „Was ist eine einzelne Seite“) an. Seite' Webapp?). SvelteKit erreicht dies, indem es Ihre Projektstruktur verwendet, um Ihre Seitenstruktur zu definieren. Wenn Sie also eine Seite „mywebapp/dosomethingwithmyfiles“ haben möchten, benötigen Sie einen Ordner namens „dosomethingwithmyfiles“ mit einer Datei +page.svelte darin. Sobald diese Vereinbarung getroffen ist, stellt Ihre bereitgestellte App für jede ihrer URLs eine separate physische Seite bereit.
Hier ist eine Beispiel-Quellordnerstruktur für ein SvelteKit-Projekt:
mein Projekt
├───src
│ └───Routen
│ └───etwas mit meinen Dateien machen
Sobald Sie SvelteKit installiert haben (siehe Svelte für neue Entwickler), wird diese Struktur durch eine Menge komplizierter Konfigurationsdateien und Build-Ordner usw. erweitert. Derzeit liegt der Fokus jedoch auf dem Routenordner. Hier speichern Sie Ihren Seitencode – und hier fragen Sie sich möglicherweise, ob SvelteKit das Richtige für Sie ist. Halten Sie es jetzt fest im Griff, denn hier wird es etwas kompliziert.
SvelteKit erfordert, dass Sie eine sehr strenge Namenskonvention für den Inhalt eines Seitenordners befolgen. Hier ist eine Liste der Dateinamen, die möglicherweise in einem Ordner „dosomethingwithmyfiles“ angezeigt werden:
Auf den ersten Blick könnten Sie das Gefühl haben, dass dies einfach inakzeptabel ist. Beachten Sie jedoch, dass jede +page.svelte-Datei in der Editorleiste durch den Namen ihres Ordnerbesitzers, „dosomethingwithmyfiles“ oder was auch immer gekennzeichnet ist. Es ist nicht so schwer, sich zu disziplinieren und nach dem Besitzer einer +page.svelte zu suchen, bevor man loslegt und mit der Bearbeitung beginnt. Und sobald Sie ein oder zwei SvelteKit-Projekte entwickelt haben, werden Sie beginnen, den Wert der Konvention zu schätzen, die den Zweck der Vereinbarung erklärt (wie Sie gleich sehen werden, gibt es eine ganze Reihe von Variationen). )
Während Sie diesen Schock verkraften, möchte ich Ihnen ein wenig Mut machen. Innerhalb einer +page.svelte-Datei erwarten Sie möglicherweise die gleiche Art von Code, die Sie in einer entsprechenden React-Datei sehen würden – eine Mischung aus exotischen useState-Aufrufen zum Manipulieren des Seitenstatus und JSX zum „Reagieren“. dazu und generieren Sie HTML. Während eine +page.svelte-Datei sicherlich die gleiche Aufgabe erfüllt, gelingt es ihr, den „exotischen“ Teil zu verwerfen und einfaches Javascript und reines, unverdünntes HTMl zu verwenden, gewürzt mit einer Prise spezieller Schlüsselwörter. Vielleicht finden Sie das erfrischend.
Hier sind ein paar weitere Standarddateinamen, die Sie möglicherweise in einem Ordner „dosomethingwithmyfiles“ finden:
Wenn Sie in der Vergangenheit unter der Notwendigkeit gelitten haben, Ihr Javascript-Gehirn jedes Mal neu zu programmieren, wenn Sie zwischen dem Schreiben von Web-API-Code für die Ausführung im Browser und dem Node.js-Stil für die serverseitige Ausführung in einer Firebase-Funktion wechseln, ist das interessant: Ich werde erfreut sein zu hören, dass die Web-API-Version in Sveltekit jetzt auch problemlos serverseitig ausgeführt werden kann.
Natürlich möchten Sie wissen, wie Sie die Dinge organisieren, damit die von einer +page.js-Datei gelesenen Daten in der zugehörigen +page.svelte landen. Lassen Sie mich sagen, dass dies vorerst durch SvelteKit-Magie geschieht. Der genaue Mechanismus wird erst klar, wenn ich die Vorkehrungen von SvelteKit zur Definition „reaktiver“ Variablen beschrieben habe. Behalten Sie vorerst Ihren Hut.
Wenn eine +layout.svelte-Seite einige Daten benötigt, kann sie eine zugehörige +layout.server.js-Datei haben
Mit „reaktiven Variablen“ meine ich Datenelemente, die dazu führen, dass die Browserseite neu gerendert wird, wenn sie sich ändern. Mit „reaktivem HTML“ meine ich HTML, das so instrumentiert ist, dass es auf diese Änderungen reagiert.
Wie Sie sich erinnern, werden in React reaktive Variablen mithilfe eines useState-Ausdrucks deklariert, der die Variablen als Eigenschaften eines Statusobjekts definiert. Die Deklaration gibt außerdem anfängliche Eigenschaftswerte und eine Funktion zu deren Änderung an.
Hier ist ein Beispiel – eine React-Webanwendung, die ein Popup anzeigt, das verschwindet, wenn Sie darauf klicken:
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> )
In Svelte (ich spreche jetzt von der Sprache im Gegensatz zum Framework, in dem sie funktioniert) können Sie diesen Effekt in einem src/routes/demo/+ erzielen page.svelte-Datei, indem Sie einfach popupVisible als Javascript-Variable deklarieren
<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>
Hier ist eine Zusammenfassung der wichtigsten Unterschiede:
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