AngularJS - html5Mode - 无法GET /登录

时间:2014-01-08 11:04:22

标签: html5 angularjs gruntjs

您已经使用自耕农,咕噜声和凉亭创建了一个angularJS应用程序。 我为应用程序启用了html5Mode。它的工作。但是,当我刷新页面(localhost:9000 / login)时,它说

Cannot GET /login //or any url I type or refresh

这是应用程序结构

MainApp
|
|__app
|  |
|  |__bower_components
|  |
|  |__scripts
|  | |
|  | |__ app.js
|  | |
|  | |__contollers -- login.js, home.js, register.js
|  | |
|  | |__service -- js files
|  | |
|  | |__styles -- CSS files
|  | |
|  | |__views -- main.html, login.html, register.html,home.html
|  |
|  |__ index.html
|
|__ node_modules
|
|__ bower.json, Gruntfile.js, karma-conf.js, karma-e2e.conf.js, package.json

这是我的 app.js 路由

'use strict';    
var superClientApp=angular.module('mainApp', ['ngCookies']);

//Define Routing for app
superClientApp.config(['$routeProvider', '$locationProvider',
  function($routeProvider,$locationProvider) {
    $routeProvider
    .when('/login', {
        templateUrl: 'login.html',
        controller: 'LoginController'
    })
    .when('/register', {
        templateUrl: 'register.html',
        controller: 'RegisterController'
      })
    .when('/home', {
       templateUrl: 'views/home.html',
       controller: 'homeController'
    })
    .otherwise({
       redirectTo: '/login'
    });
    $locationProvider.html5Mode(true);
}]);

这是我Gruntfile.js的一部分

'use strict';
var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT });
var mountFolder = function (connect, dir) {
  return connect.static(require('path').resolve(dir));
};
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;

// # 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'

module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);
  require('time-grunt')(grunt);

  // configurable paths
  var yeomanConfig = {
    app: 'app',
    dist: 'dist'
  };

  try {
    yeomanConfig.app = require('./bower.json').appPath || yeomanConfig.app;
  } catch (e) {}

  grunt.initConfig({
    yeoman: yeomanConfig,
    watch: {
      coffee: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
        tasks: ['coffee:dist']
      },
      coffeeTest: {
        files: ['test/spec/{,*/}*.coffee'],
        tasks: ['coffee:test']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['copy:styles', 'autoprefixer']
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },
    autoprefixer: {
      options: ['last 1 version'],
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost'
      },
      proxies: [
        {
            context: '/serverApp',
            host: 'localhost',
            port: '8080',
            https: false,
            changeOrigin: false
        }
      ],
      livereload: {
        options: {
          middleware: function (connect) {
            return [
              lrSnippet,
              proxySnippet,
              mountFolder(connect, '.tmp'),
              mountFolder(connect, yeomanConfig.app)
            ];
          }
        }
      },

我经历了this SO question。基于accepted answer,我将Gruntfile.js更改为以下。

'use strict';
var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT });
var mountFolder = function (connect, dir) {
  return connect.static(require('path').resolve(dir));
};
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;

var urlRewrite = require('grunt-connect-rewrite');

// # 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'

module.exports = function (grunt) {
  require('load-grunt-tasks')(grunt);
  require('time-grunt')(grunt);

  // configurable paths
  var yeomanConfig = {
    app: 'app',
    dist: 'dist'
  };

  try {
    yeomanConfig.app = require('./bower.json').appPath || yeomanConfig.app;
  } catch (e) {}

  grunt.initConfig({
    yeoman: yeomanConfig,
    watch: {
      coffee: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
        tasks: ['coffee:dist']
      },
      coffeeTest: {
        files: ['test/spec/{,*/}*.coffee'],
        tasks: ['coffee:test']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['copy:styles', 'autoprefixer']
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },
    autoprefixer: {
      options: ['last 1 version'],
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        base: 'app',
        middleware: function(connect, options) {
            // Return array of whatever middlewares you want
            return [
              // redirect all urls to index.html in build folder
              urlRewrite('app', 'index.html'),

              // Serve static files.
              connect.static(options.base),

              // Make empty directories browsable.
              connect.directory(options.base)
            ];
          }
      },
      proxies: [
        {
            context: '/serverApp',
            host: 'localhost',
            port: '8080',
            https: false,
            changeOrigin: false
        }
      ],
      livereload: {
        options: {
          middleware: function (connect) {
            return [
              lrSnippet,
              proxySnippet,
              mountFolder(connect, '.tmp'),
              mountFolder(connect, yeomanConfig.app)
            ];
          }
        }
      },

但是当我刷新页面时,我仍然遇到同样的错误。怎么解决这个问题?

6 个答案:

答案 0 :(得分:4)

您必须拥有服务器端解决方案才能将所有非解析流量重定向到index.html

我将分享一个htaccess版本和一个node.js版本。我也在spring-boot中实现了这一点,但这有点多了。

<强> htaccess的

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /the-base-from-index.html/


    RewriteEngine on
    RewriteCond %{HTTP:X-Requested-With} !XMLHttpRequest$
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule . index.html [L]
</IfModule>

为了使其正常工作,您的apache配置必须启用mod_rewrite并且还允许覆盖所有。重写也适用于apache配置。

还有一个条件允许您在ajax请求中返回404。为了使其工作,您必须向所有$ http请求注册一个飞行前标头,表示它们是xmlhttp请求。类似的东西:

 myapp.config(function($httpProvider) {
      $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
 });

<强>的NodeJS

var express = require('express');
var bodyParser = require('body-parser')
var path = require('path')
var app = express();

app.use(express.static(__dirname + '/app'));
app.get('/*', function(req, res){
  res.sendFile(__dirname + '/app/index.html');
});

app.listen(9090);
console.log("Node Server Listening on port 9090");

这很简单,可以改进。即检查xmlhttp标头的req标头,与htaccess示例的操作类似。

这些得到了一般性的想法。基本上任何会导致404的流量都会被送到index.html。这允许您继续提供静态内容,但您的路由(只要它们实际上不存在于该位置的磁盘上)将返回index.html。

警告!如果没有像所有ajax请求上的预检标题这样的解决方案,任何未解决的模板请求都将导致无限循环,并可能锁定您的浏览器。

答案 1 :(得分:2)

到目前为止,这必须是Angular的一个常见问题,需要处理以便路由工作。

我在SO上发现了类似的问题,建议使用相同的html5配置来解决hashbang方法 - 请参阅AngularJS: how to enable $locationProvider.html5Mode with deeplinking 此外,scotch.io https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag的教程也可以作为开始。

但最重要的是,我记得这是诀窍。

https://gist.github.com/leocaseiro/4305e06948aa97e77c93

我运行Apache Web服务器。我不记得在什么级别(全局或每个应用程序)我做了配置,但最好的是咨询Web服务器文档,Apache是​​好的。

答案 2 :(得分:0)

这种情况正在发生,因为当您按下刷新时,您的浏览器将尝试从服务器检索/登录,而不是通过客户端路由提供程序。我假设/ login在你的情况下返回404。

即使请求是针对/ login进行的,您也需要让实际为您的文件服务的服务器提供服务/index.html。如何执行此操作取决于您的服务器端设置。您可以使用动态脚本或重写规则来执行此操作。

如果你不能以这种方式控制服务器,那么htmlmode可能不适合你。

答案 3 :(得分:0)

添加&views; / login.html&#39;在你的模板旁边,希望这会起作用

答案 4 :(得分:0)

在所有路径

之后在server.js中添加此代码
class SoldierData extends Model {

    protected $fillable = [];

    protected $dates = [];

    protected $table = 'soldier_data';

答案 5 :(得分:-2)

您是否尝试使用$routeProvider中的绝对路径?

.when('/login', {
  templateUrl: '../app/scripts/views/login.html',
  controller: 'loginController'
},
...