使用AngularJS HTML5模式重新加载页面会产生错误的GET请求

Die*_*ker 193 html5 angularjs angular-routing

我想为我的应用启用HTML5模式.我已经把下面的代码的配置,如图所示在这里:

return app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider) {

    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix = '!';

    $routeProvider.when('/', {
        templateUrl: '/views/index.html',
        controller: 'indexCtrl'
    });
    $routeProvider.when('/about',{
        templateUrl: '/views/about.html',
        controller: 'AboutCtrl'
    });
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我使用了$locationProvider.html5mode和我改变了我所有的链接ng-href来排除/#/.

问题

目前,我可以去localhost:9000/看看索引页面并导航到其他页面localhost:9000/about.

但是,刷新localhost:9000/about页面时会出现问题.我得到以下输出:Cannot GET /about

如果我看一下网络电话:

Request URL:localhost:9000/about
Request Method:GET
Run Code Online (Sandbox Code Playgroud)

如果我先去localhost:9000/,然后点击导航到的按钮,/about我会得到:

Request URL:http://localhost:9000/views/about.html
Run Code Online (Sandbox Code Playgroud)

这使页面完美呈现.

如何在刷新时启用角度来获取正确的页面?

Jam*_*arp 99

角度文档

服务器端
使用此模式需要在服务器端重写URL,基本上您必须重写所有链接到应用程序的入口点(例如index.html)

这样做的原因是,当您第一次访问页面(/about)时,例如刷新后,浏览器无法知道这不是真正的URL,因此它会继续并加载它.但是,如果您先加载了根页面和所有的javascript代码,那么当您导航到/aboutAngular时,可以在浏览器尝试访问服务器并相应地处理它之前进入

  • 当它说"你必须重写你的应用程序入口点的所有链接(例如index.html)"这是什么意思?这是否意味着我必须进入我的`$ routeProvider`并将每个`templateUrl`的路径改为例如`templateUrl:'/ views/about.html',`到`templateUrl:'example.com/views/about. HTML",`? (21认同)
  • 不,你在$ routeProvider中的规则应保持不变.答案是指"服务器端".它指的是更改提供角度html页面的服务器上的路由.在每个请求到达你的角度应用程序之前,它必须首先通过服务器端路由,这应该重写所有请求指向你的角度应用程序入口点(例如'index.html'或'/',取决于你的角度路线工作). (7认同)
  • apache的好文章,有一个htaccess例子:https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/ (5认同)

lok*_*ers 62

设置的东西很少,所以你在浏览器中的链接看起来像是http://yourdomain.com/path你的角配置+服务器端

1)AngularJS

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true);
Run Code Online (Sandbox Code Playgroud)

2)服务器端,只需放入.htaccess根文件夹并粘贴即可

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]
Run Code Online (Sandbox Code Playgroud)

更有趣的东西,以阅读angularjs HTML5模式,并根据不同的环境需要的配置https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server -to-work-with-html5mode 这个问题也可以帮助你定位/切换html5和hashbang模式/链接重写


Tay*_*aye 34

我有类似的问题,我解决了它:

  • 使用<base href="/index.html">在索引页

  • 使用我的node/Express服务器中的catch所有路由中间件,如下所示(将其放在路由器之后):

app.use(function(req, res) {
    res.sendfile(__dirname + '/Public/index.html');
});
Run Code Online (Sandbox Code Playgroud)

我认为这应该让你起步和运行.

如果您使用apache服务器,则可能需要mod_rewrite您的链接.这并不难.配置文件中只有一些变化.

所有这一切都假设你在angularjs上启用了html5mode.现在.请注意,在角度1.2中,实际上不再推荐声明基本URL.

  • 这个答案值得三星级!感谢您提供如此简单的答案。其他所有人都重复关于“需要进行服务器重定向”的同一行。 (2认同)

Osc*_*car 26

BrowserSync和Gulp的解决方案.

来自https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643

首先安装connect-history-api-fallback:

npm --save-dev install connect-history-api-fallback
Run Code Online (Sandbox Code Playgroud)

然后将其添加到您的gulpfile.js:

var historyApiFallback = require('connect-history-api-fallback');

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: "app",
      middleware: [ historyApiFallback() ]
    }
  });
});
Run Code Online (Sandbox Code Playgroud)


Mur*_*rlu 10

我写了一个简单的连接中间件来模拟grunt项目的url重写.https://gist.github.com/muratcorlu/5803655

你可以这样使用:

module.exports = function(grunt) {
  var urlRewrite = require('grunt-connect-rewrite');

  // Project configuration.
  grunt.initConfig({
    connect: {
      server: {
        options: {
          port: 9001,
          base: 'build',
          middleware: function(connect, options) {
            // Return array of whatever middlewares you want
            return [
              // redirect all urls to index.html in build folder
              urlRewrite('build', 'index.html'),

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

              // Make empty directories browsable.
              connect.directory(options.base)
            ];
          }
        }
      }
    }
  })
};
Run Code Online (Sandbox Code Playgroud)


Mak*_*ood 8

如果你使用AngularJS与MVC进行.NET堆栈,那么你需要做的就是从url中删除'#':

  1. 在_Layout页面中设置基本href: <head> <base href="/"> </head>

  2. 然后,在角度应用配置中添加以下内容: $locationProvider.html5Mode(true)

  3. 以上将从网址中删除"#",但页面刷新将无法工作,例如,如果您在"yoursite.com/about"页面刷新将给你一个404.这是因为MVC不知道角度路由和MVC模式它将寻找MVC路由路径中不存在的'about'的MVC页面.解决方法是将所有MVC页面请求发送到单个MVC视图,您可以通过添加捕获所有URL的路由来执行此操作


routes.MapRoute(
        name: "App",
        url: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 8

IIS URL重写规则以防止在html5mode中页面刷新后出现404错误

适用于Windows下IIS下的角度运行

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>
Run Code Online (Sandbox Code Playgroud)

NodeJS/ExpressJS路由以防止在html5mode中刷新页面后出现404错误

对于Node/Express下的角度运行

var express = require('express');
var path = require('path');
var router = express.Router();

// serve angular front end files from root path
router.use('/', express.static('app', { redirect: false }));

// rewrite virtual urls to angular app to enable refreshing of internal pages
router.get('*', function (req, res, next) {
    res.sendFile(path.resolve('app/index.html'));
});

module.exports = router;
Run Code Online (Sandbox Code Playgroud)

更多信息:AngularJS - 在NodeJS和IIS中启用没有404错误的HTML5模式页面刷新


Bre*_*ett 5

正如其他人所提到的,您需要在服务器上重写路由并进行设置<base href="/"/>.

用于gulp-connect:

npm install connect-pushstate

var gulp = require('gulp'),
  connect = require('gulp-connect'),
  pushState = require('connect-pushstate/lib/pushstate').pushState;
...
connect.server({
  ...
  middleware: function (connect, options) {
    return [
      pushState()
    ];
  }
  ...
})
....
Run Code Online (Sandbox Code Playgroud)