├── .vscode
└── settings.json
├── .gitignore
├── public
└── favicon.png
├── src
├── Child.svelte
├── App.svelte
├── main.js
├── template.html
└── prerender.js
├── package.json
├── README.md
└── rollup.config.js
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | public
4 | !public/favicon.png
5 |
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akaSybe/svelte-prerender-example/HEAD/public/favicon.png
--------------------------------------------------------------------------------
/src/Child.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
Child component content
9 |
--------------------------------------------------------------------------------
/src/App.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 | Hello {name}!
14 |
15 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import App from "./App.svelte";
2 |
3 | const target = document.getElementById("app");
4 |
5 | target.innerHTML = "";
6 |
7 | const app = new App({
8 | target,
9 | props: {
10 | name: "world"
11 | },
12 | hydrate: true
13 | });
14 |
15 | export default app;
16 |
--------------------------------------------------------------------------------
/src/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Svelte Prerender Demo
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "build": "rollup -c",
6 | "serve": "serve public"
7 | },
8 | "devDependencies": {
9 | "html-minifier": "^4.0.0",
10 | "npm-run-all": "^4.1.5",
11 | "rimraf": "^3.0.0",
12 | "rollup": "^1.12.0",
13 | "rollup-plugin-bundle-html": "^0.2.1",
14 | "rollup-plugin-commonjs": "^10.1.0",
15 | "rollup-plugin-execute": "^1.1.1",
16 | "rollup-plugin-node-resolve": "^5.2.0",
17 | "rollup-plugin-svelte": "^5.0.3",
18 | "serve": "^11.1.0",
19 | "svelte": "^3.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/prerender.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const rimraf = require("rimraf");
4 | const minify = require("html-minifier").minify;
5 |
6 | const App = require(path.resolve(process.cwd(), "public/.temp/ssr.js"));
7 |
8 | const { html, css } = App.render({ name: "world" });
9 |
10 | const template = fs.readFileSync(
11 | path.resolve(process.cwd(), "public/index.html"),
12 | "utf-8"
13 | );
14 |
15 | const minifiedHtml = minify(html, {
16 | collapseWhitespace: true
17 | });
18 |
19 | const result = template.replace(
20 | "",
21 | `${minifiedHtml}`
22 | );
23 |
24 | fs.writeFileSync(path.resolve(process.cwd(), "public/index.html"), result);
25 | rimraf.sync(path.resolve(process.cwd(), "public/.temp"));
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Prerender Svelte app at build-time
2 |
3 | > :warning: I'd recommend you to use [rollup-plugin-svelte-ssr](https://github.com/akaSybe/rollup-plugin-svelte-ssr) instead. It uses the same approach but it's easier to use.
4 |
5 | This is an example how to prerender Svelte app
6 |
7 | ## Get started
8 |
9 | Install the dependencies
10 |
11 | ```bash
12 | npm install
13 | ```
14 |
15 | Build
16 |
17 | ```bash
18 | npm run build
19 | ```
20 |
21 | Run
22 |
23 | ```bash
24 | npm run serve
25 | ```
26 |
27 | Navigate to [localhost:5000](http://localhost:5000). You should see your app running
28 |
29 | ## How it works
30 |
31 | Rollup config consists of two separate configs:
32 |
33 | The first config used to build usual iife bundle with app.
34 |
35 | The second config used to build root component as [SSR component](https://svelte.dev/docs#Server-side_component_API). When SSR component bundled, Rollup executes script `prerender.js`, which uses SSR Component API to get HTML and CSS.
36 |
37 | ## Remarks
38 |
39 | It's experimental example. Maybe there is a more simple way.
40 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import svelte from "rollup-plugin-svelte";
2 | import resolve from "rollup-plugin-node-resolve";
3 | import commonjs from "rollup-plugin-commonjs";
4 | import execute from "rollup-plugin-execute";
5 | import html from "rollup-plugin-bundle-html";
6 |
7 | const production = !process.env.ROLLUP_WATCH;
8 |
9 | export default [
10 | {
11 | input: "src/main.js",
12 | output: {
13 | sourcemap: true,
14 | format: "iife",
15 | name: "app",
16 | file: "public/bundle.js"
17 | },
18 | plugins: [
19 | svelte({
20 | dev: !production,
21 | hydratable: true
22 | }),
23 | resolve({
24 | browser: true,
25 | dedupe: importee =>
26 | importee === "svelte" || importee.startsWith("svelte/")
27 | }),
28 | commonjs(),
29 | html({
30 | template: "src/template.html",
31 | dest: "public",
32 | filename: "index.html",
33 | inject: "body"
34 | })
35 | ]
36 | },
37 | {
38 | input: "src/App.svelte",
39 | output: {
40 | format: "cjs",
41 | file: "public/.temp/ssr.js"
42 | },
43 | plugins: [
44 | svelte({
45 | // enable run-time checks when not in production
46 | dev: !production,
47 | generate: "ssr"
48 | }),
49 | resolve({
50 | browser: true,
51 | dedupe: importee =>
52 | importee === "svelte" || importee.startsWith("svelte/")
53 | }),
54 | commonjs(),
55 | execute("node src/prerender.js")
56 | ]
57 | }
58 | ];
59 |
--------------------------------------------------------------------------------