Skip to content

Commit ce07134

Browse files
committed
feat: added support for wasm2js
This is *extremely* preliminary, and Perseus provides almost no support for this. This just makes the server integrations host a `bundle.wasm.js` file, there is no inbuilt facility for transpiling from Wasm to JS.
1 parent 51422ed commit ce07134

File tree

5 files changed

+26
-0
lines changed

5 files changed

+26
-0
lines changed

examples/basic/.perseus/server/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ fn get_props(is_standalone: bool) -> ServerProps<impl MutableStore, impl Transla
116116
js_bundle: "dist/pkg/perseus_engine.js".to_string(),
117117
// Our crate has the same name, so this will be predictable
118118
wasm_bundle: "dist/pkg/perseus_engine_bg.wasm".to_string(),
119+
// This probably won't exist, but on the off chance that the user needs to support older browsers, we'll provide it anyway
120+
wasm_js_bundle: "dist/pkg/perseus_engine_bg.wasm.js".to_string(),
119121
// It's a nightmare to get the templates map to take plugins, so we use a self-contained version
120122
// TODO reduce allocations here
121123
templates_map: get_templates_map_atomic_contained(),

packages/perseus-actix-web/src/configurer.rs

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ async fn js_bundle(opts: web::Data<Rc<ServerOptions>>) -> std::io::Result<NamedF
2020
async fn wasm_bundle(opts: web::Data<Rc<ServerOptions>>) -> std::io::Result<NamedFile> {
2121
NamedFile::open(&opts.wasm_bundle)
2222
}
23+
async fn wasm_js_bundle(opts: web::Data<Rc<ServerOptions>>) -> std::io::Result<NamedFile> {
24+
NamedFile::open(&opts.wasm_js_bundle)
25+
}
2326
async fn static_alias(
2427
opts: web::Data<Rc<ServerOptions>>,
2528
req: HttpRequest,
@@ -79,6 +82,7 @@ pub async fn configurer<M: MutableStore + 'static, T: TranslationsManager + 'sta
7982
// This contains everything in the spirit of a pseudo-SPA
8083
.route("/.perseus/bundle.js", web::get().to(js_bundle))
8184
.route("/.perseus/bundle.wasm", web::get().to(wasm_bundle))
85+
.route("/.perseus/bundle.wasm.js", web::get().to(wasm_js_bundle))
8286
// This allows getting the static HTML/JSON of a page
8387
// We stream both together in a single JSON object so SSR works (otherwise we'd have request IDs and weird caching...)
8488
// A request to this should also provide the template name (routing should only be done once on the client) as a query parameter

packages/perseus-warp/src/perseus_routes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ pub async fn perseus_routes<M: MutableStore + 'static, T: TranslationsManager +
4848
let wasm_bundle = warp::path!(".perseus" / "bundle.wasm")
4949
.and(warp::path::end())
5050
.and(warp::fs::file(opts.wasm_bundle.clone()));
51+
let wasm_js_bundle = warp::path!(".perseus" / "bundle.wasm.js")
52+
.and(warp::path::end())
53+
.and(warp::fs::file(opts.wasm_js_bundle.clone()));
5154
// Handle JS interop snippets (which need to be served as separate files)
5255
let snippets = warp::path!(".perseus" / "snippets").and(warp::fs::dir(opts.snippets.clone()));
5356
// Handle static content in the user-set directories (this will all be under `/.perseus/static`)
@@ -121,6 +124,7 @@ pub async fn perseus_routes<M: MutableStore + 'static, T: TranslationsManager +
121124
// Now put all those routes together in the final thing (the user will add this to an existing Warp server)
122125
js_bundle
123126
.or(wasm_bundle)
127+
.or(wasm_js_bundle)
124128
.or(snippets)
125129
.or(static_dir)
126130
.or(static_aliases)

packages/perseus/src/server/html_shell.rs

+14
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ impl<'a> HtmlShell<'a> {
6161
}
6262

6363
// Define the script that will load the Wasm bundle (inlined to avoid unnecessary extra requests)
64+
// If we're using the `wasm2js` feature, this will try to load a JS version instead (expected to be at `/.perseus/bundle.wasm.js`)
65+
#[cfg(not(feature = "wasm2js"))]
6466
let load_wasm_bundle = format!(
6567
r#"
6668
import init, {{ run }} from "{path_prefix}/.perseus/bundle.js";
@@ -72,6 +74,18 @@ impl<'a> HtmlShell<'a> {
7274
"#,
7375
path_prefix = path_prefix
7476
);
77+
#[cfg(feature = "wasm2js")]
78+
let load_wasm_bundle = format!(
79+
r#"
80+
import init, {{ run }} from "{path_prefix}/.perseus/bundle.js";
81+
async function main() {{
82+
await init("{path_prefix}/.perseus/bundle.wasm.js");
83+
run();
84+
}}
85+
main();
86+
"#,
87+
path_prefix = path_prefix
88+
);
7589
scripts_before_boundary.push(load_wasm_bundle.into());
7690

7791
// Add in the `<base>` element at the very top so that it applies to everything in the HTML shell

packages/perseus/src/server/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub struct ServerOptions {
1515
pub js_bundle: String,
1616
/// The location on the filesystem of your Wasm bundle.
1717
pub wasm_bundle: String,
18+
/// The location on the filesystem of your JS bundle converted from your Wasm bundle. This isn't required, and if you haven't generated this, you should provide a fake path.
19+
pub wasm_js_bundle: String,
1820
/// The location on the filesystem of your `index.html` file.
1921
// TODO Should this actually be a raw string of HTML so plugins can inject efficiently?
2022
pub index: String,

0 commit comments

Comments
 (0)