Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error "new URL(url, import.meta.url) is not supported in SSR." with ssr: false & adapter-static #1896

Closed
tontoko opened this issue Jul 13, 2021 · 13 comments
Labels
bug Something isn't working vite
Milestone

Comments

@tontoko
Copy link

tontoko commented Jul 13, 2021

Describe the bug

I'm trying to get sveltekit to work with wasm.
(Built with wasm-pack).
It works fine in the development environment, but I get an error only when building.

vite v2.4.1 building SSR bundle for production...
...
Error: `new URL(url, import.meta.url)` is not supported in SSR.

Looking at the error log, it appears that the js-script generated by wasm-pack is SSR-bundled, even though it is run only on the client side.

What I've tried:

  • set ssr: false in svelte.config.js
  • use @sveltejs/adapter-static and spa-mode
  • dynamic import wasm(wasm-pack generated) in onMount

Reproduction

/svelte.config.js

import preprocess from 'svelte-preprocess';
import { ViteRsw } from 'vite-plugin-rsw';
import adapter from '@sveltejs/adapter-static';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	preprocess: preprocess(),

	kit: {
		adapter: adapter({
                         // spa-mode 
                         // https://github.com/sveltejs/kit/tree/master/packages/adapter-static#spa-mode
			fallback: '200.html'
		}),
		ssr: false,
		prerender: {
			enabled: false
		},
		target: '#svelte',
		vite: {
			input: {
				markdown_wasm: './markdown_wasm/Cargo.toml'
			},
			plugins: [
				ViteRsw({
					crates: [
						{ name: 'markdown_wasm', outDir: './pkg' }
					]
				})
			]
		}
	}
};

export default config;

where wasm is called

<script lang="typescript">
	import { onMount } from 'svelte';
	let text = '';
	let html = '';
	let init
	let pulldown_cmark
	
	onMount(async () => {
		const i = await import('../../markdown_wasm/pkg/markdown_wasm')
		init = i.default
		pulldown_cmark = i.pulldown_cmark
	})
		
	const handleTextChange = async () => {
		if (!init) return
		await init();
		html = pulldown_cmark(text);
	};
</script>

init() (js-script which wasm-pack generated)

async function init(input) {
    if (typeof input === 'undefined') {
        input = new URL('index_bg.wasm', import.meta.url);
    }
    const imports = {};
    imports.wbg = {};
    imports.wbg.__wbindgen_throw = function(arg0, arg1) {
        throw new Error(getStringFromWasm0(arg0, arg1));
    };

    if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
        input = fetch(input);
    }


    // WebAssembly.instantiate(module, imports) or WebAssembly.instantiateStreaming(module, imports) are called in load(module, imports) 
    const { instance, module } = await load(await input, imports);

    wasm = instance.exports;
    init.__wbindgen_wasm_module = module;

    return wasm;
}

Logs

Tomohiko@hiraki sveltekit-wasm % npm run build

> sveltekit-wasm@0.0.1 build
> svelte-kit build


🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
⚡️⚡️         Hello RSW!           ⚡️⚡️
⚡️⚡️  Vite + Rust 💖 WebAssembly  ⚡️⚡️
🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
vite-plugin-rsw (1.8.0)
[rsw::deploy] https://github.com/lencx/rsw-node


🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
⚡️⚡️         Hello RSW!           ⚡️⚡️
⚡️⚡️  Vite + Rust 💖 WebAssembly  ⚡️⚡️
🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
vite-plugin-rsw (1.8.0)
[rsw::deploy] https://github.com/lencx/rsw-node

vite v2.4.1 building for production...
transforming (7) src/routes/todos/index.svelte
[rsw::build] markdown_wasm_bg.wasm ~> /_app/assets/markdown_wasm_bg.34797c41.wasm
✓ 39 modules transformed.
.svelte-kit/output/client/_app/assets/svelte-logo.87df40b8.svg                           1.85kb
.svelte-kit/output/client/_app/assets/markdown_wasm_bg.a665361f.wasm                     8034.25kb
.svelte-kit/output/client/_app/assets/fira-mono-cyrillic-ext-400-normal.b3140dd3.woff2   16.11kb
.svelte-kit/output/client/_app/assets/fira-mono-greek-ext-400-normal.8659ae46.woff2      7.85kb
.svelte-kit/output/client/_app/assets/fira-mono-cyrillic-400-normal.046b609f.woff2       9.08kb
.svelte-kit/output/client/_app/assets/fira-mono-greek-400-normal.1f8b3a07.woff2          10.48kb
.svelte-kit/output/client/_app/assets/fira-mono-latin-ext-400-normal.b6331a25.woff2      11.84kb
.svelte-kit/output/client/_app/assets/fira-mono-latin-400-normal.a2f9dbe8.woff2          16.44kb
.svelte-kit/output/client/_app/assets/fira-mono-all-400-normal.0d19eb5d.woff             75.54kb
.svelte-kit/output/client/_app/assets/markdown_wasm_bg.34797c41.wasm                     8034.25kb
.svelte-kit/output/client/_app/manifest.json                                             3.68kb
.svelte-kit/output/client/_app/error.svelte-2e34e082.js                                  1.55kb / brotli: 0.64kb
.svelte-kit/output/client/_app/pages/index.svelte-53d803f5.js                            4.06kb / brotli: 1.45kb
.svelte-kit/output/client/_app/pages/__layout.svelte-c0f95ef0.js                         4.62kb / brotli: 1.51kb
.svelte-kit/output/client/_app/pages/embossToImage.svelte-a91b4e29.js                    2.65kb / brotli: 1.16kb
.svelte-kit/output/client/_app/pages/markdown.svelte-64e4311e.js                         1.50kb / brotli: 0.75kb
.svelte-kit/output/client/_app/pages/about.svelte-6e209491.js                            2.39kb / brotli: 0.90kb
.svelte-kit/output/client/_app/chunks/preload-helper-9f12a5fd.js                         0.61kb / brotli: 0.31kb
.svelte-kit/output/client/_app/pages/todos/index.svelte-0c565c3b.js                      6.11kb / brotli: 2.12kb
.svelte-kit/output/client/_app/assets/start-a8cd1609.css                                 0.16kb / brotli: 0.10kb
.svelte-kit/output/client/_app/assets/pages/__layout.svelte-ded7473c.css                 5.06kb / brotli: 1.36kb
.svelte-kit/output/client/_app/start-77c5bb20.js                                         17.84kb / brotli: 5.55kb
.svelte-kit/output/client/_app/assets/pages/embossToImage.svelte-8d18bb30.css            0.14kb / brotli: 0.08kb
.svelte-kit/output/client/_app/assets/pages/index.svelte-078f1a0b.css                    1.35kb / brotli: 0.36kb
.svelte-kit/output/client/_app/assets/pages/markdown.svelte-361b27bc.css                 0.16kb / brotli: 0.10kb
.svelte-kit/output/client/_app/assets/pages/about.svelte-4db5be0d.css                    0.11kb / brotli: 0.07kb
.svelte-kit/output/client/_app/chunks/vendor-ab59cbb9.js                                 13.88kb / brotli: 5.39kb
.svelte-kit/output/client/_app/assets/pages/todos/index.svelte-05e41044.css              3.72kb / brotli: 0.86kb
.svelte-kit/output/client/_app/chunks/markdown_wasm-1d577caa.js                          29.73kb / brotli: 5.20kb

🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
⚡️⚡️         Hello RSW!           ⚡️⚡️
⚡️⚡️  Vite + Rust 💖 WebAssembly  ⚡️⚡️
🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀
vite-plugin-rsw (1.8.0)
[rsw::deploy] https://github.com/lencx/rsw-node

vite v2.4.1 building SSR bundle for production...
✓ 28 modules transformed.
[asset-import-meta-url] `new URL(url, import.meta.url)` is not supported in SSR.
file: /Users/Tomohiko/workspace/sveltekit-wasm/markdown_wasm/pkg/markdown_wasm.js:4066:16
4064: async function init(input) {
4065:     if (typeof input === 'undefined') {
4066:         input = new URL('markdown_wasm_bg.wasm', import.meta.url);
                      ^
4067:     }
4068:     const imports = {};
> `new URL(url, import.meta.url)` is not supported in SSR.
Error: `new URL(url, import.meta.url)` is not supported in SSR.
    at error (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/rollup/dist/shared/rollup.js:151:30)
    at throwPluginError (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/rollup/dist/shared/rollup.js:19296:12)
    at Object.error (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/rollup/dist/shared/rollup.js:19948:20)
    at Object.error (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/rollup/dist/shared/rollup.js:19472:38)
    at Object.transform (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/vite/dist/node/chunks/dep-cc49d7be.js:50723:30)
    at Object.<anonymous> (/Users/Tomohiko/workspace/sveltekit-wasm/node_modules/vite/dist/node/chunks/dep-cc49d7be.js:51204:19)
    at /Users/Tomohiko/workspace/sveltekit-wasm/node_modules/rollup/dist/shared/rollup.js:20153:25

System Info

System:
    OS: macOS 11.4
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 7.12 GB / 64.00 GB
    Shell: 3.2.57 - /bin/sh
  Binaries:
    Node: 16.3.0 - ~/.nvm/versions/node/v16.3.0/bin/node
    npm: 7.15.1 - ~/.nvm/versions/node/v16.3.0/bin/npm
  Browsers:
    Chrome: 91.0.4472.114
    Safari: 14.1.1
  npmPackages:
    @sveltejs/adapter-static: ^1.0.0-next.13 => 1.0.0-next.13 
    @sveltejs/kit: next => 1.0.0-next.124 
    svelte: ^3.38.3 => 3.38.3

Severity

annoyance

Additional Information

No response

@tontoko tontoko added the bug Something isn't working label Jul 13, 2021
@tontoko tontoko changed the title Error new URL(url, import.meta.url) is not supported in SSR. with ssr: false & adapter-static Error `new URL(url, import.meta.url) is not supported in SSR.` with ssr: false & adapter-static Jul 13, 2021
@tontoko tontoko changed the title Error `new URL(url, import.meta.url) is not supported in SSR.` with ssr: false & adapter-static Error "new URL(url, import.meta.url) is not supported in SSR." with ssr: false & adapter-static Jul 13, 2021
@NiQ-B
Copy link

NiQ-B commented Jul 15, 2021

@tontoko I am just commenting on this issue because I wrestled with it for a few hours myself and came up with a work around. I don't believe this is an actual svelte-kit issue, I believe it can be traced all the way back to wasm-pack. The challenge is the way svelte-kit can compile a component for both SSR and CSR.

In your /Users/Tomohiko/workspace/sveltekit-wasm/markdown_wasm/pkg/markdown_wasm.js file this line
4066: input = new URL('markdown_wasm_bg.wasm', import.meta.url);

can't be transformed by the SSR compiler because it contains the URL javascript keyword as you can see above the client compiler completes just fine. I myself tried ever permutation to get the SSR compiler to ignore that line but then you can't use wasm in SSR :( so that isn't a solution.

Anyway all that to say you have to remove line# 4066 or any line that contains new URL and then pass in the string url to the init function. The regex is used to parse the url during build and will return a string in dev. Also update the function to the path of your wasm.js file and .wasm files.

Hope this helps.

export const wasm_boot = async () => {
  const res = (await import('$rsw/bin_comm/pkg/wasm_library_bg.wasm'))
    .default
    .toString()
    .match(/\(t\,\"(.*)\"\)/)

  const url = res ? res[1] : "/@rsw/bin_comm/pkg/wasm_library_bg.wasm";
  const init = (await import('$rsw/bin_comm/pkg')).default;
  const { add } = (await import('$rsw/bin_comm/pkg'));
  const initialized: WebAssembly.Module = await init(url);

  return {initialized, add}
}

@tontoko
Copy link
Author

tontoko commented Jul 16, 2021

@NiQ-B Thanks for your comments!
I tried your workaround and found another workaround by accident.

// for my wasm file: const {pulldown_cmark} = await wasm_boot('../../markdown_wasm/pkg/markdown_wasm')
export const wasm_boot = async (wasmPath: string) => {
	const init = (await import(wasmPath + '.js')).default;
	const fn = await import(wasmPath + '.js');
	const initialized: WebAssembly.Module = await init(wasmPath + '_bg.wasm');

	return { initialized, ...fn };
};

When I ran npm run dev, I got the following warning.

/Users/Tomohiko/workspace/sveltekit-wasm/src/lib/wasm_boot.ts
1  |  export const wasm_boot = async (wasmPath) => {
2  |    const init = (await import(wasmPath + ".js")).default;
3  |    const fn = await import(wasmPath + ".js");
   |                            ^
4  |    const initialized = await init(wasmPath + "_bg.wasm");
5  |    return { initialized, ...fn };
The above dynamic import cannot be analyzed by vite.
See https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations for supported dynamic import formats. If this is intended to be left as-is, you can use the /* @vite-ignore */ comment inside the import() call to suppress this warning.

  Plugin: vite:import-analysis
  File: /Users/Tomohiko/workspace/sveltekit-wasm/src/lib/wasm_boot.ts

As vite:import-analysis says, I don't think this is a good way to do it.
But at least in my environment, it can be builded and worked with following configs.
(I checked with cd build && python -m SimpleHTTPServer 8000 for adapter-static)

svelte.config.js

import staticAdapter from '@sveltejs/adapter-static';
const config = {
	kit: {
		adapter: staticAdapter(),
                ...
	}
}

locate wasm files in /build

or

import nodeAdapter from '@sveltejs/adapter-node';
const config = {
	kit: {
		adapter: nodeAdapter(),
                ...
	}
}

locate wasm files in /build/assets

@doomnoodles
Copy link

doomnoodles commented Sep 29, 2021

Made a proof of concept with ssr that works automtically sveltekit-rust-ssr-template

@saaadasdsad
Copy link

saaadasdsad commented Oct 8, 2021

Same error using "@wasm-tool/rollup-plugin-rust" with vite and svelte-kit
npm run build

87: async function init(input) {
88:     if (typeof input === 'undefined') {
89:         input = new URL('index_bg.wasm', import.meta.url);
                    ^
90:     }
91:     const imports = {};
> `new URL(url, import.meta.url)` is not supported in SSR.
Error: `new URL(url, import.meta.url)` is not supported in SSR.
    at error (/prj/node_modules/rollup/dist/shared/rollup.js:158:30)
    at throwPluginError (/prj/node_modules/rollup/dist/shared/rollup.js:21741:12)
    at Object.error (/prj/node_modules/rollup/dist/shared/rollup.js:22415:20)
    at Object.error (/prj/node_modules/rollup/dist/shared/rollup.js:21917:38)
    at Object.transform (/prj/node_modules/vite/dist/node/chunks/dep-55830a1a.js:42795:30)
    at Object.<anonymous> (/prj/node_modules/vite/dist/node/chunks/dep-55830a1a.js:43303:19)
    at /prj/node_modules/rollup/dist/shared/rollup.js:22620:25

@antnn
Copy link

antnn commented Oct 13, 2021

I wrote simple base plugin for vite. It works well (it seems) with SSR and sveltekit (adapter-static)
https://gist.github.com/antnn/281d969c61f9ee340d83b92116013d5a

@benmccann
Copy link
Member

I would expect this is fixed now by passing ssr: false as a resolve option in handle. Previously SvelteKit would need to load a page on the server even when not rendering it, but that is no longer true. Please try again and let me know whether it works or not now. If I don't hear anything I will close this issue

@falsetru
Copy link

falsetru commented Mar 7, 2022

Same error with ssr disabled.

[vite:asset-import-meta-url] `new URL(url, import.meta.url)` is not supported in SSR.
file: /home/falsetru/h/falsetru.bitbucket.io/page-src/read-slang/pkg/read_slang.js:153:16
151: async function init(input) {
152:     if (typeof input === 'undefined') {
153:         input = new URL('read_slang_bg.wasm', import.meta.url);
                     ^
154:     }
155:     const imports = {};
> `new URL(url, import.meta.url)` is not supported in SSR.
    at error (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/rollup/dist/shared/rollup.js:199:30)
    at throwPluginError (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/rollup/dist/shared/rollup.js:21848:12)
    at Object.error (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/rollup/dist/shared/rollup.js:22571:20)
    at Object.error (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/rollup/dist/shared/rollup.js:22025:42)
    at Object.transform (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/vite/dist/node/chunks/dep-9c153816.js:38785:30)
    at Object.<anonymous> (/home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/vite/dist/node/chunks/dep-9c153816.js:39320:19)
    at /home/falsetru/h/falsetru.bitbucket.io/page-src/node_modules/rollup/dist/shared/rollup.js:22817:37

  • src/hooks.js
export async function handle({ event, resolve }) {                                                                                    
    const ssr = false;
    const response = await resolve(event, { ssr });
    return response;
}

@benmccann
Copy link
Member

Thanks. Can you please provide a repository that reproduces this issue? I don't have a .wasm file to reproduce this with

@falsetru
Copy link

falsetru commented Mar 7, 2022

@benmccann
Copy link
Member

benmccann commented Mar 7, 2022

Thanks!

Hmm. Even putting the code behind a browser and onMount check doesn't help. The onMount code is a no-op
that is never called (sveltejs/svelte#6416), but is still left in place. The code wrapped in a browser check should end up getting removed and code shaken out, but I think that doesn't happen until later in the build process

Maybe the Svelte compiler could remove the code in onMount? Or maybe the Vite transform could be a no-op in SSR and then a check at the very end of the build process in closeBundle or something could see if import.meta.url is still present and throw then instead of earlier on where it does now?

For reference, here's where the error is triggered in Vite

@benmccann
Copy link
Member

Maybe the Svelte compiler could remove the code in onMount?

Rich said we it can't do this in the svelte compiler, because it would need to apply to custom lifecycle functions in .js modules

@benmccann
Copy link
Member

A fix for this has been merged and will be included in Vite 2.9

@miunau
Copy link

miunau commented Mar 9, 2022

fwiw here's my cursed hack for a project that has a module compiled with emscripten that was needed in an endpoint.

You can also inline the entire thing with the -s SINGLE_FILE flag if you feel like digging into the makefile of your project, then only import the generated js file, skipping all of this. wasm-pack probably has something similar?

  1. Turn .wasm file into base64
// encode.js
import fs from 'fs';
const f = fs.readFileSync('mt63Wasm.wasm');
fs.writeFileSync('mt63Wasm.txt', f.toString('base64'));
node encode.js
  1. Copy result and paste it into a file in your lib:
// wasmBuf.ts
const wasmBuf = Buffer.from(...base64 contents here..., 'base64');
export wasmBuf;
  1. Wedge generated module code to just use the buffer directly
// generatedWasm.js
...
  return (
      function(Module, binary) { // pass binary with Module
          Module = Module || {};
...

          function getBinaryPromise() {
              return Promise.resolve().then(function() {
                  return binary;
              })
          }
  1. Pass the buffer from the imported file to the initializer:
// some-endpoint.ts
import { wasmBuf } from '$lib/wasm/wasmBuf.js';
import { Module } from '$lib/wasm/generatedWasm.js';

/** @type {import('@sveltejs/kit').RequestHandler} */
export async function get({ params }) {

  const mod = await Module({}, wasmBuf);
  // Tada

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vite
Projects
None yet
Development

No branches or pull requests

9 participants