2015-04-29 19 views
13

Tôi đang sử dụng Bộ định tuyến giao diện người dùng góc trong ứng dụng góc của mình và tôi đã bật chế độ HTML5 để xóa # mẫu URL bằng cách sử dụng $ locationProvider trong cấu hình.Tải lại trang không thành công khi sử dụng Angular Ui Router với chế độ Html5 được bật

var app = angular.module('openIDC', ['ui.router']); 
app.config(function($urlRouterProvider, $stateProvider, $locationProvider) { 

    $locationProvider.html5Mode(true); 

    $urlRouterProvider.otherwise('/'); 

    $stateProvider 
    .state('home', { 
     url: '/', 
     templateUrl: 'views/home.html', 
     controller: 'HomeController' 
    }) 
    .state('login', { 
     url: '/login', 
     templateUrl: 'views/login.html', 
     controller: 'LoginController' 
    }) 
}); 

Tôi cũng đã đặt thẻ <base href="/" /> trong tệp index.html. Định tuyến hoạt động tốt và tôi có thể điều hướng đến các trang và # được xóa nhưng khi tôi làm mới trang bằng cách sử dụng nút tải lại trên trình duyệt, có phản hồi lỗi 404.

enter image description here

Tại sao điều này xảy ra và làm thế nào tôi có thể sửa chữa nó và có chế độ HTML5 kích hoạt để có URL đúng

Trả lời

12

Kasun, lý do mà điều này xảy ra là bởi vì bạn đang cố gắng để làm mới trang từ một trong những tuyến đường tiểu của bạn (không có gì để làm với ui -rào).

Về cơ bản nếu bạn yêu cầu www.yourdomain.com/ bạn có thể có thiết lập máy chủ của mình để trả lại index.html khởi động ứng dụng góc của bạn. Sau khi ứng dụng đã tải xong, bất kỳ thay đổi url nào khác sẽ mất html5Mode để xem xét và cập nhật trang của bạn qua ui-router.

Khi bạn tải lại trang, ứng dụng góc không còn hợp lệ vì nó chưa được tải, vì vậy nếu bạn đang cố gắng tải tuyến phụ (ví dụ: www.yourdomain.com/someotherpage), thì máy chủ của bạn không biết cách xử lý /someotherpage và có khả năng trả về 404 hoặc một số lỗi khác.

Những gì bạn cần làm là định cấu hình máy chủ của mình để trả lại ứng dụng góc cho tất cả các tuyến. Tôi chủ yếu sử dụng nút/bày tỏ, vì vậy tôi làm điều gì đó như:

app.get('*', function(req, res, next) { 
    // call all routes and return the index.html file here 
} 

Lưu ý: Tôi thường sử dụng một cái gì đó như thế này như một nắm bắt chính thức tất cả, tuy nhiên tôi cũng bao gồm các tuyến đường khác trên nó cho những thứ như yêu cầu các tập tin tĩnh, trình thu thập dữ liệu web và bất kỳ tuyến đường cụ thể nào khác cần được xử lý.

+0

Về cơ bản giải pháp. Một điều tôi muốn thêm: nếu chương trình phụ trợ của bạn cũng đang phân phát dữ liệu động, ví dụ: một API, bạn muốn tách biệt API khỏi chuyển hướng này, vì vậy bạn phải thêm quy tắc này chỉ khi một tệp phù hợp với yêu cầu không tồn tại và không có tuyến API nào khác được khớp. –

+0

Điểm tốt. Đã cập nhật câu trả lời của tôi. Đối với các API mặc dù, tôi thích chạy chúng từ một url/tên miền riêng biệt. –

+0

Có một ví dụ điển hình về NodeJS phục vụ SPA tại đây: http://stackoverflow.com/questions/20396900/angularjs-routing-in-expressjs – mbokil

8

Bạn cần phải thiết lập url viết lại trên máy chủ bên

cho apache nó sẽ có cái gì đó như:

RewriteEngine On 
RewriteBase/
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule . index.html 

trong .htaccess file (hãy chắc chắn rằng mod_rewrite module apache là kích hoạt)

và cấu hình như thế này cho nginx:

location/{ 
    .... 
    try_files $uri $uri/ /index.html =404; 
} 
+0

Bạn làm điều tương tự như thế nào trong IIS? –

+1

Không chắc chắn, không bao giờ thực hiện việc này trong IIS. Nhưng câu trả lời này có vẻ đúng: http://stackoverflow.com/questions/12614072/how-do-i-configure-iis-for-url-rewriting-an-angularjs-application-in-html5-mode#26152011 –

3

làm đầu tiên tập tin .htaccess sau đó sao chép qua các mã

<ifModule mod_rewrite.c> 
    RewriteEngine on 

    # Don't rewrite files or directories 
    RewriteCond %{REQUEST_FILENAME} -f [OR] 
    RewriteCond %{REQUEST_FILENAME} -d 
    RewriteRule^- [L] 


    RewriteRule^your root folder/index.html [L] 
     </ifModule> 


<base url="/"></base> in index.html file 
2

Cant giải thích chi tiết tại sao điều này xảy ra nhưng tôi có thể mô tả cho bạn một cách tôi giải quyết vấn đề này ra. Vì vậy, tôi đã sử dụng UrlRewriterFilter cho chương trình phụ trợ SpringMvc của tôi. Cấu hình mô-đun chung góc:

var app = angular.module('ilonaChatGeneralModule', 
    [ 
     'ui.router' 
    ]); 

app.config(function($locationProvider){ 
    $locationProvider.html5Mode(true); 
}); 

app.config(function($stateProvider, $urlRouterProvider) { 

    $urlRouterProvider.otherwise('/'); 

    var home = ['/', { 
     url: '/', 
     templateUrl: 'views/userlist.html' 
    }]; 

    var login = ['login', { 
     url: '/login', 
     templateUrl: 'views/login.html' 
    }]; 

    var privateRoom = ['privateroom', { 
     url: '/privateroom', 
     templateUrl: 'views/privateroom.html' 
    }]; 

    $stateProvider 
     .state(home) 
     .state(login) 
     .state(privateRoom) 
     ; 
}); 

Trang chủ, chỉ mục của tôi.html:

<html ng-app="ilonaChatGeneralModule" ng-controller="ilonaChatGeneralCtrl"> 
<head> 
    <base href="/"> 
    ... 

</head> 
<body> 
<div> 
    <div ui-view=""></div> 
</div> 
</body> 
</html> 

Đây là giao diện người dùng. Đối với backend tôi đã sử dụng UrlRewriteFilter, bạn có thể lấy nó với sự phụ thuộc maven sau:

<dependency> 
     <groupId>org.tuckey</groupId> 
     <artifactId>urlrewritefilter</artifactId> 
     <version>4.0.3</version> 
    </dependency> 

Tôi đã thêm nó vào SpringMVC WebAppInitializer của tôi theo cách sau:

package com.sbk.config; 

    import org.springframework.context.ApplicationContext; 
    import org.springframework.web.context.ContextLoaderListener; 
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 
    import org.springframework.web.filter.CharacterEncodingFilter; 
    import org.springframework.web.servlet.DispatcherServlet; 
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 
    import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter; 

    import javax.servlet.*; 
    import java.nio.charset.StandardCharsets; 
    import java.util.EnumSet; 

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
     private static final String URL_REWRITE_FILTER_NAME = "urlRewrite"; 
     private static final String URL_REWRITE_FILTER_MAPPING = "/*"; 

... 
     @Override 
     public void onStartup(ServletContext servletContext) throws ServletException { 
      super.onStartup(servletContext); 

      FilterRegistration.Dynamic urlReWrite = servletContext.addFilter(URL_REWRITE_FILTER_NAME, new UrlRewriteFilter()); 
      EnumSet<DispatcherType> urlReWriteDispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD); 
      urlReWrite.addMappingForUrlPatterns(urlReWriteDispatcherTypes, true, URL_REWRITE_FILTER_MAPPING); 
     } 
    } 

Bộ lọc này đòi hỏi urlrewrite.xml nộp dưới ur WEB-INF thư mục (có vẻ như trong cấu hình nhưng mặc định nơi - ở đây). Nội dung của tập tin này:

<!DOCTYPE urlrewrite 
     PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN" 
     "http://www.tuckey.org/res/dtds/urlrewrite2.6.dtd"> 

<urlrewrite> 

    <rule> 
     <from>/login$</from> 
     <to>index.html</to> 
    </rule> 

    <rule> 
     <from>/privateroom$</from> 
     <to>index.html</to> 
    </rule> 

</urlrewrite> 

Tôi đã không đọc hướng dẫn sử dụng một cách cẩn thận nhưng tôi nghi ngờ ý tưởng đó là khi bạn làm mới trình duyệt ur với http://yourhost:xxxx/privateroom ứng dụng ur cố gắng tìm xem physicaly hiện http://yourhost:xxxx/privateroom. Nhưng vắng mặt của nó. Và khi bạn chuyển hướng nó đến góc trang cơ sở ur sẽ xây dựng liên kết chính xác đến tệp vật lý sử dụng định nghĩa trạng thái của nó. Tôi có thể nhầm lẫn về mặt lý thuyết nhưng nó hoạt động trong thực tế

3

Nhận thấy một nhận xét hỏi về IIS - chưa thấy nó ở đây - nhưng đây là cách tôi làm việc. Đảm bảo cài đặt URL Rewrite 2.0.

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
<system.webServer> 
<rewrite> 
<rules> 
<rule name="AngularJS Routes" stopProcessing="true"> 
<match url=".*" /> 
<conditions logicalGrouping="MatchAll"> 
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> 
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> 
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /> 
</conditions> 
<action type="Rewrite" url="/" /> 
</rule> 
</rules> 
</rewrite> 
</system.webServer> 
</configuration>` 
+0

Làm việc tuyệt vời, cảm ơn! – RandomUs1r

2

Nếu bạn không thể định cấu hình máy chủ của mình, hãy định cấu hình web.xml của bạn để xử lý làm mới khi người dùng đang ở trên đường dẫn html5.

<error-page> 
    <!-- Mapping a 404 when user refreshes with an html5 push route--> 
    <error-code>404</error-code> 
    <location>/index.html</location> 
</error-page> 
Các vấn đề liên quan