Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS html5Mode using Grunt connect. grunt 0.4.5

I recently switched over to grunt 0.4.5 and it changed how connect works.

I previously used connect-modrewrite and it worked pretty well (had some issues with urls generated by /:parameter).

Here is the old version that worked with grunt 0.4.1 from generator-angular 0.8.0 with the middleware part modded by me to use html5mode.

connect: {
    options: {
        port: 9000,
        hostname: '*IP HERE*',
        livereload: 35729,
        middleware: function (connect, options) {
            var optBase = (typeof options.base === 'string') ? [options.base] : options.base;
            return [require('connect-modrewrite')(['!(\\..+)$ / [L]'])].concat(
                optBase.map(function(path){ return connect.static(path); })
            );
        }
    },
    livereload: {
        options: {
            open: true,
            base: [
                '.tmp',
                '<%= yeoman.app %>'
            ]
        }
    },

Here is the new version from generator-angular 0.9.0-1

connect: {
    options: {
        port: 9000,
        hostname: '*IP HERE*',
        livereload: 35729
    },
    livereload: {
        options: {
            open: true,
            middleware: function (connect) {
                return [
                    connect.static('.tmp'),
                    connect().use(
                        '/bower_components',
                        connect.static('./bower_components')
                    ),
                    connect.static(appConfig.app)
                ];
            }
        }
    },

How can I change this to use mod-rewrite or any other method to achieve html5mode?

I tried using the method provided here: https://gist.github.com/nnarhinen/7719157 I combined it to create the following:

middleware: function (connect) {
    return [
        connect.static(modRewrite(['^[^\\.]*$ /index.html [L]'])),
        connect.static('.tmp'),
        connect().use(
            '/bower_components',
            connect.static('./bower_components')
        ),
        connect.static(appConfig.app)
    ];
}

This allows me to view the normal view, but the modRewrite part does not seem to do what it needs to in order to get to any other view via url.

like image 526
Mark Lenser Avatar asked Jun 18 '14 10:06

Mark Lenser


4 Answers

If anyone else stumbles across this here is the fix:

(the only line added was the modRewrite line)

livereload: {
    options: {
        open: true,
        middleware: function (connect) {
            return [
                modRewrite(['^[^\\.]*$ /index.html [L]']),
                connect.static('.tmp'),
                connect().use(
                    '/bower_components',
                    connect.static('./bower_components')
                ),
                connect.static(appConfig.app)
            ];
        }
    }
},

Make sure you have the following declared at the top of your grunt file:

var modRewrite = require('connect-modrewrite');
like image 66
Mark Lenser Avatar answered Oct 17 '22 04:10

Mark Lenser


Given how other answers are pretty verbose and don't preserve default grunt-contrib-connect middlewares, I came up with solution that uses dedicated middleware – connect-history-api-fallback:

npm install connect-history-api-fallback --save-dev
var history = require('connect-history-api-fallback')
//...
connect: {
    options: {
        middleware: function(connect, options, middleware) {
            middleware.unshift(history())
            return middleware
        },
        //...
    },
    //...
}
like image 24
Klaster_1 Avatar answered Oct 17 '22 04:10

Klaster_1


Though above accepted answer is correct. Im adding the config which I use, it works perfectly on CentOs.

Below 1 to 3 steps are for making Angularjs clean URL work in your local machine using $ grunt serve

But if you want to make them run fine on Server, specially nginx you will also need to update nginx config. (step 4)

  1. $ npm install connect-modrewrite --save

  2. Edit your gruntfile.js. Add at the top of the file

    var modRewrite = require('connect-modrewrite');
    

Then in your middleware:

middleware: function (connect) {
    return [
        modRewrite(['^[^\\.]*$ /index.html [L]']),
        connect.static('.tmp'),
        connect().use('/bower_components',
        connect.static('./bower_components')),
        connect.static(config.app)
    ];
}

for e.g.

// Generated on 2015-11-09 using generator-angular 0.14.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
var modRewrite = require('connect-modrewrite');

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

3.Then go to Livereload middleware, add modRewrite

livereload: {
    options: {
        middleware: function (connect) {
            return [
                modRewrite([
                  '^[^\\.]*$ /index.html [L]'
                ]),
                connect.static('.tmp'),
                connect().use('/bower_components', connect.static('./bower_components')),
                connect.static(config.app)
            ];
        }
    }
},

4.Edit NGINX config:

server {
    server_name yoursite.com;
    root /usr/share/html;
    index index.html;

    location / {
    try_files $uri $uri/ /index.html;
    }
}

Hope it helps :)

like image 3
STEEL Avatar answered Oct 17 '22 04:10

STEEL


Here is my solution, adapted to generator-angular setup, but can be used anywhere. It allows a rewriting syntax (the interesting part is the example livereload configuarion).

connect: {
  options: {
    port: 9000,
    // Change this to '0.0.0.0' to access the server from outside.
    hostname: 'localhost',
    livereload: 35729,
    // Modrewrite rule, connect.static(path) for each path in target's base
    middleware: function (connect, options) {
      var optBase = (typeof options.base === 'string') ? [options.base] : options.base,
          middleware = [require('connect-modrewrite')(['!(\\..+)$ / [L]'])]
            .concat(optBase.map(function (path) { 
              if (path.indexOf('rewrite|') === -1) {
                return connect.static(path);
              } else {
                path = path.replace(/\\/g, '/').split('|');
                return  connect().use(path[1], connect.static(path[2]))
              }
            }));

      return middleware;
    }
  },
  livereload: {
    options: {
      open: true,
      base: [
        '.tmp',
        'rewrite|/bower_components|./bower_components',
        'rewrite|/app/styles|./app/styles', // for sourcemaps
        '<%= yeoman.app %>'
      ]
    }
  }
}
like image 1
pilau Avatar answered Oct 17 '22 04:10

pilau