3 ms·
I'm confused here. What defines the "webserver" versus the "the SPA"? The way I've implemented SPAs is to run nginx. All my JS and CSS is in /static/ and ser
by Sohcahtoa82 3y ago
I'm confused here. What defines the "webserver" versus the "the SPA"?
The way I've implemented SPAs is to run nginx. All my JS and CSS is in /static/ and served up by nginx. "/" returns an index.html. "/api/*" gets forwarded to a back end of some sort, usually Python's Bottle because it's lightweight and simple to use. If the route doesn't exist, Bottle returns a 404. If I have an endpoint that includes an ID of some sort in the URL, like /api/getobject/12345, but you request an object that doesn't exist, then I still return a 404.
How are you implementing SPAs in a way that you can't return a 404?
- __jonas 3y ago> How are you implementing SPAs in a way that you can't return a 404? Not specifically me, but a lot of SPAs have their own routing. So you would go to https://my-spa.com/user/39820002/post/39811155 When you hit that route, the webserver returns /index.html with the JS bundle, the JS runs and matches the user ID and post ID from the URL and then maybe makes some API requests to fetch content of whatever, I mean the SPA doesn't have to be backed by an API anyways, could be purely static but still use a router. In the React world, react-router is (was) pretty popular: https://github.com/remix-run/react-router https://github.com/remix-run/react-router That's a library that works exactly that way, relying on every route being passed to the JS bundle for handling, so the webserver needs to be configured to never return 404 and just return the index.html for every route, here is an example of what this looks like from the docs of Caddy, another popular webserver with a pretty easy to understand config format: https://caddyserver.com/docs/caddyfile/patterns#single-page-apps-spas https://caddyserver.com/docs/caddyfile/patterns#single-page-... It's a "Single Page App", you may have many pages being rendered by this app, but it's a single html page that is responsible for doing this. Now – SPAs are not as popular as they used to be, and there is an argument to be made that they aren't the best solution in most cases with what's available now, regardless of that they do exist and this appears to be a web server specifically for them so having the option handle SPA routing as it's commonly done, does make sense. And I think for stuff like internal management apps, admin panels etc. SPAs with their own routing are still a decent solution.
- fragmede 3y ago> they aren't the best solution in most cases with what's available now What's available now that superceds them?
- __jonas 3y agoWell I suppose that's subjective, I probably put my bias in there but I would say: For mostly static or content driven sites, there are really nice static site generators now. I find Astro[1] really pleasant to use, offering the convenience of SPA framework tooling, while allowing me to build sites that run without the need for any client-side JavaScript but the option to into client-side JS as needed. But also NextJS has a similar static export function, and of course there are many other great SSGs outside the JavaScript world like Hugo. For dynamic web applications like the example from my comment I would just do server side rendering using your language and framework of choice, Phoenix, Rails, Next, Django, whatever. In both cases the issue with 404 routes is avoided. [1] https://astro.build/ https://astro.build/
- shkkmo 3y ago> What's available now that superceds them? The mostly same stuff as before, but slightly better. SPAs were a fad that got very popular, but they were generally a poor solution in most cases and as the fad faded, they stopped being as overused. One of the reasons why SPAs are bad solution is because they interfere with how the web works in significant ways (browser history, caching, server response statuses) and solving those issues without degrading user experience is hard. When a SPA was actually useful, it was worth spending the time to solve those issues. The overuse of SPAs means that most of them did not take the time to solve these issues properly so most SPAs sucked (and still do). This is why I don't understand releasing a SPA server in 2024 that doesn't even try to provide tools to solve those issues.
- Sohcahtoa82 3y agoAhhh...I see what you're saying. So like, if you're on my-spa.com, and click a link to a post, the JS loads the post and updates the URL, but doesn't perform a full page load. So while you might be on https://my-spa.com/user/39820002/post/39811155 https://my-spa.com/user/39820002/post/39811155, your browser likely never actually sent a GET request to /user/39820002/post/39811155. But this creates the issue that if you manually navigate to that URL, your browser WILL send a request for it. In that case, yeah, I think the correct thing to do is to return the 200 OK with your usual index.html. When the JS makes the API requests, those requests should return a 404, and the JS will then render a page that says "That post doesn't exist" or something. But in the case of a request that couldn't possibly exist, like a GET request for /etc/passwd, they should still be 404s. Any router should be able to do that. EDIT: I think a better way to do this hold thing is to make the resource an anchor tag in the URL. Instead of https://my-spa.com/user/39820002/post/39811155 https://my-spa.com/user/39820002/post/39811155, make it https://my-spa.com/#user/39820002/post/39811155 https://my-spa.com/#user/39820002/post/39811155
- MrJohz 3y agoA lot of SPAs do some level of client-side routing, so that if you open up the SPA and click on a link, rather than directing you to a different page, the app instead updates the URL with Javascript and renders the content of the new page. There are various benefits and drawbacks to this approach, but it's quite common, and you can find tools like React Router that are designed to support this client-side routing. The problem is that when you only serve your app from `/`, and then the user navigates via the app to `/user/123`, the url gets updated, but if the user tries to reload the page, they'll end up on a 404 page because you're not serving the app from `/user/123`. There's a few ways to solve this, each again with tradeoffs, but one way is to have the server return 200 and the contents of the main page any time that the user requests an unknown route, under the assumption that the user is probably trying to navigate to a dynamic route handled by the frontend.