2014-01-08 39 views
10

您已經創建了一個與yeoman,grunt和bower的angularJS應用程序。 我已經爲應用程序啓用了html5Mode。它的工作。但是,當我刷新頁面(本地主機:9000 /登錄),它說AngularJS - html5mode - 無法獲取/登錄

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) 
      ]; 
      } 
     } 
     }, 

但是當我刷新頁面時仍然出現同樣的錯誤。如何解決這個問題?

+1

本地主機後加入server.js這個代碼? – michael

+0

對不起,我沒有得到你 –

+2

在純HTML5模式,你不能直接調用網址。您首先需要調用localhost:9000,以便瀏覽器可以配置此模式。之後,在href =「login」上點擊將包含你想要的模板。 – michael

回答

4

你必須有一個服務器端解決方案,以重定向所有非解決流量的index.html

我將分享一個htaccess這個版本和一個node.js版本。我也在春季啓動中實現了這一點,但是這涉及更多一點。

的.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請求註冊一個pre-flight頭文件,表明它們是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請求中的預檢標題這樣的解決方案,任何未解決的模板請求都將導致無限循環並可能鎖定您的瀏覽器。 !9000 /#/登錄:

-1

你嘗試過使用絕對路徑在$routeProvider

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

這是發生,因爲當你按刷新,瀏覽器將嘗試從服務器檢索/登錄,而不是通過您的客戶端路線提供商。我認爲/ login在你的情況下返回404。

即使請求是爲/ login生成的,您需要獲取實際上爲您的文件提供/index.html服務的服務器。你如何做到這一點取決於你的服務器端設置。你可以用動態腳本或重寫規則來做到這一點。

如果你不能用這種方式控制服務器,那麼htmlmode可能不適合你。

+1

我只使用Grunt。我如何在Gruntfile.js中執行重寫規則? –

2

到目前爲止,Angular需要處理路由才能工作的問題。

我發現了這樣類似的問題,這表明同一HTML5 config來解決該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的很好。

0

加入側「的意見/ login.html的」你templateUrl希望這將工作

0

所有路由

app.use('/*',function(req, res) { 
    res.sendfile(__dirname + '/public/index.html'); 
});