Browse Source

Fix base path (#4276)

* fix base path

* remove log

* fix clippy
Evan Almloff 1 week ago
parent
commit
10a63d07e2

+ 11 - 15
packages/cli/src/build/request.rs

@@ -3841,7 +3841,7 @@ impl BuildRequest {
         };
 
         // Inject any resources from the config into the html
-        self.inject_resources(assets, &mut html)?;
+        self.inject_resources(assets, wasm_path, &mut html)?;
 
         // Inject loading scripts if they are not already present
         self.inject_loading_scripts(&mut html);
@@ -3860,7 +3860,12 @@ impl BuildRequest {
     }
 
     // Inject any resources from the config into the html
-    fn inject_resources(&self, assets: &AssetManifest, html: &mut String) -> Result<()> {
+    fn inject_resources(
+        &self,
+        assets: &AssetManifest,
+        wasm_path: &str,
+        html: &mut String,
+    ) -> Result<()> {
         use std::fmt::Write;
 
         // Collect all resources into a list of styles and scripts
@@ -3930,19 +3935,10 @@ impl BuildRequest {
         }
 
         // Manually inject the wasm file for preloading. WASM currently doesn't support preloading in the manganis asset system
-        let wasm_source_path = self.wasm_bindgen_wasm_output_file();
-        if let Some(wasm_assets) = assets.get_assets_for_source(&wasm_source_path) {
-            let wasm_path = wasm_assets
-                .iter()
-                .next()
-                .expect("There should be exactly one optimized wasm asset");
-            let wasm_path = wasm_path.bundled_path();
-            head_resources.push_str(&format!(
-                    "<link rel=\"preload\" as=\"fetch\" type=\"application/wasm\" href=\"/{{base_path}}/assets/{wasm_path}\" crossorigin>"
-                ));
-
-            Self::replace_or_insert_before("{style_include}", "</head", &head_resources, html);
-        }
+        head_resources.push_str(&format!(
+            "<link rel=\"preload\" as=\"fetch\" type=\"application/wasm\" href=\"/{{base_path}}/assets/{wasm_path}\" crossorigin>"
+        ));
+        Self::replace_or_insert_before("{style_include}", "</head", &head_resources, html);
 
         Ok(())
     }

+ 5 - 2
packages/router/src/components/link.rs

@@ -163,8 +163,11 @@ pub fn Link(props: LinkProps) -> Element {
         NavigationTarget::Internal(url) => url.clone(),
         NavigationTarget::External(route) => route.clone(),
     };
-    // Add the history's prefix to the href for use in the rsx
-    let full_href = router.prefix().unwrap_or_default() + &href;
+    // Add the history's prefix to internal hrefs for use in the rsx
+    let full_href = match &to {
+        NavigationTarget::Internal(url) => router.prefix().unwrap_or_default() + url,
+        NavigationTarget::External(route) => route.clone(),
+    };
 
     let mut class_ = String::new();
     if let Some(c) = class {

+ 22 - 1
packages/router/tests/via_ssr/link.rs

@@ -8,10 +8,15 @@ fn prepare<R: Routable>() -> String {
 }
 
 fn prepare_at<R: Routable>(at: impl ToString) -> String {
+    prepare_at_with_base_path::<R>(at, "")
+}
+
+fn prepare_at_with_base_path<R: Routable>(at: impl ToString, base_path: impl ToString) -> String {
     let mut vdom = VirtualDom::new_with_props(
         App,
         AppProps::<R> {
             at: at.to_string(),
+            base_path: base_path.to_string(),
             phantom: std::marker::PhantomData,
         },
     );
@@ -21,6 +26,7 @@ fn prepare_at<R: Routable>(at: impl ToString) -> String {
     #[derive(Props)]
     struct AppProps<R: Routable> {
         at: String,
+        base_path: String,
         phantom: std::marker::PhantomData<R>,
     }
 
@@ -28,6 +34,7 @@ fn prepare_at<R: Routable>(at: impl ToString) -> String {
         fn clone(&self) -> Self {
             Self {
                 at: self.at.clone(),
+                base_path: self.base_path.clone(),
                 phantom: std::marker::PhantomData,
             }
         }
@@ -44,7 +51,7 @@ fn prepare_at<R: Routable>(at: impl ToString) -> String {
         rsx! {
             h1 { "App" }
             HistoryProvider {
-                history:  move |_| Rc::new(MemoryHistory::with_initial_path(props.at.clone())) as Rc<dyn History>,
+                history:  move |_| Rc::new(MemoryHistory::with_initial_path(props.at.clone()).with_prefix(props.base_path.clone())) as Rc<dyn History>,
                 Router::<R> {}
             }
         }
@@ -79,6 +86,15 @@ fn href_internal() {
     let expected = format!("<h1>App</h1><a {href}>Link</a>", href = r#"href="/test""#,);
 
     assert_eq!(prepare::<Route>(), expected);
+
+    // The base path should be added to the front of internal links
+    let base_path = "/deeply/nested/path";
+    let expected = format!(
+        "<h1>App</h1><a {href}>Link</a>",
+        href = r#"href="/deeply/nested/path/test""#,
+    );
+
+    assert_eq!(prepare_at_with_base_path::<Route>("/", base_path), expected);
 }
 
 #[test]
@@ -113,6 +129,11 @@ fn href_external() {
     );
 
     assert_eq!(prepare::<Route>(), expected);
+    // The base path should not effect external links
+    assert_eq!(
+        prepare_at_with_base_path::<Route>("/", "/deeply/nested/path"),
+        expected
+    );
 }
 
 #[test]