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

Rocket + Rust + React + Routing + SPA? #1183

Closed
Jasperav opened this issue Dec 9, 2019 · 6 comments
Closed

Rocket + Rust + React + Routing + SPA? #1183

Jasperav opened this issue Dec 9, 2019 · 6 comments
Labels
duplicate This issue or pull request already exists question A question (converts to discussion)

Comments

@Jasperav
Copy link

Jasperav commented Dec 9, 2019

I am experimenting with Rust, React and Rocket. This is eventually what I want:

  • Rust to be the server code.
  • React doing the frontend. I think I want to do the routing inside React, not server side (but not sure about it, because I do not know which one is better).
  • Some glue between them so I can make Rest calls from React to Rust

For the glue I have chosen Rocket. One thing that my brain is missing, is how I can deploy Rust, React and Rocket together, so not one by one (I made a post on Reddit because I didn't understand how it can/should be done: https://www.reddit.com/r/rust/comments/e7zg3g/rust_as_server_react_as_frontend_how_to_deploy/).

I searched some time on google and came across some tutorials which quality isn't that great. But currently I have this project: https://github.com/Jasperav/rustreactrocket which can do the trick. It deploys React, Rust and Rocket all in once (after npm install & build)!

However, the routing is done in Rust/Rocket. I don't understand how I can make it work through react routing and components. I want to use the react routing dom dependency (https://reacttraining.com/react-router/web/guides/quick-start). This enables SPA and adds a suffix to the URL when creating a route.

That is where my problem is. When the suffix will be inserted inside the URL, Rocket tells me it doesn't know how to handle it. I can use a wildcard matcher in the get macro (#[get("/<file..>")]), but what do I need to return from that function? React is doing my routes already.

Ofcourse I can let Rocket do my routing, but is it still SPA? From what I am seeing is that it returns a whole html file (or some strings). That's not what I want. I have looked quickly in the docs but I haven't found out one with React.

@Jasperav Jasperav changed the title Rocket + Rust + SPA? Rocket + Rust + React + Routing + SPA? Dec 9, 2019
@olback
Copy link
Contributor

olback commented Dec 9, 2019

To make SPAs work, you need to respond with the index.html file on all GET requests that are not a part of your API.
Example: GET /contacts and GET /thispagedoesnotexistlalalalala should return the same content. Your React application then reads the path and determines what to do. If it is /contacts then it'll show the contacts and if the path isn't defined in React, just show a 404 page.

To get/send data to the server, one could set up endpoints like GET /api/contacts and POST /api/contacts. But make sure to not make any pages in React called /api/<whatever> because they will interfere with the API.

@jebrosen
Copy link
Collaborator

jebrosen commented Dec 9, 2019

The best documentation I could find for this in the past is https://create-react-app.dev/docs/deployment#serving-apps-with-client-side-routing. Notably, I didn't see anything like it mentioned in the tutorial you linked. It would probably be worth making an issue/PR for that tutorial if there isn't already, because I expect it to be a common source of confusion.

This has been asnwered before (#723 (comment)) so I'll close this as a duplicate - but feel free to ask further questions!

@jebrosen jebrosen closed this as completed Dec 9, 2019
@jebrosen jebrosen added duplicate This issue or pull request already exists question A question (converts to discussion) labels Dec 9, 2019
@ghimiresdp
Copy link

ghimiresdp commented Jun 22, 2021

Hello, I think I've found a way to solve problems with SPA and client-side routing.
We can simply add the static_file route with rank = 1 and fallback_url with rank = 2.

In the fallback_url, we can simply return the template that renders the react app.

additionally, all assets including css, js, service workers, and manifest files should be added to the static folder

#[macro_use]
extern crate rocket;

use rocket::fs::{FileServer, relative, NamedFile};
use rocket::response::{content, status};
use std::path::{PathBuf, Path};

mod apps;


#[get("/<_..>", rank = 2)]
pub(crate) fn fallback_url() -> &'static str {
    "Hey, this is the fallback url"
}


#[get("/<file..>", rank=1)]
async fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("static/").join(file)).await.ok()
}


#[launch]
fn rocket() -> rocket::Rocket<rocket::Build> {
    rocket::build()
        .attach(apps::device::stage())
        // .mount("/static", FileServer::from(relative!("/static")))
        .mount("/static", routes![files,])
        .mount("/", routes![fallback_url,])
}

@SergioBenitez
Copy link
Member

@ghimiresdp This is just FileServer::from(relative!("/static")).rank(1).

@ghimiresdp
Copy link

@ghimiresdp This is just FileServer::from(relative!("/static")).rank(1).

Thanks, @SergioBenitez. I was unaware of this. Worked perfectly!! 🚀 🚀.

@bobrossrtx
Copy link

Hey @ghimiresdp, your solution worked out amazingly for me, thanks for posting that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists question A question (converts to discussion)
Projects
None yet
Development

No branches or pull requests

6 participants