I'm a newbie in js, I follow this example to study how to route UI in SPA with angularjs.
When I download and run this example, the URL is
"http://localhost:8080/#/home"
but when I start to create my sample myself, the URL always is
"http://localhost:8080/#!/home"
I don't know the meaning of "!" symbol in the URL. My sample still work but the "!" inside the URL make me confuse, I wonder that "something was missing, isn't it?"
Please teach me or give me some keywords to understand the problem deeper.
Thanks
It is called Fragment_identifier
The $location service is designed to support hash prefixed URLs
for cases where the browser does not support HTML5 push-state navigation.
The Google Ajax Crawling Scheme expects that local paths within a SPA start
with a hash-bang (e.g. somedomain.com/base/path/#!/client/side/path).
The $locationProvide allows the application developer to configure the
hashPrefix, and it is normal to set this to a bang '!', but the default
has always been the empty string ''.
This has caused some confusion where a user is not aware of this feature
and wonders why adding a hash value to the location (e.g. $location.hash('xxx'))
results in a double hash: ##xxx.
This commit changes the default value of the prefix to '!', which is more
natural and expected.
See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started
Referred from
and please visit here : URL hash-bang (#!/) prefix instead of simple hash (#/) in Angular 1.6
Related
I am working on a project where I am using Angularjs (1.x) as web framework. In that app, I needed routing, so I am using angular-ui-router. I configured the routes in my app and its working fine, but exclamation(!) in routes is not clear to me and why these exclamation comes to routes.
Also, I saw demo example code provided by angular ui router . In Hello World tutorial, I observed that routes are with hash(#) but not with exclamation(!) eg: https://some_url/#/home
but in Hello Solar System tutorial routes are with hash(#) and exclamation(!) eg. https://some_url/#!/hello.
Config for angular ui router in both tutorials are in same way. Thats why I am not able to understand what exactly is making the difference in both of them. So, I need help to understand this.
Any useful suggestion will be appreciated.
Thanks!
To let everyone know the answer for this question, adding what I understood from comments.
This change can be observed in angular version > 1.6.x. In previous version it was like just # (hash bang) only.
To get url like # way only, you can simply write in this way,
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix('');
}]);
This change was introduced in version 1.6.0, which you can see https://github.com/angular/angular.js/blob/master/CHANGELOG.md#location-due-to.
Also, adding here what is written there:
The hash-prefix for $location hash-bang URLs has changed from the empty string "" to the bang "!". If your application does not use HTML5 mode or is being run on browsers that do not support HTML5 mode, and you have not specified your own hash-prefix then client side URLs will now contain a "!" prefix. For example, rather than mydomain.com/#/a/b/c will become mydomain.com/#!/a/b/c.
As mentioned in Angular doc:
Setting a prefix is not necessary, but it is considered a good
practice (for reasons that are outside the scope of this tutorial). !
is the most commonly used prefix.
https://docs.angularjs.org/tutorial/step_09
Do anyone know why it's a good practice? What's the advantages of using prefix?
It should be due to the fact that the Google Ajax Crawling Scheme expects that local paths within a SPA (Single Page Application) start with a hash-bang, as you can read in the following link from the related angular feature:
https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52
You can find more information on the Google Ajax Crawling Scheme in the following link, where they say the hash-bang (#!) is a way for the Google Crawler to understand a URL is a pretty AJAX URL:
https://developers.google.com/webmasters/ajax-crawling/docs/getting-started
I'm deciding whether it's safe to develop my client-facing app in AngularJS using pushState.
I've read that when using pushState in an AngularJS app, we don't need to worry about Googlebot because it can now execute enough JS to produce an HTML snippet for itself. But then I wonder about Bing, Facebook and other bots and scrapers. The tutorials I've seen for making AngularJS SEO-friendly all deal with apps that use hashbangs (#!). These don't apply to me since I'm not using hashbangs.
Does anyone have insight into this problem? What are some methods for ensuring an AngularJS app that uses pushState is SEO-friendly and Social-scraper-friendly? If you use a service like Seo4Ajax or prerender.io I'd appreciate your thoughts on it.
Note: As I understand it, when developing single page apps in the last couple of years it has been necessary to send HTML snippets to SEO crawlers. This was accomplished by using hashbangs and a meta tag that let Google, Bing and Facebook know that it needed to replace the bang (!) with an _escaped_string when making a request. On the server you'd listed for requests with _escaped_string and deliver the appropriate HTML snippet using a tool to generate HTML snippets like phantomJS.
Now that we have pushState, I don't see how we indicate to javascript-less bots what part of the URL to rewrite with an _escaped_string or even if it's necessary. I'm having trouble finding any information beyond "you're site will be okay with google ;)".
Here are some other SO questions that are similar but have gone unanswered.
Angularjs vs SEO vs pushState
.htaccess for SEO bots crawling single page applications without hashbangs
Here's a solution I posted in that question and am considering for myself in case I want to send HTML snippets to bots. This would be a solution for a Symfony2 backend:
Use prerender or another service to generate static snippets of all your pages. Store them somewhere accessible by your router.
In your Symfony2 routing file, create a route that matches your SPA. I have a test SPA running at localhost.com/ng-test/, so my route would look like this:
# Adding a trailing / to this route breaks it. Not sure why.
# This is also not formatting correctly in StackOverflow. This is yaml.
NgTestReroute:
----path: /ng-test/{one}/{two}/{three}/{four}
----defaults:
--------_controller: DriverSideSiteBundle:NgTest:ngTestReroute
--------'one': null
--------'two': null
--------'three': null
--------'four': null
----methods: [GET]
In your Symfony2 controller, check user-agent to see if it's googlebot or bingbot. You should be able to do this with the code below, and then use this list to target the bots you're interested in (http://www.searchenginedictionary.com/spider-names.shtml)...
if(strstr(strtolower($_SERVER['HTTP_USER_AGENT']), "googlebot"))
{
// what to do
}
If your controller finds a match to a bot, send it the HTML snippet. Otherwise, as in the case with my AngularJS app, just send the user to the index page and Angular will correctly do the rest.
Supposedly, Bing also supports pushState. For Facebook, make sure your website takes advantage of Open Graph META tags.
When routing in Angular views we add the following. I don't understand the need to add #; if I remove it, I get a 404 Error.
a href="#/AddNewOrder"
Putting # in URL indicates start of the hash part, which is used to address elements inside a single page. In modern single-page web applications, this can be used to address application states.
If you don't put the # there, you're changing the path, which means you're creating a new URL and prompting the browser to load the content at that new URL instead of the current page.
As other posters have suggested, you don't have to use hashes when using html5mode. I left it out, because it brings a few challenges of its own, which I feel to be outside the scope of the question.
enter link description hereYou don't have to. You can configure your URLs to look like normal URLs, but in reality they will still work the same way.
Check https://docs.angularjs.org/guide/$location
And refer to html5mode
It will only work in modern browsers though. Old browsers will still show the hash. But the cool thing is that you can write your URLs the old/normal way.
# or fragment identifier is a way to indicate a specific portion of a single document. Without the #, the url corresponds to a different page.
For example www.yoursite.com/page links to the /page location of your website, while www.yoursite.com/#/location points to the same index page of your website but at a specfic point in the web page #location, or in your case, a different template view.
Angular routing can not load different templates for different server urls. It is specifically designed for single-page applications and any loading of partial views or templates has to happen on the same web-page or location. Hence only the fragment part of the url changes when using angularjs routing.
More information about fragments can be found here: http://en.wikipedia.org/wiki/Fragment_identifier
in order to make nice urls, I decide to remove the # from my ulrs using the tip from the following question Removing the fragment identifier from AngularJS urls (# symbol) Now, I realized that my urls are not working if I try a direct access to them. from the given example in the related question if put the url below directly in the browser http://localhost/phones
I'll get a 404.
Any idea how to solve this?
You need to write server side code that will generate the page that you were previously depending on the client-side JavaScript to generate.
This will then be the initial view for that URL.
If the client supports JavaScript (and the JavaScript doesn't fail for any reason) it will then take over for future interactions.
Otherwise, the regular links and forms you (should) have in the page will function as normal without JS.