Home > Web Front-end > JS Tutorial > body text

A gentle introduction to SvelteKit for Google Cloud developers

PHPz
Release: 2024-07-17 19:39:17
Original
370 people have browsed it

 A gentle introduction to SvelteKit for Google Cloud developers

介绍

本系列之前的一篇文章(对 React 的非常温和的介绍)向读者介绍了用于开发 Web 应用程序的优秀React 框架系统。 SvelteKit 是一个替代框架。它与 React 有什么不同,有什么更好的地方吗?

从功能上来说,我想没有太大区别。在 React 中可以做的大多数事情也可以在 SvelteKit 中完成。反之亦然。但当你深入细节时,很多人认为 SvelteKit 在轻松实现“响应式”目标方面具有优势。 Svelte 的意思是“优雅”——这就是它的本质——一种纤细、适应性强且实用的工具。

就我个人而言,我被 SvelteKit 所吸引,因为它还倾向于推动您进行服务器端设计 - 即在 Web 应用程序的云服务器上运行的代码,而不是在用户的 Web 浏览器中运行。这很讽刺,因为编写和调试客户端代码的便捷性最初让我对 Web 应用程序开发着迷。但后来我发现索引蜘蛛是多么不愿意投入精力来“滋润”客户端代码,并意识到我只需要在这里投入更多的精力(请参阅下面的 SvelteKit 中的调试,看看会带来什么)。但您也可能考虑使用服务器端代码还有其他原因。这里有几个:

  • 一旦您开始使用 Postmark(电子邮件发送)或 Paypal(收款)等第三方服务,您就会意识到将其安全代码包含在客户端代码中并不是一个好主意。如果可以使用“检查器”来查看这些,那么其他人也可以。运行服务器端的代码无法访问。

  • 服务器端代码距离您的数据更近,并且比在客户端笔记本电脑上运行得更快。

SvelteKit 可以轻松地播放音乐,指定 Web 应用程序的哪些部分要本地运行,哪些部分要远程运行。

  • 在某些情况下,页面可能完全是服务器端渲染的 - 如果它们仅包含静态信息,Sveltekit 将使您能够“预渲染”它们。预渲染页面在构建时构建并作为纯 HTML 块下载。
  • 或者,它们可能完全是客户端渲染的。
  • 或者再一次,它们可能在两者上运行。旨在提供最佳响应时间的 SvelteKit Web 应用程序最初可能只显示一个源自服务器的“占位符”屏幕,以获取可见的某些内容(显然,您在这里获得了 Google 索引机器人的大力支持)。然后,客户端代码将其“水合”为特定于用户实例的信息。

让我们开始讨论更具体的事情。

Svelte 中的路由

从外部来看,Sveltekit Web 应用程序看起来与任何经典浏览器应用程序完全相同 - “页面”的层次结构,例如 mywebapp/dosomethingwithmyfiles。之所以会这样,是因为客户端用户期望并依赖这种类型的安排。但在表面之下,SvelteKit Web 应用程序以与 React Web 应用程序完全不同的方式提供这种安排。在 React 中,这些页面实际上是一大堆代码的所有部分,并且请求通过在 Web 界面上操作的重定向来路由到那里(如果这句话对您来说没有任何意义,请看看什么是“单-”)页的网络应用程序?)。 SvelteKit 通过使用项目结构来定义页面结构来实现这一点。因此,如果您想要一个 mywebapp/dosomethingwithmyfiles 页面,您需要有一个名为 dosomethingwithmyfiles 的文件夹,其中包含一个 +page.svelte 文件。一旦这种安排到位,您部署的应用程序就会为其每个 URL 提供一个单独的物理页面。

这是 SvelteKit 项目的示例源文件夹结构:

我的项目
├────src
│ └────路线
│ └───用我的文件做点什么

一旦安装了 SvelteKit(请参阅 Svelte for New Developers),此结构将通过大量复杂的配置文件和构建文件夹等来增强。但是,目前,重点是在路由文件夹上。 这是您存储页面代码的地方 - 在这里您可能会开始怀疑 SvelteKit 是否适合您。现在要抓紧,因为这就是事情变得有点复杂的地方。

SvelteKit 要求您对页面文件夹的内容遵循非常严格的命名约定。以下是 dosomethingwithmyfiles 文件夹中可能出现的文件名列表:

  • dosomethingwithmyfiles/+page.svelte. This file would contain the source for the code that displays the page for URL myproject/dosomethingwithmyfileson the browser screen. Whoah - let that sink in for a moment. When you're working in your VSCode editor on a SvelteKit project with half a dozen different pages, your filebar may display half a dozen tabs all named +page.svelte. Confusing? Yes, I agree.

At first sight, you might feel that this is simply unacceptable. But note that each +page.svelte file is qualified on the editor bar by the name of its folder owner, dosomethingwithmyfiles, or whatever. It's not so difficult to discipline yourself to check for the owner of a +page.svelte before you dive in and start editing. And once you've developed a SvelteKit project or two you'll begin to appreciate the value of the convention in declaring the purpose of the arrangement (as you'll see in a moment there are quite a few variations)

While you're absorbing this shock, let me give you a bit of encouragement. Within a +page.svelte file you might expect to find the same sort of code you'd see in an equivalent React file - a mixture of exotic useState calls to manipulate page state, and JSX to 'react' to this and generate HTML. While a +page.svelte file certainly does the same job, it manages to discard the "exotic" bit and uses plain javascript and pure, undiluted HTMl salted with a sprinkling of special keywords. You may find this refreshing.

Here are a few more standard filenames you might find in a dosomethingwithmyfiles folder:

  • dosomethingwithmyfiles/+page.js, This would contain the source for a file that delivers data to a +page.svelte file (ie, the equivalent of a React useEffect). Code here will run on the server when the page is initially loaded. Subsequently, if the page is re-referenced, the +page.js code runs in the browser with the advantages listed earlier.

     

    Interestingly, if you've suffered in the past from having to "re-program" your javascript brain whenever you switch between writing Web API code to run in the browser and Node.js style to run server-side in a Firebase function you'll be delighted to hear that, in Sveltekit, the Web API version is now perfectly happy to run server-side as well.

     

    Naturally, you'll want to know just how you organise things so that data read by a +page.js file ends up in the associated +page.svelte. Let me say that, for the present, this arrives by SvelteKit magic. The exact mechanism will only become clear once I've described SvelteKit's arrangements for defining "reactive" variables. Hang onto your hat for now.

     

  • dosomethingwithmyfiles/+page.server.js. This is where you would place code that you want to run only on the server (typically for security or performance reasons). As mentioned earlier, you can request that this is pre-rendered and thus constructed at build-time. In this case, performance is simply startling.

     

  • dosomethingwithmyfiles/+layout.svelte. This is where you would place code that sets up those bits of a page common to a whole set of other pages - toolbar headers, for example. A +layout.svelte file applies to every child route and any sibling +page.svelte. You can nest layouts to arbitrary depth. Again, the precise arrangement for inserting the common layout into the recipient pages will be left for later - more Svelte magic.

     

    If a +layout.svelte page needs some data, it can have an attendant +layout.server.js file

     

  • dosomethingwithmyfiles/+server.js. This is where you would place code that you wanted to be available as an "API endpoint" via a parameterised URL such as myProject/dosomethingwithmyfiles?type="pdf". I'll provide more details on this arrangement later.

'Reactive variables' and 'Reactive HTML' in SvelteKit

By 'reactive variables' I mean data items that cause the browser page to re-render when they change. By 'reactive HTML' I mean HTML instrumented to make it respond to these changes.

In React, you'll recall, reactive variables are declared using a useState expression that defines the variables as properties of a state object. The declaration also specifies initial property values and a function to change them.

Here's an example - a React webapp that displays a popup that disappears when you click it:

import React, { useState } from "react";

const [screenState, setScreenState] = useState({popupVisible: true,});

return (
    

{setScreenState({popupVisible: !screenState.popupVisible})}}> Main Page - Click to toggle popup

{screenState.popupVisible &&
{setScreenState({popupVisible: !screenState.popupVisible})}}>

Popup Window - Click to Hide popup

}
)
Copy after login

In Svelte (I'm now talking about the language as opposed to the framework in which it operates) you might achieve this effect in a src/routes/demo/+page.svelte file by simply declaring popupVisible as a javascript variable



 

(popupVisible = !popupVisible)}> Main Page - Click to toggle popup

{#if popupVisible}
(popupVisible = !popupVisible)} >

Popup Window - Click to Hide popup

{/if}
Copy after login

Here's a summary of the key differences:

  • 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.

Inputs: Local Functions, Actions and API endpoints

Keyboard input in React generally uses the following pattern:

const [myState, setMyState] = useState({myProperty: "",});

function handleChange({ target }) {
    setMyState({ ...myState, [target.name]: target.value });
};

return (
    
)
Copy after login

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:



Copy after login

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:



myProperty = 

/>
Copy after login

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
myProperty =
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 } };
Copy after login

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.

Components

  • 1-way bindings

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 ... Svelte html referencing param1 and param2 ...

Copy after login

The parent +page.svelte could then engage the component like this:



Input1 value Input2 value
Copy after login

This creates a default export for a MySharedInputPanel component that a routes/editrecord/+page.svelte file can import and use to build an edit 'form' for the named, exported inputs as follows:



Edit Record

Latest values: Input1 = {input1} : Input2 = {input2}

>
Copy after login

If you try this out yourself, you'll see that the shared panel initially displays the input1 and input2 values specified in the edit record route and that the parent editrecord/+page.svelte view of these changes when new values are entered. This confirms that the route is automatically rerendering when changes occur.

A routes/createrecord/+page.svelte could use the same form component to collect inputs and create a record.

Note that, for brevity, I've used neither the

nor
source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!