2.4 Creating a serious Svelte webapp (a) : Routes, Layouts, Components

MartinJ - Aug 21 - - Dev Community

To create a new post x.y, start with "ngatesystems-post-series-v2-xy" as your title and save this with /empty/ content. The important thing is not

to put your -- title -- into the post until you've got the URL initialised with your first save.

Introduction

Webapp users expect websites to have a "page" structure - a hierarchy of "pages" such as mywebapp/products/product_detail. They want this arrangement because it dovetails with browser "breadcrumb" arrangements that enable them to navigate up and down the branches of the webapp's hierarchy. If a page is frequently accessed, users can save its URL as a bookmark to return to it easily by clicking the saved link. The arrangement is called "routing" and URLs such as mywebapp/products/product_detail are called "routes".

Additionally, users find it helpful if routes employ common elements such as a standard menu bar and page trailer to give the parent website a uniform appearance. Svelte refers to these common elements as "Layouts".

Another form of shared elements is styled a "Component". SVelte is, from top to bottom a "component architecture.

You won't be surprised to learn that all of these concepts are baked into the heart of SvelteKit

Routing in Svelte

SvelteKit uses your project's filing structure to define the required page structure. If you want a mywebapp/products page, for example, you need a project folder called src/routes/products with a +page.svelte file inside it. Once this arrangement is in place, your webapp delivers a separate physical page for each route. This is in sharp contrast with what you find in an SPA or "single page webapp" where the physical separation of pages is entirely simulated

Here's a sample source folder structure for a SvelteKit project:

myproject
├───src
│ └───routes
│ └───products
│ └───+page.svelte
│ └───product_detail
│ └───+page.svelte

Hang on, though, isn't this going to be a bit confusing - lots of files all called +page.svelte? Yes, it is, at least at first sight. But 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)

Try this out in your current svelte_test project with the following products/+page.svelte and product_detail/+page.svelte code.

products/+page.svelte

<h1>Products</h1>
<a href="/products/product_detail">View Product Detail</a>
Enter fullscreen mode Exit fullscreen mode

iproduct_detail/+page.svelte

<h1>Product Detail</h1>
Enter fullscreen mode Exit fullscreen mode

Now run your dev server, start the webapp and change the root address to http://localhost:5173/products (making allowance for any variation in port number, of course). It should look like this:

Now, note what happens when you click the link. Unsurprisingly, the display changes to this:

However, note that the page address has also been changed. Try using the browser's navigation buttons to return to the original page. Yes, everything works exactly as you would expect, and all you've had to do to achieve this is to accede to Svlte's naming conventions. I'd say that's a price well worth paying!

Layouts in Svelte

A more realistic scenario would feature a "products" page that provided a company's "showcase". In this case, it would list all available products and likely carry a header banner featuring the company logo and contact details. Customers would find it useful to have access to the same information on a "product-detail" page too.

It would be perfectly possible to duplicate the necessary code, but this would be very undesirable from a maintenance point of view.

Svelte's "layout" facility provides a neat solution to the problem.

Supposing that the header banner used the following code (noting that, if you have difficulty working out what the styling does here, you can always paste the entire code block into chatGPT and ask it to explain how it works):

<header>
    <h1 style="display:flex; justify-content:space-between">
        <a href="/about">About</a>
        <span>Magical Products Coy</span>
        <a href="/product_search">Search</a>
    </h1>
</header>

<slot></slot>

<trailer>
    <p>© 2024 Magical Products Coy</p>
</trailer>
Enter fullscreen mode Exit fullscreen mode

if you save this in a new +page.svelte file in the products folder you'll find that the header and trailer layouts have now been wrapped automatically around all +page.svelte pages in this branch of the folder hierarchy. Thus, for example, the product_detail/+page.svelte would now look like:

The <slot></slot> element within the +layout.svelte file defines where the content of subject pages will be inserted. See +layout in Svelte docs for more information about the arrangement.

Svelte layouts are especially handy for building a "nav" bar. This is the array of links or buttons used in many applications to provide a standard centralized menu for navigating between different site pages. It is usually positioned at the top of the screen, though you could just as easily style it to appear at the side instead.

Components in Svelte

While the standard "header/footer" layout arrangement is useful, there are many other situations where you might like to introduce a standard piece of HTML into the body of a page. Wherever you find yourself repeating the same block of HTML you need to consider whether you shouldn't be looking for some way of importing this from a central location. Svelte components meet this need.

As an aside, the "DRY" (don't repeat yourself) principle applies just as much to Javascript coding as to HTML. Whenever you see you are repeating the same code structure, you should always look for a way to deliver this from a centralised source. Typically this would be a function

A Svelte component is a self-contained unit of code that combines HTML, CSS, and JavaScript to create a piece of the user interface (UI). Typically you would store this in a src/lib/MyComponent.svelte file. Here "MyComponent" would be some appropriate meaningful expression of the component's purpose.

PascalCase is recommended for Svelte component names. This means that each word in the component name starts with an uppercase letter and spaces or underscores between words are omitted. UserProfile.svelte would be an example.

Just like a Javascript function, a Svelte component will usually need to be provided with some parameters to achieve its purpose, so a UserProfile.svelte might be referenced in the HTML body section of a +page.svelte file with a statement like:

<UserProfile userId={userId} />
Enter fullscreen mode Exit fullscreen mode

Here, the userId parameter will have been declared by the +page.svelte file with a let userId statement and seeded with a value. The component will also have been imported into +page.svelte, so its <script> section will look like this:

<script>
    import { UserProfile} from "$lib/UserProfile.svelte";

    let userId;

<script/>
Enter fullscreen mode Exit fullscreen mode

Note the "$" shortcut used in the import declaration. Svelte works out the actual route automatically, saving you working out all the conventional "./" and "//" designators.

Meanwhile, in the UserProfile.svelte file, the parameter will have been declared as a prop (ie a parameter) with an export statement

<script>
    export userId;
<script/>
Enter fullscreen mode Exit fullscreen mode

You'll recall this is exactly how a +page.svelte file gets its data from an attendant +page.server.js file. This is because all +page.svelte files are themselves components. In this case, though, their names give them special significance for page routing

Roundup

The Svelte file types described above deliver a "default" design in which pages are primarily initially rendered on the server and initially displayed to the client as pure HTML. Here, in a process Svelte calls "hydration", javascript is added to make the page interactive. Finally, "state" data used on the server to generate the initial HTML is replayed to ensure that everything is still consistent. Overall this arrangement:

  • ensures that sensitive application logic, vulnerable form validation logic and valuable security keys are hidden
  • makes the most of the (generally) superior processing capability of the server
  • encourages better "indexing" by search engines. While search engines have got better in recent years at indexing content that was rendered with client-side JavaScript, server-side rendered content is indexed more frequently and reliably.

That said, there will always be cases where other arrangements are to be preferred and Svelte is very helpful in providing ways of enabling these.

For example, if the data accessed by a +page.server.js isn't changing very much (ideally, not at all) you can instrument Svelte to pre-render your +page.svelte at "build" time (the point at which the webapp is prepared for "deployment" to the liver server - a subject to be covered later in this series).

Additionally, there may be cases when client-side processing would be a more practical way of loading the data for a +page.svelte file. Perhaps it doesn’t matter if the data fetch happens asynchronously after the initial page load or if the data can be fetched via APIs that don’t require server-side security. In this case, Svelte offers a +page.js file to export a load function. Unlike a +page.server.js file, a +page.js can be inspected in the browser

For more information about this and other specialist arrangements, please refer to the SvelteKit Page Options docs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player