11

Modules and Secrets

While routing is certainly important to SvelteKit, there is far more to it than just that. Throughout this book, we’ve utilized multiple different SvelteKit modules. For instance, we’ve imported bindings from $app/forms, $app/environment, and $app/stores, to name a few. But we have yet to explore what these modules are or how they work. In this chapter, we’ll give a brief overview of some of the modules we’ve seen previously as well as some we have not yet seen. We’ll also cover some of the modules used for managing secrets and when to use which ones.

In this chapter, we’ll examine the following:

  • SvelteKit Module Summaries
  • Keeping Secrets Safe

Having covered various modules, as well as examining our previous example of storing GitHub API secrets, we’ll have a clear understanding of when best to harness the power of each individual module.

Technical requirements

The complete code for this chapter is available on GitHub at: https://github.com/PacktPublishing/SvelteKit-Up-and-Running/tree/main/chapters/chapter11.

SvelteKit Module Summaries

In previous chapters, we’ve used several different modules but only provided short explanations. While the analysis in this section will also be brief, it should provide a broad enough insight that prospective SvelteKit developers feel familiar with the workings of available modules. We have encountered a few listed here but there are some that we are yet to cover. For more in-depth explanations, see the resources at the end of this chapter.

$app/environment

To begin our analysis of modules, let’s start with one that we have used relatively recently. In Chapter 9, while attempting to throw an error in the client, we used the $app/environment module and imported browser. As we’ve come to expect with SvelteKit naming conventions, all of the bindings exported from this module pertain to the application environment. This makes it trivial to identify the purpose of each of the bindings by their names. For instance, we saw that browser returns a Boolean value based on whether or not the environment it is being run in is the client. Likewise, building and dev will return Boolean values based on whether or not the code is being run during the build process or in our development environment, respectively. The final export from $app/environment is version. While version is still appropriately named, it’s important to note that it doesn’t refer to the version of SvelteKit. Rather, it refers to the version of the application build. The value of version is determined by the Unix timestamp at the time of building. SvelteKit uses this string value to check for a new version when client-side navigation encounters an error and defaults to standard navigation practices by making a full-page load.

$app/forms

When we utilized enhance from $app/forms in Chapter 4, we saw how it could progressively enhance our form submissions by sending data in the background instead of requiring our entire page to be reloaded when submitting the form. If the default behavior of enhance has not quite satisfied our needs, it can be customized. If we decide to change its default behavior and provide it with a custom callback function, applyAction can be used to update the data within the form property of our components. The final binding we can import from $app/forms is deserialize, which is a helpful function when deserializing response data from a form submission.

$app/navigation

As expected, $app/navigation provides tools pertaining to navigation. We previously used invalidateAll in Chapter 5 and invalidate in Chapter 9 from this module. In both of those instances, we did so to force load() to run again. Some other helpful bindings from this module are afterNavigate and beforeNavigate. Both of these bindings run callback functions at specific timings within the SvelteKit life cycle. With afterNavigate, the provided callback is executed once the current component has mounted and after the user has navigated to a new URL. The callback function for beforeNavigate is run just before navigating to a new URL.

Some other bindings available from this particular module include disableScrollHandling, goto, preloadCode, and preloadData. If we wanted to change how SvelteKit manages the browser window scrolling position, we could disable it entirely by calling disableScrollHandling(). The goto() function provides developers with the ability to navigate to another URL while also including options that allow for the management browser history, keeping focus applied to a particular element, and even triggering the rerun of load() functions. The preloadCode() function allows developers to import the code for a particular route before that route has been navigated to, while preloadData() will do the same as well as calling the route’s load() function. The same behavior of preloadData() is found when <a> elements are given the data-sveltekit-preload-data attribute.

$app/paths

When we need to manipulate file paths or create links to routes for our application that reside in a sub-directory, we can rely on $app/paths. Both assets and base will return a string value that can be customized in svelte.config.js under config.kit.paths. If the application is being served from a subdirectory, we can prepend manually written routes with the {base} text to ensure our application serves the route from the correct directory and does not attempt to serve the route from the domain root directory. The value provided by base must always be a root-relative path that begins with a / but never ends with one. Conversely, assets will always be an absolute path to the application files.

$app/stores

The SvelteKit developers were kind enough to provide developers with a few readable stores that can supply us with helpful information. When importing from $app/stores, we’ll have access to navigating, page, updated, and getStores. During navigation, navigating will be populated with an object consisting of metadata such as where the navigation event started, where it is going, and the type of navigation. The type can range from a form submission to a link click, or even a browser back-and-forward event. Once navigation has been completed, the value of this store will return to null. Meanwhile, page serves as a store that contains information related to the currently viewed page. We used it back in Chapter 4 to display the current page’s error message. The updated store will return a Boolean value after SvelteKit has checked whether or not a new version of the application has been detected. All of these stores can be retrieved by calling getStores()but doing so is not recommended and should only be done when the store subscription needs to be paused until after a component has mounted. Otherwise, all store values can be accessed by prefixing the store name with the $ symbol, which will automatically handle the subscription process.

$service-worker

When building a PWA, we will inevitably find ourselves configuring a service worker. For these cases, we’re provided with the $service-worker module, which can only be used within a service worker. When importing bindings, we’ll have access to base, build, files, prerendered, and version. Again, sane naming conventions come to our rescue and mostly explain the type of data returned from each of these bindings. We can receive a string value from base, which works similarly to the base from $app/paths. It will provide us with the base path to the application even if the application exists in a subdirectory. The array of strings from build will consist of URLs generated by Vite during the build process. Another array of strings, files, will provide details on static files or those included in config.kit.files.assets. For prerendered path names, we can retrieve the strings from the prerendered array. And finally, we can use version to determine the application version within our service worker code.

This list of modules is by no means comprehensive. Before leaning on them too heavily, it’s recommended to read the official SvelteKit documentation listed at the end of this chapter. Now that we’ve examined some of these modules, let’s move on to the modules that help us keep sensitive information safe.

Keeping secrets safe

When it comes to keeping secrets such as API keys or database credentials safe, SvelteKit has us covered. As we saw in Chapter 9, we can import .env secrets from $env/static/private. But this is not the only module that allows us to import environment variables. In this section, we’ll examine more modules and how they all can help us import environment variables as well as secrets.

$env/static/private

Beginning with the module we’ve already used, $env/static/private is great for importing environment variables like those specified in .env files or those set when starting the runtime. For instance, if we were to start our application with the API_KEY="" node index.js command, the API_KEY variable would be available, just as GITHUB was available after we imported $env/static/private in Chapter 9. Any environment variables provided when starting the application will override the value of those provided in a .env file. The variables from this module are statically bundled within the application code at build time by Vite. This means less bundled code but also means that secrets will be included in the application build. We can confirm this by building the following commands:

npm run build
grep -r 'YOUR_API_KEY' .svelte-kit/

Substituting YOUR_API_KEY with your personal access token provided by GitHub will show the text and the file in our build where our API key has been injected. As such, we should be cautious not to commit builds to version control as doing so could then expose secrets. Fortunately for us, this module will only work with server-side code and will cause a build to fail if we attempt to import it into client-side code.

$env/static/public

We can consider $env/static/public a sibling to $env/static/private. The major difference is that this module will only import variables that begin with the value set in config.kit.env.publicPrefix. By default, this value is PUBLIC_. This allows us to keep our secrets all in the same .env file while allowing us to specify which are safe to expose to clients and which are not. For example, the following .env file would allow for PUBLIC_GITHUB_USER to be imported into client-side code but not GITHUB_TOKEN. Even though both values exist in the same file, we can rest assured knowing that SvelteKit won’t tell our secrets to anyone other than the server we know we can trust:

.env

GITHUB_TOKEN=YOUR_GITHUB_PERSONAL_ACCESS_TOKEN
PUBLIC_GITHUB_USER=YOUR_USERNAME_HERE

$env/dynamic/private

Just as we cannot import $env/static/private into client-side code, we cannot import $env/dynamic/private into client-side code either. The difference between these two modules is that while the $env/static modules have access to .env files, $env/dynamic has access to the environment variables specified by the adapter. Think back to Chapter 8 when we deployed our application to Cloudflare. When we did that, we specified the environment variable NODE_VERSION. Obtaining the Node version likely isn’t very useful to us but using $env/dynamic/private allows us to access other secrets set in our Cloudflare Pages project settings. This can be helpful when working in a team as sharing secrets can be done on the platform rather than passing around .env files. When the platform the project will be deployed to has its own means of setting environment variables, it’s very likely you’ll be relying on $env/dynamic to access them.

$env/dynamic/public

By following the established pattern, this module should need little explanation. With $env/dynamic/public, we will only be able to import environment variables that begin with PUBLIC_ or whatever value has been specified in config.kit.env.publicPrefix. This works in the same way as $env/static/public. Of course, it differs from $env/static/public because this is another dynamic module, which means it is specific to the configured environment adapter. For instance, if we were to add PUBLIC_GITHUB_USER to our Cloudflare Pages environment variables, we would then be able to access the value of that environment variable using this module.

Summary

There are a great many modules available within SvelteKit. Hopefully, this brief overview has given enough insight so that we know where to start with each of them. In the next chapter, we’ll examine some best practices for enhancing accessibility, which can come with the added benefit of improving Search Engine Optimization (SEO).

Resources

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset