html 5 mode in angular application [duplicate] - javascript

What actually happens when you enable the html5 mode ? This might go back to the point how routing takes place in single page applications
What I perceived before(it may be wrong) : Looking at the dirty url in the angularjs application I always assumed it being url fragment to which different views are bind for different fragments. So in short we already have all the pages and a particular fragment is being displayed for a particular url .
Now in order to remove the hash you have to set html5mode true and you have to tell the server to return the index page for every request other than your apis . Kinda like
app.get('/ap1',some);
//more apis
*
*
*
//in the end
app.get('*' ,(req,res,next) => req.sendFile('index.html'));
Shouldn't the request go the server and the page be reloaded everytime the url changes ?
and what does html5mode does to the browser ? In the newer frameworks like react and angular(2 or greater) , you don't even have to enable html5mode(except in angular 2 where you have to tell what kind of url you want) .
What is this sorcery ?

This uses the History API.
It is designed so that developers can:
Tell the browser things like "I have used JavaScript to change the contents of the page. It is now the same as the page you would get if you asked for /other/page"
Intercept clicks on Back and Forward so that they can use JS to change the contents of the page to the be the same as the URLs that would be navigated to if the click on Back/Forward wasn't intercepted.
This updates the browser history and the URL in the address bar without triggering a normal navigation to a fresh page. The idea is that you can provide a smoother, faster transition between pages while still having real URLs that work well if you link to them or come back to them later.
That way:
If the JavaScript fails for any reason, the real URLs can still deliver the page
If a search engine indexes the URL, it gets the real data from it
If a visitor lands on a URL that isn't the homepage, they get the content they asked for immediately without having to wait for JavaScript to run, making additional Ajax requests, and assemble all the pieces client side.
It was designed in response to people using hangbangs instead of real URLs.
Now in order to remove the hash you have to set html5mode true and you have to tell the server to return the index page for every request other than your apis
This is terrible advice from Angular.
It abandons all of the good stuff that the history API can provide in order to have all the drawbacks of hashbangs, but with nicer looking URLs.
The problem with doing it properly is that it requires duplicating the logic on the server and the client, which is a lot of work. Isomorphic JavaScript is an approach to reduce this workload.
and what does html5mode does to the browser ?
Nothing. The html5mode variable is read by Angular. The browser doesn't care about it directly. It tells Angular to use the History API instead of hangbang URLs.
In the newer frameworks like react and angular(2 or greater) , you don't even have to enable html5mode(except in angular 2 where you have to tell what kind of url you want) .
They just use the History API by default.

Related

What happens when you enable the html5 mode in mode in angularjs?

What actually happens when you enable the html5 mode ? This might go back to the point how routing takes place in single page applications
What I perceived before(it may be wrong) : Looking at the dirty url in the angularjs application I always assumed it being url fragment to which different views are bind for different fragments. So in short we already have all the pages and a particular fragment is being displayed for a particular url .
Now in order to remove the hash you have to set html5mode true and you have to tell the server to return the index page for every request other than your apis . Kinda like
app.get('/ap1',some);
//more apis
*
*
*
//in the end
app.get('*' ,(req,res,next) => req.sendFile('index.html'));
Shouldn't the request go the server and the page be reloaded everytime the url changes ?
and what does html5mode does to the browser ? In the newer frameworks like react and angular(2 or greater) , you don't even have to enable html5mode(except in angular 2 where you have to tell what kind of url you want) .
What is this sorcery ?
This uses the History API.
It is designed so that developers can:
Tell the browser things like "I have used JavaScript to change the contents of the page. It is now the same as the page you would get if you asked for /other/page"
Intercept clicks on Back and Forward so that they can use JS to change the contents of the page to the be the same as the URLs that would be navigated to if the click on Back/Forward wasn't intercepted.
This updates the browser history and the URL in the address bar without triggering a normal navigation to a fresh page. The idea is that you can provide a smoother, faster transition between pages while still having real URLs that work well if you link to them or come back to them later.
That way:
If the JavaScript fails for any reason, the real URLs can still deliver the page
If a search engine indexes the URL, it gets the real data from it
If a visitor lands on a URL that isn't the homepage, they get the content they asked for immediately without having to wait for JavaScript to run, making additional Ajax requests, and assemble all the pieces client side.
It was designed in response to people using hangbangs instead of real URLs.
Now in order to remove the hash you have to set html5mode true and you have to tell the server to return the index page for every request other than your apis
This is terrible advice from Angular.
It abandons all of the good stuff that the history API can provide in order to have all the drawbacks of hashbangs, but with nicer looking URLs.
The problem with doing it properly is that it requires duplicating the logic on the server and the client, which is a lot of work. Isomorphic JavaScript is an approach to reduce this workload.
and what does html5mode does to the browser ?
Nothing. The html5mode variable is read by Angular. The browser doesn't care about it directly. It tells Angular to use the History API instead of hangbang URLs.
In the newer frameworks like react and angular(2 or greater) , you don't even have to enable html5mode(except in angular 2 where you have to tell what kind of url you want) .
They just use the History API by default.

How do I have a web game run on the same URL?

For rapid prototyping of my concepts, I'm using Express with Mongo and so far have set up a mongostore cookie storage system.
My question: Is it possible, after logging in/authenticating/etc, to have everything occur on the same page, aka '/game'? I still want multiple views and routes to be rendered, but using different areas of the screen, or overwriting elements on the screen, with the base game.jade still visible.
I essentially want to have the user on the same URL the entire time, but still use multiple routes and views. I looked into stuff like '/game/:stuff' but that still changes the URL I think.
FYI this is called a single-page web application.
One common way to do this is to route to different views using the hash token. For example, all of the following URLs would be part of the same page:
/game#introScreen
/game#level1
/game#level2
Your client code can respond to changes in the hash portion of the URL and change the display accordingly. The page does not reload and all your JavaScript code (and variable state) remains in place.
If you're using a framework like angularjs it can help do the routing for you.

Javascript Client Routing - Reload Page

I have a client side router with which I can navigate through my web application with hash based urls, like http://example.com/#home. With the history.pushState(..) method I make the url more cleaner, like http://example.com/home. Now my problem is when someone reload the page, the url is unknown, because there is no hash in it. Is there a elegant way to fix this?
What it's meant for
history.pushState(..) is needed for single-page-applications to create an artificial browser history. That artificial history allows users to navigate via back and forward buttons and also to bookmark a "page" (there is only one, but it feels like multiple pages).
What you're doing
Now you're rewriting URLs to locations, which don't exist. On reload the browser navigates to that location and finds nothing, it doesn't know the relationship between your single-page-application and that new URL.
Solutions
You could try to fix this by creating redirections on server-side. Then you'll be able to read the current state. There are multiple options for redirects:
mod_rewrite - all to index except static folder
Redirect from an HTML page? (discouraged)
...
Keep the hashed URLs and use the saved time to work on real features.
I'd take the second option.

How does Asana handle URLs without a #

You may have seen app.asana.com.
If not you should check it out, it is a very nice designed webapp.
But I can't figure out how they handle the whole URL management.
Backbone.js or Knockout.js handles the URL with the #, and everything after that is just generated.
But asana doesn't have a hash and can modify the URL, how are they doing this?
Looks like they're using HTML5 history.pushState(); so they don't have to refresh the page and so they don't have to use # (hashes) in the URL to go to a certain part in a web app.
Here's a good tutorial about history.pushState();: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
This is the what Google+ and Facebook uses to change the URL without refreshing.
I hope this helps.
HTML5 Push State: http://spoiledmilk.dk/blog/html5-changing-the-browser-url-without-refreshing-page
The big benefit here is that if you paste an Asana URL directly into the browser (or click on a link from an email), the server sees the full URL and can immediately send the appropriate task data to the client. We used to use url fragments, but we needed to do a second round trip after the application loaded to read the fragment in JavaScript and pass it to the server.

Clientside URL Routing

Looking at turning my ASP MVC app into pure JS/Html however its not just a 1 page app, it has a couple of pages, but each one has alot of ajax and events.
Anyway currently my urls on ASP MVC are like:
/login
/admin/{action}/{adminId}
/posts/{posterId}
/picture/{pictureId}
So that is all nice and simple and easy to see what you are doing in the url, you also get correct back button behaviour. So trying to adopt this sort of thing to a pure JS/Html approach seems to bit either very tough or impossible. I dont need an exact match but I was hoping to do something like:
http://localhost/myapp/posts/10
Then that would somehow be able to route the actual request to http://localhost/myapp/posts.html with the variable exposed. Now I am pretty sure this is impossible as when the above is entered into the browser it is going to attempt to look in a directory called posts and look for 10, which wont exist.
Now I have seen Crossroads and LeviRoutes and a few other similar technologies, however they seem to rely upon the hashbang method, which some people like others hate. Is there any way around this? If not can anyone point to any good tutorials on how to use these frameworks, as each seems fairly light on documentation.
There's no workaround for not using hash. HTML5 History API isn't available on IE and Opera yet. If your application is targeting very specific platform, then you can use History API instead of hash. However, History API is inconsistent across browsers. You can read it here: http://www.battlehorse.net/page/2011/02/12/html5history.htm
If you choose to use History API, it would be easy. You can use whatever routing strategy you want in ASP.NET MVC, then just match this strategy in JavaScript. You can read more about History API here: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
If you choose to use hash, you need to do make some requests into AJAX requests:
Determine if a request is done via AJAX:
if GET/posts/{action}/{id} is by AJAX, serve the original content
if it's not by AJAX, redirect the user to /#!/posts/{action}/{id}.
Handle client side hash by requesting for the right content:
When the hash is changed to #!/posts/{action}/{id}, GET /posts/{action}/{id} via AJAX and replace the content with the new one from the server.
Intercept form.onsubmit event:
Whenever a form is trying to submit to /posts/{action}/{id}, cancel it and use AJAX to post and then replace the content with the new one from the server.
Now your app should work like a one page app.
There is no real way around hashbangs if you wish to keep it clientside and cross browser compatible.

Categories