This tool gives an ability to run express.js server to render svelte.js application on server side with functionality to preload svelte.js application data via api requests before send response to client.
Take a look at fully packed example of integration with webpack in svelte-ssr-template-webpack.
⚠️ Currently this tool supports only webpack.js assets bundler.
You can run this tool in production or development modes.
Firstly you have to build your app with assets bundler.
As output you need client.js
and server.js
.
Then you need to start server.js
with node.js
and this service will perform server side rendering requests.
In development mode this tool will launch development server for client.js
and server.js
and node.js
service to perform server side rendering requests.
1. Install via npm
npm install --save svelte-ssr
1. Create index.html
file inside src
folder
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
</head>
<body>
<div id="root"></div>
</body>
</html>
1. Create App.svelte
file inside src
folder
<script context="module">
/**
* @param {{ base: string, path: string, inner: string, query: {} }} location - requested location
* @param {resolveCallback} resolve - resolve prepared result
* @param {{ redirect: redirectCallback }} helpers - preload helpers
* @returns any
*/
export async function preload(location, resolve, helpers) {
// preload data with api requests for example via `axios`
return { preloaded: { foo: 'bar' } };
}
/**
* Return resolved candidate.
* @callback resolveCallback
* @param {any} candidate
* @param {callback} prepare
*/
/**
* Return redirect instance.
* @callback redirectCallback
* @param {number} status
* @param {string} url
*/
</script>
<script>
// `client`, `server` or `node`
export let entry = process.env.ENTRY;
// this property will be available
// only in server side rendering scenario
export let path = undefined;
// data which has been preloaded
// from the preload method
export let preloaded = {};
</script>
<div id="app">
<!-- render content -->
</div>
3. Create server.js
file inside src
folder
import path from 'path';
import {
cleanServerInstanceOnExit,
createCatchMiddleware,
createRedirectMiddleware,
createRenderMiddleware,
createServer,
createServerInstance,
createStaticMiddleware,
resolveCommandOptions
} from 'svelte-ssr/server';
import component, { preload } from './App.svelte';
// create plain express server
const app = createServer();
// resolve command line arguments
const { port, base, staticProxyPort, staticPathToDirectory } = resolveCommandOptions();
// serve static content with the magic middleware
// if both development severs are running - this middleware
// serve files from client development server port
app.use(createStaticMiddleware({ base, staticProxyPort, staticPathToDirectory, verbose: true }));
// serve content to render based on desired template
// and render request content inside the target
const targetSelector = '#root';
const pathToTemplate = path.resolve(__dirname, '..', 'build', 'client', 'index.html');
app.use(createRenderMiddleware({
base,
component,
preload,
pathToTemplate,
targetSelector,
verbose: true,
debug: true
}));
// redirect all not resolved requests to the base
app.use(createRedirectMiddleware({ base, verbose: true }));
// log into console all errors
app.use(createCatchMiddleware({ verbose: true }));
// listen desired port by the server and clean server instance on node application exit event
const instance = createServerInstance(app, port, () => console.log(`Server is ready on ':${port}'`));
cleanServerInstanceOnExit(instance);
4. Create client.js
file inside src
folder
// import core dependencies
import { renderClient } from 'svelte-ssr/client';
import component from './App.svelte';
// import application styles
import './styles/global.pcss';
// render application inside the target
renderClient({ component, target: '#root' });
5. Create webpack.config.server.js
file
const path = require('path');
const { createWebpackServerConfig } = require('svelte-ssr/webpack');
const config = production => createWebpackServerConfig({
resolve: {
extensions: ['.mjs', '.js', '.svelte', '.json'],
alias: {
svelte: path.resolve(__dirname, 'node_modules', 'svelte')
}
},
module: {
rules: [
{
test: /\.svelte$/,
use: {
loader: 'svelte-loader',
options: {
emitCss: false,
generate: 'ssr',
hydratable: true,
hotReload: true,
dev: !production,
preprocess: require('svelte-preprocess')({ postcss: true })
}
}
},
{
test: [/\.css$/, /\.pcss$/],
loader: 'null-loader'
}
]
}
}, { production });
module.exports = (_, { mode }) => {
return config(mode === 'production');
};
6. Create webpack.config.client.js
file
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { addWebpackProductionHash, createWebpackClientConfig } = require('svelte-ssr/webpack');
const config = production => createWebpackClientConfig({
resolve: {
extensions: ['.mjs', '.js', '.svelte', '.json'],
alias: {
svelte: path.resolve(__dirname, 'node_modules', 'svelte')
}
},
module: {
rules: [
{
test: /\.svelte$/,
use: {
loader: 'svelte-loader',
options: {
emitCss: true,
hydratable: true,
hotReload: true,
dev: !production,
preprocess: require('svelte-preprocess')({ postcss: true })
}
}
},
{
test: [/\.css$/, /\.pcss$/],
use: [
{
loader: MiniCssExtractPlugin.loader,
options: { hmr: !production }
},
'css-loader',
'postcss-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: addWebpackProductionHash('[name].css', production)
}),
new HtmlWebpackPlugin({
inject: true,
template: path.resolve(__dirname, 'src', 'index.html')
})
]
}, { production });
module.exports = (_, { mode }) => {
return config(mode === 'production');
};
6. Add the following scripts to your package.json
file
{
"scripts": {
"start": "node ./node_modules/svelte-ssr/build/cli.js development -b webpack -c webpack.config.client.js -s webpack.config.server.js",
"build": "node ./node_modules/svelte-ssr/build/cli.js build -b webpack -c webpack.config.client.js -s webpack.config.server.js",
"production": "node ./node_modules/svelte-ssr/build/cli.js production -b webpack -c webpack.config.client.js -s webpack.config.server.js"
}
}
7. Run in development
mode
npm run start
8. Run in production
mode
npm run build
npm run production
This tool has a help to display all supported commands and options.
$ ./node_modules/.bin/svelte-ssr help
Usage: svelte-ssr [options] [command]
Tool to launch server side rendering service
Options:
-V, --version output the version number
-h, --help output usage information
Commands:
build [options] Build client and server entries
development [options] Launch client and server development servers and node server to serve server side rendering
production [options] Launch node server to serve server side rendering
$ ./node_modules/.bin/svelte-ssr build --help
Usage: svelte-ssr build [options]
Build client and server entries
Options:
-b, --bundler <webpack> Which tool to use to bundle assets (only webpack is supported right now)
-c, --client-config <config.client.js> Path to bundler tool client config
-s --server-config <config.server.js> Path to bundler tool server config
$ ./node_modules/.bin/svelte-ssr development --help
Usage: svelte-ssr development [options]
Launch client and server development servers and node server to serve server side rendering
Options:
-b, --bundler <webpack> Which tool to use to bundle assets (only webpack is supported right now)
--base </> Base html tag to listen for the server
-p --node-port <3000> Port to listen for server side rendering server
-c, --client-config <config.client.js> Path to bundler tool client config
--client-port <8080> Port to listen for client bundler
-s --server-config <config.server.js> Path to bundler tool server config
--server-port <8081> Port to listen for server bundler
$ ./node_modules/.bin/svelte-ssr production --help
Usage: svelte-ssr production [options]
Launch node server to serve server side rendering
Options:
-b, --bundler <webpack> Which tool to use to bundle assets (only webpack is supported right now)
--base </> Base html tag to listen for the server
-p --node-port <3000> Port to listen for server side rendering server
-c, --client-config <config.client.js> Path to bundler tool client config
-s --server-config <config.server.js> Path to bundler tool server config