title | author | layout | categories | |||
---|---|---|---|---|---|---|
Using grunt and angular with pushstate support |
Blackjid |
post |
|
One of the neat things about angularjs routes system is the ability to use the html5 pushstate apis to remove the hash (#) from the url when creating a single page sites.
For this to work you need to tell your server that every request must be rewrited to /index.html
, this way angular is goint to take care of the rest.
If you are using yeoman 1.0 to scaffold your app, you should have a Gruntfile.js
in the root of your project. You can add some rewrites using the connect-modrewrite module. (Note: Remember to add the connect-modrewrite module to your package.json
)
npm install connect-modrewrite
Require the module in your Gruntfile.js
adding
var modRewrite = require('connect-modrewrite');
Then in your livereload configuation add a section in the middlewares
livereload: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: '0.0.0.0',
middleware: function (connect) {
return [
modRewrite([
'!(\\..+)$ / [L]'
]),
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app)
];
}
},
}
Here in the modRewrite middleware you can pass an array of rules that you want to rewrite (check here to see how to write this rules)
You have to be careful because if you are requesting a .js file or .css file you should serve that file and not rewrite the request. For this I use a regex that matches every url that has one of the most common extensions used in the web. (Note the !
at the beggining of the regex means that will invert the match)
'!\\.?(js|css|html|eot|svg|ttf|woff|otf|css|png|jpg|git|ico) / [L]'
You will need to enable the pushstate method within angular routes. In the app.js
file inject the locationProvider
and the html5Mode line in the config section.
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true); // Add this line
$routeProvider
.when('/', { ...
Also I was calling my scripts and css files with relatives urls and this only work if you start navigating from the root page.
Change this
<script src="components/angular/angular.js"></script>
to this
<script src="/components/angular/angular.js"></script>
Note the leading slash. Now the url is absolute.
Yes, doesn't work with new Grunt version, and I can't resolve it yet. It should works with:
But now in Grunt file you can't use functions, only strings.