Express and Backbone Routing with pushState - backbone.js

I am new to both of these technologies and am wondering how is the best way to configure my app. I want to have no hastags and just use pushState. Also from what I read its best to have a mix between rendering server side and client side but I am not sure how to set this up. I have figured out how to do it one or the other but not together.
As of right now here is where I am at:
Express routes
app.get('/', site.index);
app.get('/product/:id', wiki.show);
Again this works fine without using pushState but now how do I combine the two together?

To create a hybrid client/server app, you want both the client and server to be able to render every view. When a user visits your site, the server render the view and sends the html to the user. At this point, the client-side app loads and any relative links should be intercepted and replaced with backbone navigation.
$(document).on('click', 'a:not([data-bypass])', function(e){
href = $(this).prop('href')
root = location.protocol+'//'+location.host+'/'
if (root===href.slice(0,root.length)){
e.preventDefault();
Backbone.history.navigate(href.slice(root.length), true);
}
});
This line of code, once the backbone app has started, will catch all anchor tags without a data-bypass attribute and fire route functions in your client application instead of sending requests for that page to the server. Add a data-bypass attribute to create a link that will not fire a route function.

Related

How to route for a react-router app using express?

So I have a backend running in expressjs and I have multiple routes on it. Now I just followed this tutorial to set up a RESTful api on express. Now I want to switch to full react on the frontend, so that I will have an api running in the backend to get things from the database and am thinking using fetch from react to get that data. I saw many people say that is the best way to do it. But now there is an issue, I am not sure how to route for this. I have react-router setup so I am assuming I would use that. But how can I serve these files to the client side? How can I make sure every route except /api routes just serve my js files? Like I have a built folder already with an index.html and main<hash>.js. I am running them easily but how can I intergrate them with express? I was not able to find any answers to this. How can I route for a reactjs app to be served using expressjs? and also I saw a tutorial telling me to use a * route but that means even my api routes will only point to that.
There are three ways basically to render an application.
One is Server Side Rendering, the other one is Client Side rendering and the third one is Isomorphic rendering.
So if you are defining your routes in Nodejs and navigating the application through those routes than it will be entirely server side rendering.
I saw a tutorial telling me to use a * route but that means even my
api routes will only point to that. ? How can I make sure every route
except /api routes just serve my js files?
Regarding this what you can do is
server.get('/api', (req, res, next) => {
//You can handle the request here
})
server.get('*', (req, res, next) => {
//You can handle the request here
})
You can define your route in this order.So by this way any call to the '/api' will be handled by the first route and all the other request will be handled by the second route.
Now I want to switch to full react on the frontend, so that I will
have an api running in the backend to get things from the database and
am thinking using fetch from react to get that data
Here you dont need this.It will be an client side rendering completely
server.get('*', (req, res, next) => {
//You can handle the request here
})
For this you can create an react app from scratch or use some boilerplate (https://github.com/facebookincubator/create-react-app).
There you can define all the routing and simply call the url http://localhost/api/xxxx and get the data and you can use this data in the frontend.In this case there will be a Nodejs Server which will be serving the frontend and the expressjs server will he hosting the 'api' service to get data from.
I have react-router setup so I am assuming I would use that. But how
can I serve these files to the client side?`
How can I route for a reactjs app to be served using expressjs?
The Reactjs app when compiled is a combination of static files comprising mainly of html, css, javascript. If you want your app to be served by your express.js server then you need to use isomorphic rendering. It is by far the best approach for rendering application as it is good for SEO and initial fast page load. It comes at the cost of a complicated setup. In this case, whenever the page refreshes or the first request comes, express will serve the first page (index.html) and index.html will contain the required static(bundled) js and css files for client side rendering. The first rendering will be done by the express server and the subsequent rendering will be done by browser itself.

Single Page App on React.js and ZF2. Is it possible?

I'm thinking how to implement a SPA on Zend framework 2 using Reactjs? Haven't seen any tutorial that might help me. So, I was asking if this is possible. How would zf2 will handle the routes?
The routes are handled on the client side (by pushing URLs into browser's history so you can also use browser's back button for navigation)
Simply put, changing a route will not load a whole page from the server.
The server does not even know that your JS app is changing the URL in the browser (imagine you write by hand http://example.com#test while you were already on example.com; that #test thing is a fragment URL and it will never be sent to a server)
Instead, the JS application will respond to (once again, client-side) route changes by rendering a different page or section, and making some ajax calls to the server to fetch or update data.
Now let's see what the server should do:
send the first page (the "single-page") and the assets (CSS, JS) on
the first load
respond to app-originated AJAX API calls once the page is loaded and
the JS app has been started
That's why they call them "single page apps", because they do much of the logic and the presentation in the browser (DOM rendering, routes), and the server merely acts as a data layer, or a backend if you like this word better.

How to render templates with express?

My current setup is as follows:
Starting the server and going to localhost takes me to home.ejs as stated here (in my front end routing):
However, when I go to localhost:3000/posts, the posts template is infact not being injected into my index file (where my ui-view is). Ive been following the mean stack guide from thinkster, but have been making a few changes (not using inline templates)
My question is, how do I setup my routing such that localhost:3000/posts will actually take me to the posts page?
You are dealing with two types of routing, client side and server side. Client side is located in your app.config function in your angular code. That function should be calling html files, which are located in your public directory. These files are not rendered server side via express and they wouldn't not be able to read the ejs format.
Typically with MEAN stack applications, you just render your index file when the user logs in, and from there the Angular router takes over with html files and you handle your routing from there. If you don't want Angular routing, you have to set up your index.js file to render pages as they are called with res.render('posts')
You can change your posts.ejs file into an html file, and just call it via Angular when the user navigates to localhost/#/posts (depending on your version and configuration of Angular).
Your Express server side routing will handle your API calls as you have defined in index.js. In order to call those APIs, you will make GET or POST requests via Angular's $http method, through a service or factory.
Hope that helps, if not, let me know and I can elaborate or provide examples.
To solve this, I used Eric Hartmanns solution. By changing posts.ejs to posts.html, and letting the angular router take over on client side, the page was being rendered. However, when typing in localhost:3000/posts in the address bar, the page wasnt being rendered and the server was being hit for some reason. To get around that I simply made a new get route in express and re-rendered index whenever that route was hit like so:
router.get('/', function(req, res) {
res.render('index');
});

How to handle non-root URLs in a singlepage app?

I try to make a single page app with Rails 3.2 and Backbone.js with pushState option but faced with something that I do not understand.
If I load the root URL of the app (/), everything goes right: Rails return an HTML-layout with JS which bootstraps Backbone which makes some XHRs for JSON-entities and renders the content.
But if I start using app from non-root URL (e.g. by manually typing it in the browser's address bar) then Rails will try to handle this request using theirs routing rules from routes.rb - that's wrong, cause it's a "Backbone's" route. How do I load the page and bootstrap Backbone for handling this URL in that case?
Finally I found the solution.
I put the following code into my routes.rb
class XHRConstraint
def matches?(request)
!request.xhr? && !(request.url =~ /\.json$/ && ::Rails.env == 'development')
end
end
match '(*url)' => 'home#index', :constraints => XHRConstraint.new
With this matcher all non-XHR requests are routed to HomeController which returns an HTML page. And XHR requests will be handled by other controllers which return JSON responses.
Also I left requests ending with ".json" as valid in development environment for debugging.
This is a somewhat tricky issue, but basically in a nutshell, you need to respond to all valid (HTML) requests in rails with the same (root) page, from there backbone will take over and route to the correct route handler (in your bakckbone router).
I've discussed this issue in more detail here: rails and backbone working together
Basically what I do is to create actions for every page that I want to handle, and blank views. I use respond_with to return the page (which is the same in each case) and because I handle GET actions only for HTML requests, I add this line at the top of the controller:
respond_to :html, :only => [ :show, :new ]
JSON requests are handled with respond_with as well, but unlike the HTML requests actually return the requested resource (and perform the requested action in the case of PUT, POST and DELETE).
Backbone will not be informed of your url change if you do it manually. This change will be catch by the browser and it will do its job sending the request to the server as usual.
Same if you click in a normal link, it will follow its href without inform Backbone.
If you want Backbone being in charge of a url change you have to do it through the Backbone tools you have available and this is the own Router.
So if you want to make an URL change in the Backbone way you have to do it explicitly, something like:
app.router.navigate("my/route", {trigger: true});

What is client-side routing and how is it used?

I will be glad if someone could answer the following questions
How does it work?
Why is it necessary?
What does it improve?
Client side routing is the same as server side routing, but it's ran in the browser.
In a typical web application you have several pages which map into different URLs, and each of the pages has some logic and a template which is then rendered.
Client-side routing simply runs this process in the browser, using JavaScript for the logic and some JS based template engine or other such approaches to render the pages.
Typically it's used in single page applications, where the server-side code is primarily used to provide a RESTful API the client-side code uses via Ajax.
I was trying to build a Single page application and came to know about client side routing.
By implementing client side routing I was able to achieve the following
The front and back buttons in the browser started working for my single page JavaScript application. This was very important while accessing the page from a mobile browser.
The user was able to Bookmark/share a URL which was not possible earlier.
I know that it's late but I have some information about how the client side routing (CSR) works. This answer does not try to provide a full js implementation of client side routing but rather tries to shed some light on what concepts will help you implement one of your own. It's true that when user click an anchor tag, the browser sends a request to the server. But we will be able to intercept the event and prevent it's default behavior, i.e sending a request to the server by using "event.preventDefault();". Below is snippet from React routers web page.
<a
href="/contact"
onClick={event => {
// stop the browser from changing the URL and requesting the new document
event.preventDefault();
// push an entry into the browser history stack and change the URL
window.history.pushState({}, undefined, "/contact");
}}
/>
Also listening to forward/backward button click is important. This can be done by,
window.addEventListener("popstate", () => {
// URL changed!
});
But looking at the above two snippets you can imagine how a CSR could be implemented. There is much more to it. That's why libraries like React Router exists and web frameworks like angular provide CSR by default.
If you want more information please visit the link below, it will take your the concepts page of react router.
https://reactrouter.com/docs/en/v6/getting-started/concepts
Also if you want to get more depth into the topic your could check out the code of Angular router. Comparing the two implementations will give a much more insight.
What :
In react the history object takes care of that what it does..it keeps track of all the addresses and the Router defines all the different routes. So Router takes the help of this History object to keep a track of various addresses / History of the current URL and based on that location it serves the appropriate content.
Why :
To reduce unnecessary reloads.
For better user experience.
It's internally handled by JS.

Resources