├── .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 | --------------------------------------------------------------------------------