AngularJs remove # (hash) from url or setup Pretty URL
This article will help you to setup Pretty URL in AngularJs, that is to remove # from url.
AngularJS applications by default route with # in the url, the reason for the same is that # is an old browser shortcut which doesn't fire the request.This allows many JavaScript frameworks to build their own client side rerouting.
We need the # (hashtag) for non HTML5 browsers, otherwise they will just do an HTTP call to the server at the mentioned href.
Url with #
http://example-domain.com/#/home
Url without #
http://example-domain.com/home
Getting Started
For now let's hope you have already setup a new AngularJs project or has an existing AngularJs project.Here we are considering working with an existing AngularJs App. I have named my project as angular-one-sample.
The project was scaffolded using Yeoman gulp-angular generator , Yeoman is scaffolding tool for modern web apps and can be used to generate basic app structure for your projects.
After generating the basic app using Yeoman the project structure looks something like this
if you want to run the same in local just use the command
gulp serve --open
The above command will start serving the project at the url
http://localhost:3000/#/home
To remove #
To remove the # from URL we need to make sure 4 things mainly.
- Configure the $locationProvider
- Setting our base for relativelinks
- Edit your .htaccess file if you are using apache server
- Remove # from the routing links through out the app (optional)
Configure $locationProvider
Angularjs $location service parses the URL in the address bar and makes changes to your application and vice versa.
We will use the $locationProvider module and set html5Mode to true.
Now import the $locationProvider module to the router file index.route.js and add the following code to enable the html5Mode
// use the HTML5 History API
$locationProvider.html5Mode(true);
html5Mode is a standardized way to manipulate the browser history using a script. This lets Angularjs change the routing and URLs of our pages without refreshing the page.
After editing the router file it will look something like this
index.route.js
(function() {
'use strict';
angular
.module('angularOneSample')
.config(routerConfig);
/** @ngInject */
function routerConfig($stateProvider, $urlRouterProvider,$locationProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
});
// use the HTML5 History API
$locationProvider.html5Mode(true)
$urlRouterProvider.otherwise('/');
}
})();
Setting our Base
To link around your application using relative links, you will need to set a <base>
in the <head>
of your document. while setting base you will have to consider where the projects resides in the server
if your project files is placed in the /var/www/html
folder (that is project files copied from dist folder after gulp build to root folder of your server) or you are running on gulp serve (while under development in local) then your base will be
<base href="/">
if your project files resides in some folder somefolder then set base to
<base href="/somefolder/">
In my case while developing (on gulp serve) in local i had to set base to
<base href="/">
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<base href="/">
</head>
Now you can see that the app reloads and # is removed from url
Edit your .htaccess file
Sometimes while While running on the Apache server Angulajs Apps seems to hit 404 Page Not found
error on page refresh. To solve this issue we need to add the .htaccess file with the following code to the project folder/root folder where project files are placed
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
Also since we are enabling pretty url to increase SEO points, i like to add some more code to .htaccess to enable compression
and leverage browser Caching
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
# Enable Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
</IfModule>
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
# Leverage Browser Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>
<IfModule mod_headers.c>
<filesmatch "\.(ico|flv|jpg|jpeg|png|gif|css|swf)__aSyNcId_<_hrAtuNXW__quot;>
Header set Cache-Control "max-age=2678400, public"
</filesmatch>
<filesmatch "\.(html|htm)__aSyNcId_<_hrAtuNXW__quot;>
Header set Cache-Control "max-age=7200, private, must-revalidate"
</filesmatch>
<filesmatch "\.(pdf)__aSyNcId_<_hrAtuNXW__quot;>
Header set Cache-Control "max-age=86400, public"
</filesmatch>
<filesmatch "\.(js)__aSyNcId_<_hrAtuNXW__quot;>
Header set Cache-Control "max-age=2678400, private"
</filesmatch>
</IfModule>
Remove # from links used in the app
This step is optional, even if the # in navigation links were not removed, the links will work without any problem . These links automatically will be redirected to links without # (hash)