I can't find any example anywhere online that shows how to (or if we can) output a single HTML file from a Svelte project using Rollup (not Webpack), containing all CSS and JS injected inline (and not as URLs in script).
-
1rollup does not generate or output a html file (though there are some [plugins that do](https://github.com/bengsfort/rollup-plugin-generate-html-template)), so your probably going to have the do it some other way (gulp maybe? [gulp-iinline](https://github.com/ashaffer/gulp-inline)), or write your own rollup plugin (or find a rollup plugin that does what you want, both html output and inline script / css, I could not find one). – 2pha May 02 '20 at 23:16
4 Answers
There is no built-in way to achieve this, so you'll have to write your own plugin to do so. This code is some sort of an attemt to get this done and could act as a starter point. It is in no way actually complete or good. (to be honest I doubt you will be winning any sort of performance with this approach)
import svelte from 'rollup-plugin-svelte';
import fs from 'fs';
import path from 'path';
function inlineSvelte(template, dest) {
return {
name: 'Svelte Inliner',
generateBundle(opts, bundle) {
const file = path.parse(opts.file).base
const code = bundle[file].code
const output = fs.readFileSync(template, 'utf-8')
bundle[file].code = output.replace('%%script%%', () => code)
}
}
}
export default {
input: 'src/main.js',
output: {
format: 'iife',
file: './public/index.html',
name: 'app'
},
plugins: [
svelte({
}),
inlineSvelte('./src/template.html')
]
};
This will rely on a template.html file that in it's most basic would like this
<html>
<head>
<script>%%script%%</script>
</head>
<body></body>
</html>

- 3
- 2

- 14,343
- 2
- 23
- 41
inliner can help
limit: inliner cant handle defer
scripts
so in your public/index.html
template file
move
<head>
<script defer src="/build/bundle.js"></script>
</head>
to after the </body>
tag, like
</body>
<script src="/build/bundle.js"></script>
</html>
now run inliner
npm i -D inliner
npm run build
npm run start &
sleep 5 # wait for webserver to start
npx inliner \
http://localhost:5000/index.html \
>build/index-inlined.html

- 2,447
- 1
- 18
- 25
The accepted answer should work though for Svelte 3
I have to modify it as follows:
// rollup.config.js
import svelte from 'rollup-plugin-svelte'
import resolve from '@rollup/plugin-node-resolve'
export default {
input: 'Static.svelte',
output: {
file: 'static.html'
},
plugins: [
svelte(),
resolve(),
{
generateBundle(options, bundle) {
const name = path.parse(options.file).base // static.html
const module = bundle[name].facadeModuleId // Static.svelte
// We ignore the bundle[name].code generated by other plugins
// and load the input module explicitly instead.
require('svelte/register')
const Static = require(module).default
bundle[name].code = Static.render().html
}
}
]
}
In the above code we have to use the *-svelte
plugin because Rollup accepts only Javascript
. Here the Rollup is used just to follow a familiar building process, we see input and output files' names in one place, and it saves the output file.
Use npm
as an alternative way (much faster):
// static.js
require('svelte/register')
const Static = require('Static.svelte').default
console.log(Static.render().html)
// package.json
{ ...
"scripts": {
"build": "node static.js > static.html"
}
}

- 1,556
- 1
- 14
- 26
this is my create example: https://github.com/wenjayliu/rollup-plugin-html-insert/tree/main/example/sevlte-template
use rollup-plugin-html-insert
import svelte from 'rollup-plugin-svelte'
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import dev from 'rollup-plugin-dev' // 开发服务器
import cleanupDir from 'rollup-plugin-cleanup-dir'
import terser from '@rollup/plugin-terser' // 代码压缩
import livereload from 'rollup-plugin-livereload'
import sveltePreprocess from 'svelte-preprocess'
import typescript from '@rollup/plugin-typescript'
import css from 'rollup-plugin-css-only'
import htmlInsert from 'rollup-plugin-html-insert'
const production = !process.env.ROLLUP_WATCH
export default {
input: 'src/main.ts',
output: {
dir: 'dist',
format: 'iife',
name: 'app',
sourcemap: !production,
entryFileNames: '[name].iife.[hash].js'
},
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
typescript({
sourceMap: !production,
inlineSources: !production
}),
htmlInsert({}),
dev({
dirs: ['dist']
}),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('dist'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser(),
production && cleanupDir()
],
watch: {
clearScreen: false
}
}

- 1
- 1