feat: router-based wasm bundle splitting (#3683)

* feat: wasm-split base implementation

* kinda sorta works with the cli

* okay great it actually works

* fix: cache busting for chunks

* cleaned up version

* it works with the router

* wip: migrate to a faster linear solution using id remapping

* add a good harness

* it works completely on the docsite

* the super tight build works too

* make parallelizable

* works on the docsite but not the harness

* light cleanups, fix for both harness and docsite

* make codegen smaller by extract some shared functions to prevent monos

* chunking works, but tbd on tuning heuristics

* extract used module

* wip: cleaning up module

* wip: much better understanding of how imports work

* fix the call graph

* working again...

* wip: thinking about ifuncs

* ifunc approach works

* yes the ifunc approach works!!

* it all works completely even with chunks

* small cleanups

* comments

* actually locate all of the symbols

* clean up final implementation

* clean up tomls, revert some mono changs

* clean up, add some more comments / docs in places

* hoist more packages

* clean up impl a bit more

* clean cli

* move harness to playwright

* update playwright

* extract codgen

* add lazy to components

* Add docs to split loader

* clippy

* typos

* clippy, don't generate splits if not on wasm

* whoops, const

* Typos and docs

* enable optimizations in ci

* add optimizations to ci

* add wasm-split router feature

* parallel playwright?

* fix no case check

* disable pre-compress... think that might be the issue

* better logging, no default pre-compress, caching of shared symbols
* Fix: compressing assets

* fix non-interactive logging for serve

* cache playwright even on failure, use the cli with optimizations

* fix prebuild

* fix playwright webserver
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-02-13 18:54:38 -08:00
1 parent 14eb7597df
commit bdeedc13eb
59 files changed
+4249 -299

No files matched your search

+1 -74
View File
@@ -475,82 +475,9 @@ impl RouteEnum {
site_map,
};
// If we're on the web, only the URL history is preserved between navigation. We need to warn the user that the segment is not present in the URL.
if cfg!(feature = "web") {
for variant in &data.variants {
for field in &variant.fields {
if !myself.field_present_in_url(field.ident.as_ref().unwrap()) {
return Err(syn::Error::new_spanned(
field.ident.as_ref().unwrap(),
format!("The `{}` field must be present in the url for the web history. You can include the field in the url by using the `#[route(\"/:{}\")]` attribute on the enum variant.", field.ident.as_ref().unwrap(), field.ident.as_ref().unwrap()),
));
}
}
}
}
Ok(myself)
}
fn field_present_in_url(&self, field: &Ident) -> bool {
let mut from_route = false;
for nest in &self.nests {
if nest.dynamic_segments_names().any(|i| &i == field) {
from_route = true
}
}
for route in &self.endpoints {
match route {
RouteEndpoint::Route(route) => match &route.ty {
RouteType::Child(child) => {
if let Some(child) = child.ident.as_ref() {
if child == "child" {
from_route = true
}
}
}
RouteType::Leaf { .. } => {
for segment in &route.segments {
if segment.name().as_ref() == Some(field) {
from_route = true
}
}
if let Some(query) = &route.query {
if query.contains_ident(field) {
from_route = true
}
}
if let Some(hash) = &route.hash {
if hash.contains_ident(field) {
from_route = true
}
}
}
},
RouteEndpoint::Redirect(redirect) => {
for segment in &redirect.segments {
if segment.name().as_ref() == Some(field) {
from_route = true
}
}
if let Some(query) = &redirect.query {
if query.contains_ident(field) {
from_route = true
}
}
if let Some(hash) = &redirect.hash {
if hash.contains_ident(field) {
from_route = true
}
}
}
}
}
from_route
}
fn impl_display(&self) -> TokenStream2 {
let mut display_match = Vec::new();
@@ -737,7 +664,7 @@ impl RouteEnum {
// Collect all routes matches
for route in &self.endpoints {
if let RouteEndpoint::Route(route) = route {
matches.push(route.routable_match(&self.layouts, &self.nests));
matches.push(route.routable_match(&self.layouts, &self.nests, name));
}
}