How front-end router works in a MVC Framework? - javascript

I cannot fully understand how a single page application can do routing by itself.
Maybe you can see the example here.
If you click on those links (below the visited, purple color link), the url and the page will be change without reloading. But how to achieve this if the front-end is deployed in a MVC framework?
Isn't that if you visit a url on MVC, it'll will look for the corresponding controller for that url? If that happen, of course the page will be reloaded isn't it? If it using HTML5 History, how can when I revisit the url, the page display the changed state?
Can someone explain how to achieve this with React app that deployed on a MVC framework like Rails? Thank you

I'm more familiar with Angular, but all the Single Page Applications (SPA) are based on the the same model. You have three layers:
the Rails MVC routing system with its routes and controllers
the React SPA routing system (that also has its own
routes and controller system)
the React event handling system that, as a javascript framework, among other things, catches mouse clicks in the web application
In your reactrails example page, the root of your web site (/) is handled by Rails, and every other pages (/*) are intercepted and handled by the react routing system.
So basically, if you have a rails ApplicationController you could have a config/routes.rb like this:
# routes.rb
root 'application#main'
# catch every routes and serve only the Application.main action
match '*path', to: 'application#main'
# application_controller.rb
class ApplicationController
def main
end
end
This will redirect every urls coming to Rails (/this/is/an/example, /that/one/is/not/an/example...) to the React router. (Note that you could also have other routes such as /api/gimme/my/damn/json/data that will resolve to other controllers and send back JSON, xml, html or any kind of data)
Then, in your html page, React intercepts every clicks, on links or buttons, and compare them to its own routes.
If a route match, it will display the correct page via its templating system, (usually loading it by Ajax or read it from its cache), and you won't see any page reload. You could say that react act has a client-side server.
If you call a url such as /i/like/flowers, the route will be first processed by rails (/*), that will send you an html file located at the / route, containing your SPA app, that will kicks in, analyse the route itself, and show you the correct content from its own templating system.
So to sum up, you have:
GET /my/super/react/url
//=> Rails serves `main.html` that includes `react-router`
Once main.html is loaded, react-router looks at its routes components and serve the right template if route exists (/my/super/react/url).
You could find more examples in the react-router documentation
This is the basic scenario, and I'm sure others will complete anything I didn't cover, and add react specific samples!

Related

Dynamic URL routes for Static site in Vue

I have a static site, there is no way to add in re-writes via htaccess or similar which is how would normally approach this functionality. We're running the site with Vue, on top of static .html templates eg
\example\index.html
So I can visit www.mywebsite.com/example/ and it'll load the page, and run Vue, when I want a subpage, based on this layout, I currently have to create
\example\subpage\index.html
Again this works great www.mywebsite.com/example/subpage/, but what I'm wanting is to pull data in via an API feed, and be able to have dynamic URLs
\example\subpage\any-page-name-here
The closest I've found is to use # so
\example\subpage#any-page-name-here
Which allows Vue to pick up the data after the # and query the API with that.
Any help would be greatly appreciated, there's no work around for the limitations of the hosting, so I need a Vue/JS/HTML only soltion.
Thanks!
As you cannot change the web server configuration, the only possibilities are the hashtag option or the query string e.g
example.com/site/?dynamic-data
The reason is the web server decides what to do with the request in the first instance, and without any configuration it will simply load a page if it exists or show a 404. This happens before your Vue app is invoked.

Advantage and Implementation of Angular Universal?

Ancient website:
User navigates to url via bar or href, server call is made for that particular page
The page is returned (either static html or html rendered on server by ASP.NET
MVC, etc
EVERY page reloads everything, slow, reason to go to SPA
Angular 2 SPA:
User navigates to url via bar or router
A server call is made for the component's html/javascript
ONLY the stuff within the router outlet is loaded, not the navbar, etc (main advantage of SPAs)
HOWEVER, html is not actually received from server as is, Angular 2 code/markup is - then this markup is processed on the CLIENT before it can be displayed as plain HTML, which the browser can understand - SLOW? Enter Angular Universal?
Angular Universal:
First time users of your application will instantly see a server rendered view which greatly improves perceived performance and the overall user experience.
So, in short:
User navigates to url via search bar or router
Instead of returning Angular components, Angular Universal actually turns those components into html AND then sends them to the client. This is the ONLY advantage.
TLDR:
Is my understanding of what Angular Universal does correct? (last bullet point above).
And most importantly, assuming I understand what it does, how does it achieve this? My understanding is that IIS or whatever just returns requested resources, so how does Angular Universal pre-process them (edit: I would basically running something akin to an API that returns processed html)?
This HAS to mean that the server makes all the initial API calls needed to display the initial view, for example from route resolves...correct?
Edit: Let's focus on this approach to narrow down the question:
The second approach is to dynamically re-render your application on a web server for each request. There are still several caching options available with this approach to improve scalability and performance, but you would be running your application code within the context of Angular Universal for each request.
The approach here:
The first option is to pre-render your application which means that you would use one of the Universal build tools (i.e. gulp, grunt, broccoli, webpack, etc.) to generate static HTML for all your routes at build time. Then you could deploy that static HTML to a CDN.
is beyond me. Seeing how there is a bunch of dynamic content there, yet we preload static html.

Making views work with templates generated on the server with AngularJS & Laravel

I am looking to create an application with AngularJS that also has pages rendered on the server side with PHP/Laravel.
Essentially, I want to be able to render a static version of a view on the server side, but have the Javascript views start kicking in as soon as the page is rendered.
The idea being that when a user goes to an internal page for the first time, all of the content is rendered ahead of time on the server, yet the one page application will continue to work as soon as the page is loaded in the browser.
The backend of the application is currently written in Laravel, so I would feel comfortable writing the view logic in PHP.
What would be the best direction to go for this? I really want to avoid passing the pages to a third party service such as prerender.io or first rendering the page in phantomjs.
Essentially: having Javascript disabled on a web browser will not make any one page AngularJS app run. This is why I want to find a way to render the full page on the server, and once the page is loaded in the browser, either re-render the page (if that is the way it must be done) with my Angular application or somehow bind all of the data with the static views with my AngularJS controllers and models.

Use React and Express

I'm using Express framework on NodeJS (hosted by Heroku) to create my web site. I'm also using the React framework to create my components.
I have several HTML files with divs inside and React components which can be rendered in those divs.
When a user chooses a route (e.g. /movies) I want to be able to associate one HTML file with a component and return it back to the user. I already looked for a solution, but all of them talk about server-side rendering and sending back HTML files.
Is there another solution?
Check out react router you don't have to use server side rendering, you just need to give a react component that you want to return when a route is requested.
The standard way to do this now is to build a Single-Page applications and redirect all requests to /, and the front end routing will handle the required page to load.

Backbone routers and compatibility with web server controller

How do I get compatibility between my web server's controllers and Backbone router?
I have it set it so when a user clicks on a link, a view is rendered, and the URL looks like this: /test/1, which is what I want. The problem comes in when the user tries to access test/1 by entering it into the address bar. My backend has controllers that is in charge of routing URLS.
How would I get it so it uses the Backbone routes rather than the backend routes?
One way that works is when I access the url #test/1. It is bookmarkable and can be entered into the address bar. The problem is that backbone stripes the # on load.
So, I see two solutions to my problem:
Get the backend controllers to interact with Backbone routes
Make it so the #'s aren't removed when they are entered inside of the address bar.
Which of the above solutions is recommended. And, how would I implement them. The second solution seems easier, but how would I make it so backbone doesn't strip the URLs of the hashes?
From what I understand when the user navigates to the root page and then test/1 via a link the logic is handled by backbone and a view is rendered. But when the user navigates directly to test/1 this is not handled correctly.
To handle this you need to setup a route on your server that points any URLs handled by backbone to the root page. The logic for this depends on your server which you have not specified. To do something like this in ASP you might setup a route like this:
RouteTable.Routes.MapWebPageRoute("test/{id}", "~/Default.cshtml", new {}, new { id = "\\d+" });
This would cause a URL such as test/1 to be handled by the default page which be the same handler as if the user navigated to /. Once the page has loaded on the client the Backbone router would fire for the test/1 route.
Well, really, there are many reasons why you want the URL to include the # all the time. It makes lots of things work better. For example, the correct controller is automatically selected by the web server and the correct route is automatically provided to Backbone whether you manually type in the URL, use a bookmark, use a link from another site, or use the back and forward buttons on the web browser. So choice 2 is definitely the one you want. This is also the standard behavior of Backbone.
So my question is "How did you get backbone to stop using the # in the first place?"
Edit: Thanks to Chris Herring for pointing us to a great article explaining why # is bad. With that, I will leave it as an exercise to the reader about which kind of pain they want to endure. I think # is still the way to go so long as all the Backbone route is changing is how the information on the page is displayed and not what information is on the page. If a web crawler that does not support JavaScript can scrape all the same information regardless of what comes after the #, then I still don't see a problem with it.

Categories

Resources