使用grunt server,如何将所有请求重定向到根URL?

46

我正在构建我的第一个Angular.js应用程序,使用Yeoman

Yeoman使用Grunt,可以通过命令“grunt server”运行node.js连接服务器。

我正在以html5模式运行我的angular应用程序。根据angular文档,这需要修改服务器以重定向所有请求到应用程序的根目录(index.html),因为angular应用程序是单页ajax应用程序。

"在[html5]模式下使用需要在服务器端进行URL重写,基本上您必须重写所有链接以输入您的应用程序入口点(例如index.html)"

我试图解决的问题在这里详细说明。

如何修改我的grunt服务器以将所有页面请求重定向到index.html页面?

5个回答

53
首先,使用命令行导航到包含gruntfile的目录。
在CLI中输入以下内容:
npm install --save-dev connect-modrewrite

在你的Grunt文件顶部添加以下内容:

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

现在进入下一步,您只需要将modRewrite添加到您的connect中即可。
modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']),

这是我的 Gruntfile.js 文件中 "connect" 配置的一个示例。不需要担心我的 lrSnippet 和 ssIncludes,你只需要关注如何加入 modRewrite。

        connect: {
        options: {
            port: 9000,
            // Change this to '0.0.0.0' to access the server from outside.
            hostname: '0.0.0.0',
        },
        livereload: {
            options: {
                middleware: function (connect) {
                return [
                        modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']),
                        lrSnippet,
                        ssInclude(yeomanConfig.app),
                        mountFolder(connect, '.tmp'),
                        mountFolder(connect, yeomanConfig.app)
                        ];
                }
            }
        },
        test: {
            options: {
                middleware: function (connect) {
                    return [
                    mountFolder(connect, '.tmp'),
                    mountFolder(connect, 'test')
                    ];
                }
            }
        },
        dist: {
            options: {
                middleware: function (connect) {
                    return [
                    mountFolder(connect, yeomanConfig.dist)
                    ];
                }
            }
        }
    },

上面关于拉取请求的回答很好,但我喜欢@zuriel在这里手动演示如何操作。 - Murphy Randle
这个问题的被接受的答案对我有用。 - AWolf
谢谢!这个救了我的一天。我不知道为什么Yeoman Angular生成器不能帮助解决这个问题... - tkarls

26

最近Yeoman/Grunt修改了新Gruntfiles的默认模板。

复制默认中间件逻辑 对我很有帮助。

middleware: function (connect, options) {
  var middlewares = [];
  var directory = options.directory || options.base[options.base.length - 1];

  // enable Angular's HTML5 mode
  middlewares.push(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']));

  if (!Array.isArray(options.base)) {
    options.base = [options.base];
  }
  options.base.forEach(function(base) {
    // Serve static files.
    middlewares.push(connect.static(base));
  });

  // Make directory browse-able.
  middlewares.push(connect.directory(directory));

  return middlewares;
}

更新: 从grunt-contrib-connect 0.9.0开始,将中间件注入到connect服务器中变得更加容易了:

module.exports = function (grunt) {
  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);
  grunt.initConfig({
    // The actual grunt server settings
    connect: {
      livereload: {
        options: {
         /* Support `$locationProvider.html5Mode(true);`
          * Requires grunt 0.9.0 or higher
          * Otherwise you will see this error:
          *   Running "connect:livereload" (connect) task
          *   Warning: Cannot call method 'push' of undefined Use --force to continue.
          */
          middleware: function(connect, options, middlewares) {
            var modRewrite = require('connect-modrewrite');

            // enable Angular's HTML5 mode
            middlewares.unshift(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png$ /index.html [L]']));

            return middlewares;
          }
        }
      }
    }
  });
}

3
Zuriel的回答很好,但这应该是被采纳的回答。别忘了运行npm install --save-dev connect-modrewrite - Liam

7

这还是现状吗? - FutuToad

5
为了更深入地简化@Zuriel的答案,以下是我发现对我有用的内容。
  • Install connect-modrewrite: npm install connect-modrewrite --save
  • Include it in your grunt file: var rewrite = require( "connect-modrewrite" );
  • Modify your connect options to use the rewrite:

    connect: {  
        options: {  
            middleware: function ( connect, options, middlewares ) {
                var rules = [
                    "!\\.html|\\.js|\\.css|\\.svg|\\.jp(e?)g|\\.png|\\.gif$ /index.html"
                ];
                middlewares.unshift( rewrite( rules ) );
                return middlewares;
            }
        },
        server: {
            options: {
                port: 9000,
                base: "path/to/base"
            }
        }
    }  
    
我尽量简化了这个问题。由于您可以访问connect提供的中间件,因此很容易将重写设置为第一优先响应。我知道这个问题已经存在一段时间了,但这是谷歌搜索相关问题的前几个结果之一。
这个想法来自源代码:https://github.com/gruntjs/grunt-contrib-connect/blob/master/Gruntfile.js#L126-L139。 规则字符串来自:http://danburzo.ro/grunt/chapters/server/

0

我尝试了所有这些方法,但都没有成功。我正在编写一个Angular2应用程序,解决方案来自于grunt-connect pushstate。 我所做的只是:

npm install grunt-connect-pushstate --save

在Grunt文件中:

var pushState = require('grunt-connect-pushstate/lib/utils').pushState;
middleware: function (connect, options) {
  return [
    // Rewrite requests to root so they may be handled by router 
    pushState(),

    // Serve static files 
    connect.static(options.base)
  ];
}

而且所有的都像魔术一样运行。

https://www.npmjs.com/package/grunt-connect-pushstate


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接