193

我想为我的应用启用 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'
    });

如您所见,我使用了$locationProvider.html5mode并更改了所有链接ng-href以排除/#/.

问题

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

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

如果我查看网络调用:

Request URL:localhost:9000/about
Request Method:GET

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

Request URL:http://localhost:9000/views/about.html

完美呈现页面。

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

4

23 回答 23

99

角度文档

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

原因是当你第一次访问页面/about(但是,如果您首先加载了根页面和所有 javascript 代码,那么当您导航到/aboutAngular 时,可以在浏览器尝试访问服务器并相应地处理它之前进入那里

于 2013-05-15T16:37:43.267 回答
64

需要设置的东西很少,因此您在浏览器中的链接看起来像http://yourdomain.com/path,这些是您的角度配置 + 服务器端

1) AngularJS

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true);

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

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

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

更多有趣的东西要阅读关于 angularjs 中的 html5 模式以及每个不同环境所需的配置https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server -to-work-with-html5mode 这个问题也可以帮助你$location / 在 html5 和 hashbang 模式之间切换 / 链接重写

于 2014-09-21T16:26:01.017 回答
37

我有一个类似的问题,我通过以下方式解决了它:

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

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

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

我认为这应该让你启动并运行。

如果您使用 apache 服务器,您可能需要 mod_rewrite 您的链接。做起来并不难。只需在配置文件中进行一些更改。

所有这一切都假设您在 angularjs 上启用了 html5mode。现在。请注意,在 Angular 1.2 中,实际上不再建议声明基本 url。

于 2013-08-13T16:35:31.320 回答
27

BrowserSync 和 Gulp 的解决方案。

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

首先安装connect-history-api-fallback

npm --save-dev install connect-history-api-fallback

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

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

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: "app",
      middleware: [ historyApiFallback() ]
    }
  });
});
于 2015-06-08T14:17:49.500 回答
15

您需要配置服务器以将所有内容重写为 index.html 以加载应用程序:

https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode

于 2014-03-12T20:33:26.647 回答
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)
            ];
          }
        }
      }
    }
  })
};
于 2013-06-18T09:08:46.600 回答
8

IIS URL 重写规则以防止在 html5 模式下刷新页面后出现 404 错误

用于 Windows 上 IIS 下的 Angular 运行

<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>

NodeJS / ExpressJS 路由以防止在 html5 模式下刷新页面后出现 404 错误

用于 Node/Express 下的 Angular 运行

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;

更多信息:AngularJS - 在 NodeJS 和 IIS 中启用 HTML5 模式页面刷新而不出现 404 错误

于 2016-07-26T01:52:29.170 回答
8

如果您在带有 AngularJS 的 MVC 的 .NET 堆栈中,那么您必须执行以下操作才能从 url 中删除“#”:

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

  2. 然后,在您的 Angular 应用程序配置中添加以下内容:$locationProvider.html5Mode(true)

  3. 上面将从 url 中删除 '#' 但页面刷新将不起作用,例如,如果你在“yoursite.com/about”页面刷新会给你一个 404。这是因为 MVC 不知道角度路由和 MVC 模式它将查找 MVC 路由路径中不存在的“关于”的 MVC 页面。解决方法是将所有 MVC 页面请求发送到单个 MVC 视图,您可以通过添加捕获所有 url 的路由来做到这一点


routes.MapRoute(
        name: "App",
        url: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
于 2015-09-22T23:04:41.397 回答
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()
    ];
  }
  ...
})
....
于 2014-07-02T01:55:38.537 回答
4

我在我的开发环境和生产环境中使用 apache (xampp),添加:

errorDocument 404 /index.html

到 .htaccess 为我解决这个问题。

于 2015-05-15T12:32:19.593 回答
4

对于 Grunt 和 Browsersync,请在此处使用 connect-modrewrite

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


browserSync: {
            dev: {
                bsFiles: {

                    src: [
                        'app/assets/css/*.css',
                        'app/*.js',
                        'app/controllers/*.js',
                        '**/*.php',
                        '*.html',
                        'app/jade/includes/*.jade',
                        'app/views/*.html',
               ],
            },
        options: {
            watchTask: true,
            debugInfo: true,
            logConnections: true,
            server: {
                baseDir :'./',
                middleware: [
                       modRewrite(['!\.html|\.js|\.jpg|\.mp4|\.mp3|\.gif|\.svg\|.css|\.png$ /index.html [L]'])
                ]
            },

            ghostMode: {
                scroll: true,
                links: true,
                forms: true
                    }
                }
            }
        },
于 2016-08-22T09:47:17.483 回答
3

我解决了

test: {
        options: {
          port: 9000,
          base: [
            '.tmp',
            'test',
            '<%= yeoman.app %>'
          ],
         middleware: function (connect) {
                  return [
                      modRewrite(['^[^\\.]*$ /index.html [L]']),
                      connect.static('.tmp'),
                      connect().use(
                          '/bower_components',
                          connect.static('./bower_components')
                      ),
                      connect.static('app')
                  ];
              }
        }
      },
于 2015-02-19T08:50:18.103 回答
3

我从更大的问题中回答这个问题:

当我添加 $locationProvider.html5Mode(true) 时,我的网站将不允许粘贴 url。当 html5Mode 为 true 时,如何配置我的服务器工作?

启用 html5Mode 后,您的网址中将不再使用 # 字符。# 符号很有用,因为它不需要服务器端配置。没有#,url 看起来更好,但它也需要服务器端重写。这里有些例子:

对于使用 AngularJS 的 Express Rewrites,您可以通过以下更新解决此问题:

app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});

<!-- FOR ANGULAR ROUTING -->
<base href="/">

app.use('/',express.static(__dirname + '/public'));
于 2016-02-20T02:12:44.613 回答
2

我们在 Express 中有一个服务器重定向:

app.get('*', function(req, res){
    res.render('index');
});

而且我们仍然遇到页面刷新问题,即使我们添加了<base href="/" />.

解决方案:确保您在页面中使用真实链接进行导航;不要在 URL 中输入路由,否则您将获得页面刷新。(愚蠢的错误,我知道)

:-P

于 2014-01-29T22:00:22.063 回答
2

我相信您的问题与服务器有关。关于 HTML5 模式的角度文档(在您问题中的链接中)指出:

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

我相信您需要设置从 /about 到 / 的 url 重写。

于 2013-05-15T16:35:39.947 回答
1

最后,我找到了一种通过服务器端解决此问题的方法,因为它更像是 AngularJs 本身的问题,我使用的是 1.5 Angularjs,并且在重新加载页面时遇到了同样的问题。但是在我的server.js文件中添加以下代码后,它可以节省我的时间,但这不是一个正确的解决方案或不是一个好方法。

app.use(function(req, res, next){
  var d = res.status(404);
     if(d){
        res.sendfile('index.html');
     }
});
于 2017-02-12T19:18:09.290 回答
1

我通过将以下代码片段添加到 node.js 文件中解决了这个问题。

app.get("/*", function (request, response) {
    console.log('Unknown API called');
    response.redirect('/#' + request.url);
});

注意:当我们刷新页面时,它会寻找 API 而不是 Angular 页面(因为 URL 中没有 # 标签。)。使用上面的代码,我用 # 重定向到 url

于 2018-02-21T07:48:19.570 回答
0
I solved same problem using modRewrite.  
AngularJS is reload page when after # changes.  
But HTML5 mode remove # and invalid the reload.  
So we should reload manually.
# install connect-modrewrite
    $ sudo npm install connect-modrewrite --save

# gulp/build.js
    'use strict';
    var gulp = require('gulp');
    var paths = gulp.paths;
    var util = require('util');
    var browserSync = require('browser-sync');
    var modRewrite  = require('connect-modrewrite');
    function browserSyncInit(baseDir, files, browser) {
        browser = browser === undefined ? 'default' : browser;
        var routes = null;
        if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
            routes = {
                '/bower_components': 'bower_components'
            };
        }

        browserSync.instance = browserSync.init(files, {
            startPath: '/',
            server: {
            baseDir: baseDir,
            middleware: [
                modRewrite([
                    '!\\.\\w+$ /index.html [L]'
                ])
            ],
            routes: routes
            },
            browser: browser
        });
    }
于 2015-02-21T13:48:19.987 回答
0

我发现了更好的 Grunt 插件,如果你的 index.html 和 Gruntfile.js 在同一个目录下,它就可以工作;

https://npmjs.org/package/grunt-connect-pushstate

之后在你的 Gruntfile 中:

 var pushState = require('grunt-connect-pushstate/lib/utils').pushState;


    connect: {
    server: {
      options: {
        port: 1337,
        base: '',
        logger: 'dev',
        hostname: '*',
        open: true,
        middleware: function (connect, options) {
          return [
            // Rewrite requests to root so they may be handled by router
            pushState(),
            // Serve static files
            connect.static(options.base)
          ];
        }
      },
    }
},
于 2014-01-14T10:27:55.410 回答
0

Gulp + browserSync:

通过 npm 安装 connect-history-api-fallback,稍后配置你的服务 gulp 任务

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

gulp.task('serve', function() {
  browserSync.init({
    proxy: {
            target: 'localhost:' + port,
            middleware: [ historyApiFallback() ]
        }
  });
});
于 2016-01-25T02:38:21.783 回答
0

我有这个我一直在使用的简单解决方案及其工作原理。

在 App/Exceptions/Handler.php

在顶部添加:

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

然后在render方法里面

public function render($request, Exception $exception)
{
    .......

       if ($exception instanceof NotFoundHttpException){

        $segment = $request->segments();

        //eg. http://site.dev/member/profile
        //module => member
        // view => member.index
        //where member.index is the root of your angular app could be anything :)
        if(head($segment) != 'api' && $module = $segment[0]){
            return response(view("$module.index"), 404);
        }

        return response()->fail('not_found', $exception->getCode());

    }
    .......

     return parent::render($request, $exception);
}
于 2017-03-07T15:43:06.360 回答
0

您的服务器端代码是 JAVA,然后按照以下步骤操作

第 1 步:下载 urlrewritefilter JAR单击此处 并保存以构建路径 WEB-INF/lib

第 2 步:启用 HTML5 模式 $locationProvider.html5Mode(true);

第 3 步:设置基本 URL <base href="/example.com/"/>

第 4 步:复制并粘贴到您的 WEB.XML

 <filter>
     <filter-name>UrlRewriteFilter</filter-name>
 <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

第 5 步:在 WEN-INF/urlrewrite.xml 中创建文件

 <urlrewrite default-match-type="wildcard">


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

    <!--Write every state dependent on your project url-->
    <rule>
            <from>/example</from>
            <to>/index.html</to>
        </rule>
    </urlrewrite>
于 2016-08-24T10:56:43.383 回答
0

我对使用JHipster生成的java + angular 应用程序有同样的问题。我用过滤器和属性中所有角度页面的列表解决了这个问题:

应用程序.yml:

angular-pages:
  - login
  - settings
...

AngularPageReloadFilter.java

public class AngularPageReloadFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.getRequestDispatcher("index.html").forward(request, response);
    }
}

WebConfigurer.java

private void initAngularNonRootRedirectFilter(ServletContext servletContext,
                                              EnumSet<DispatcherType> disps) {
    log.debug("Registering angular page reload Filter");
    FilterRegistration.Dynamic angularRedirectFilter =
            servletContext.addFilter("angularPageReloadFilter",
                    new AngularPageReloadFilter());
    int index = 0;
    while (env.getProperty("angular-pages[" + index + "]") != null) {
        angularRedirectFilter.addMappingForUrlPatterns(disps, true, "/" + env.getProperty("angular-pages[" + index + "]"));
        index++;
    }
    angularRedirectFilter.setAsyncSupported(true);
}

希望,这会对某人有所帮助。

于 2015-10-28T14:06:15.103 回答