npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@elo7/fastify-svelte

v3.0.0

Published

Fastify plugin for using Svelte as a view engine (server-side rendering)

Downloads

5

Readme

fastify-svelte

Fastify plugin for using Svelte as a view engine (server-side rendering)

Table of Contents

  1. Installation
  2. Usage
  3. View method's API
  4. Constructor's API
  5. Plugins

Installation

To install this plugin, run the command:

# npm
npm install --save @elo7/fastify-svelte
# yarn
yarn add @elo7/fastify-svelte

Usage

Using your fastify instance, register the plugin:

// src/server.js
import fastify from 'fastify';
import sveltePlugin from 'fastify-svelte';

const app = fastify();
app.register(sveltePlugin);

The plugin accepts some options, which are detailed in the "Constructor's API" section below.

Consider that you have, the following file structure:

|-> rollup.config.js
|-> src/
| |-> server.js
| |-> views/
| |   |-> Home/
| |   |   |-> template.svelte
| |   |-> template/
| |   |   |-> template.js
| |-> controller/
| |   |-> Home.js

In your controller, for returning an visual page as a response do:

// src/controllers/Home.js

app.get('/', (req, reply) => {
	reply.view('Home', { name: 'John Doe' }, { themeColor: '#fff' });
});

This will send the server side rendered home page, constructed using the second argument as props for the page, and the third argument is passed to the generic template as is.

The plugin expects that you have compiled your Svelte templates beforehand to a ES Module format. You can do this by using a bundler such as Rollup or Webpack in your project. For an example, your rollup.config.js could look like this:

import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import glob from 'glob';

const templates = glob.sync('src/**/template.svelte');

const dev = NODE_ENV === 'development';

const serverSideConfig = (template) => ({
	input: template,
	output: {
		file: template.replace('svelte', 'js'),
		format: 'esm',
	},
	plugins: [
		svelte({
			css: (css) => {
				css.write(template.replace('src', 'static/css').replace('svelte', 'css'), false);
			},
			dev,
			generate: 'ssr',
		}),
		resolve(),
		commonjs(),
	],
});

const clientSideConfig = (template) => ({
	input: template,
	output: {
		file: template.replace('src', 'static/js').replace('svelte', 'js'),
		format: 'iife',
		name: 'Page',
	},
	plugins: [
		svelte({
			css: false,
			dev,
			hydratable: true,
		}),
		resolve(),
		commonjs(),
	],
});

export default [
	...templates.map(serverSideConfig),
	...templates.map(clientSideConfig),
];

Your generic template.js should look like this, this will be used as the skeleton for your page, adding meta tags and providing anchors for your svelte page to be mounted, this template receives an object that contains both the css, the script and the html (named as content here) generated by the svelte page compilation, the props used to hydrate the component, once the page is loaded by the user and the extraData passed throgh the controller

// src/views/template/template.js
export default ({ css, script, content, props, extraData }) => `<!DOCTYPE html>
<html lang='en'>

<head>
	<meta charset='utf-8'>
	<meta name='viewport' content='width=device-width, initial-scale=1'>
	<link rel='stylesheet' href='${css}'>
	<meta name="theme-color" content="${extraData.themeColor}">
</head>

<body>
	<div id='content'>
		${content}
	</div>
	<script src='${script}'></script>
	<script>
		new Page({
			hydrate: true,
			props: ${props},
			target: document.getElementById('content'),
		});
	</script>
</body>

</html>`;

View method's API

This plugin will make available the reply.view method, which receives three arguments:

Path (first argument)

Required: true

This is the path of the directory where the file template.svelte is, the plugin's option svelteTemplatesPath will be appended to argument path, as well as the return of the platform option. For an example look at the assetUrlForConstructor explanation.

Props (second argument)

Required: false

This is the props object that will be used to render the component passed through the first argument.

Extra data (third argument)

Required: false

This object will be passed to your generic template.js as is.

Constructor's API

This plugin can receive three options, all are optional:

Platform

Default: () => ''

The platform argument is used to be appended with the path of an specified page. In the example below, the plugin will look for the templates under src/views/<path>/mobile or src/views/<path>/desktop:

const isMobile = (reply) => // implement your logic here.

app.register(sveltePlugin, {
	platform: (reply) => isMobile(reply) ? 'mobile' : 'desktop',
});

SvelteTemplatesPath

Default: <rootdir>/src/views

The svelteTemplatesPath argument is used to specify the path where templates are found. In the example below, the plugin will look for the templates under <rootdir>/src/pageViews:

app.register(sveltePlugin, {
	svelteTemplatesPath: `{__dirname}/pageViews`,
});

Note that the code present in the example assumes that you are calling the plugin's constructor under <rootdir>/src.

AssetUrlForConstructor

Default:

() => (page, type) => {
	return `/static/${type}/views/${page}/template.${type}`;
};

The assetUrlForConstructor argument is used to specify how the path of a page is translated in its assets, the javascript file and the css one. It receives the fastify instance as its only argument, and it must return a function, which receives two arguments and returns a path to an asset. The page argument will be the path given to the reply.view first argument with the return of the platform function appended, for example, if you have a code that look like this:

// src/server.js
app.register(sveltePlugin, {
	platform: () => 'mobile',
});

// src/controllers/Home.js
app.get('/', (req, reply) => {
	return reply.view('pages/Home');
};

The page argument value will be pages/Home/mobile. And the type argument value will be either js or css. Below, we have an example where the asset's path is just static folder and the function logs to the console when a template is found.

app.register(sveltePlugin, {
	assetUrlForConstructor: (app) => {
		app.log.info('Template found');
		return (page, type) => `/static/${page}.${type}`
	}
});

Plugins

This fastify's plugin accepts its own plugins, so you can extend its functionality. The plugins are passed as itens in an array.

import sveltePartialHydration from
'@elo7/fastify-svelte-parital-hydration-plugin`;

app.register(sveltePlugin, {
	plugins: [sveltePartialHydration],
});

Plugins

This fastify's plugin accepts its own plugins, so you can extend its functionality. Each plugins specifies in which stage of the fastify-svelte process and the key that the value returned by the plugin will occupy in the object passed to the template.js. For an example on how to build a plugin, check Partial Hydration Plugin.