kit
kit copied to clipboard
Build an output that is usable from local disk (file:// URL)
Is your feature request related to a problem? Please describe.
Quite often i code tools which take some input (like a JSON file) and generate a HTML report out of it. This HTML report might be served by a server (e.g. Github Pages) but often just sits somewhere on the disk and should be openable/consumable from there (e.g. open file:///Users/x/projects/y/build/test/index.html
).
Describe the solution you'd like
From initial experiments (with adapter-static
) I found 2 things I would need for the above to work which I failed to accomplish with svelte-kit
so far:
- Links/Includes (from
index.html
) need to be relative instead of absolute-
paths/assets||base
were quite resistant setting up anything relative
-
- The JS field need to be in
IIFE
format (since module script imports will raise CORS issues)-
vite.build: { lib: { name: "my-app", entry: "src/main.ts", formats: ["iife"] }}
producedUMD and IIFE output formats are not supported for code-splitting builds
-
A solution would be to make the 2 things possible. Perfect would be a simple way to achieve that. Like an specialized adapter.
Describe alternatives you've considered
Maybe what I'm trying to achieve is dump and using svelte-kit for such a thing doesn't make much sense? Just stick to Svelte Classic
?
With Svelte Classic
and Vite I can accomplish the above by tweaking vite.config.js
in the following way:
- Set
base
to''
(makes the links relative) - Configure
IIEF
format:
build: {
lib: { name: "my-app", entry: "src/main.ts", formats: ["iife"] },
}
- Move the
index.html
topublic/
and add appropriate script and css includes
How important is this feature to you? This is the first thing I usually set up for the majority of apps I'm crafting.
I understand your pain as I have the same problem. See also issues https://github.com/sveltejs/kit/issues/1553 and https://github.com/sveltejs/kit/issues/1154.
@jzillmann Re your current Svelte Classic
& Vite
solution: could you go more into the routing?
@btakita Not sure what you mean...
@jzillmann How are you currently routing to the different "page" components in the SPA? I wonder if it's feasible to extract only the Sveltekit router to use with Classic Svelte & Vite.
--- Edit
I'm going to try to add use rollup
& @sveltejs/kit
as a git submodule
to directly output all of the JS & CSS into index.html
. Will expose some core functions such as create_manifest_data
and whatever else is useful to handle the routing. Fortunately kit is well factored. Hopefully it will work out.
Oh, I guess i just do customized routing, nothing special there!
This issue is essential for Electron apps, which use the filesystem.
All the links and scripts in the page are absolute, so it doesn't work.
Just a heads-up. I'm working on a fork of Sapper to support file://
hash-based routing. My project needs to continue supporting sapper until some SSR issues are fixed (https://github.com/vitejs/vite/issues/4306).
My current work in progress is at https://github.com/btakita/sapper/tree/hbr
I presume that SvelteKit & Sapper have similar routing. I'm using conditionals checking the window.location.origin === 'file://'
to use the Hash Based Routing strategy.
I had to attend to some other priorities & will continue with the hbr branch over the next couple of days.
@benmccann I was able to modify the routing to switch between hash-based routing when the origin is file://
& otherwise the default path-based-routing. https://github.com/btakita/sapper/tree/hbr
When the time comes to migrate my project over to Svelte Kit, I'll work on a PR. The conditionals are spread out in several places in https://github.com/btakita/sapper/blob/hbr/runtime/src/app/router/index.ts & https://github.com/btakita/sapper/blob/hbr/runtime/src/app/goto/index.ts.
I didn't want to do any major refactorings, lest the hbr branch diverge too far from the master branch.
Also hoping this can get added to sveltekit.
IMO This is essential for running native apps with svelte running in WebView as a GUI
Is there a workaround available?
I'd like to keep using SvelteKit for creating the full blown app with a server. But also need the SPA app to be run from file on client if no connection is available.
I've tried installing the vite-plugin-singlefile
and putting the default config in the svelte.config.js
, but the resulting bundle never shows up. I am not familiar with vite
.
any solution for now?
I want to use sveltekit
and adapter-static
to generate static html files use on cordova
, but there is no luck for now.
After a lot of tinkering I have managed to build a script that can take an html-file generated by adapter-static and inline all javascript in the file. It is very hacky and runs code in the browser to make the imports work, but it works for my use-case which is to build simple html-files with a bit of interactivity in them that I can send in an email without hosting them anywhere. Might be useful as inspiration for someone.
The trickiest part is that the only way I could use import
was if the the module was added as a blob to the page. But adding it as a blob generates a new url for the module, which means that all import
statements must be rewritten after the blob has been added.
https://github.com/mattiash/svelte-notebook/blob/master/util/inlinejs.cjs
I also came up with a hacky workaround for a similar issue including hash routing, not sure if it's specific to file:///
but as an index.html
being loaded from within an extension which I think is treated similarly.
- Create an
index.html/+page.svelte
route that is not prerendered, which is ran when the extension loads theindex.html
. Thisindex.html
route then redirects to the root route viagoto('/')
; - Hash routes are swapped in after route transitions (
handleRouteChange
withafterNavigate
on root+layout.svelte
) - On app initialization any initial hash routes are navigated to the correct route (
handleInitialHashRoute
withonMount
on root+layout.svelte
) and subsequently replaced with the hash route again.
This might what ya all are looking for: https://github.com/richardtallent/vite-plugin-singlefile
from https://github.com/sveltejs/kit/issues/2042#issuecomment-889818690 (has example)
I hope this is the correct issue to comment on.
My use-case is similar, even though I don't need it to work standalone with file://
.
I am trying to make a my application work within an electron app. For that, I found that if I was not using SvelteKit, I could configure vite with base: './'
and it would work as expected. With SvelteKit this currently seems impossible as all paths have to empty or absolute.
When I leave kit.paths.base
empty, it won't use what I put in vite either. Seems like the configuration for SvelteKit wins either way.
@till it would seem that SvelteKit always sets base to ./
when building the client:
https://github.com/sveltejs/kit/blob/cad0389e5f5f6d407e1c48f45d84c28c744d73aa/packages/kit/src/exports/vite/index.js#L431
Is there anything you notice being different in the output between a normal Vite build with ./
and a SvelteKit build?
@benmccann Maybe I am using it wrong, or using not the latest? I just upgraded to a 1.x
.
When I set base
in vite's config nothing happens, when I leave paths.base
empty in SvelteKit's configuration, all paths in the build are /
and then my app fails to run.
Hmm, looking at the code, maybe paths.base
vs paths.assets
?
Links/Includes (from index.html) need to be relative instead of absolute
The file references are relative now:
The JS field need to be in IIFE format (since module script imports will raise CORS issues)
Yep. It looks like this is the main blocker:
IIFE requires that we have only a single input, so in IIFE mode we would need to tweak that:
https://github.com/sveltejs/kit/blob/74798e94ab16db33887a2229ae03f6ec419d40f3/packages/kit/src/exports/vite/index.js#L407
This is highly related to https://github.com/sveltejs/kit/issues/3882. I'm not entirely sure what will be required to support IIFE beyond that. Probably we should try to use IIFE only on the client.
@benmccann is there anything to check on my end?
This is the code that gets generated currently:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-security-policy" content="">
<link rel="modulepreload" href="/_app/immutable/start-029f2991.js">
<link rel="modulepreload" href="/_app/immutable/chunks/index-1e690e6a.js">
<link rel="modulepreload" href="/_app/immutable/chunks/singletons-89169131.js">
<link rel="modulepreload" href="/_app/immutable/chunks/index-e3c86715.js">
</head>
<body class="flex flex-col items-center min-h-screen">
<script type="module" data-sveltekit-hydrate="45h">
import { start } from "/_app/immutable/start-029f2991.js";
start({
env: {},
paths: {"assets":"","base":""},
target: document.querySelector('[data-sveltekit-hydrate="45h"]').parentNode,
version: "1674548434903"
});
</script>
</body>
</html>
My svelte.config.js
:
// import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-static'
import preprocess from 'svelte-preprocess'
/** @type {import('@sveltejs/kit').Config} */
export default {
extensions: ['.svelte'],
kit: {
adapter: adapter({
// default options are shown
pages: 'build',
assets: 'build',
fallback: 'index.html',
precompress: false,
}),
},
preprocess: [
preprocess({
postcss: true,
}),
],
}
My vite.config.js
:
const config = {
build: {
minify: true,
},
resolve: {
alias: {
$routes: path.resolve('./src/routes'),
$store: path.resolve('./src/store'),
},
},
plugins: [sveltekit()],
}
export default config