angular1.x使用html5模式去掉#

在Angular1.x里,它默认使用’#’在根目录后面,然后使用angular-router或ui-router来配置路由。例如你的地址会变成这样:

1
http://localhost:8100/#/tab/dash

但是,这样的地址,有很多不方便的地方。首先,我们在网上发布链接的时候经常需要带上分享渠道等信息,这样的路径后面加参数就很不方便,不管是加到后面:

1
http://localhost:8100/#/tab/dash?channel_id=ABAS201

还是加到前面

1
http://localhost:8100/?channel_id=ABAS201#/tab/dash

都很不方便,比如用angular的$location服务的seach()方法获取参数,获取path等有可能有问题。

至于搜索引擎,因为我们的index页面里面什么都没有,内容都是框架加载的,如果不做其他的处理,angular的应用要让搜索引擎搜索到也是不可能。而且,这样的路径http://localhost:8100/#/tab/dash,即使井号后面路径不一样,搜索引擎也会把它当成同一个页面。

其实这个井号也是可以去掉的,只是需要代码里、服务器端一起修改和配置。

添加base

首先在index.html页面里面,在开头meta部分的下面,添加base设置:

1
<base href="/" />

这个base的意思,就是这个应用的根目录。假设我们开发的是一个admin端的管理系统,用户输入域名,如http://www.mydomain.com打开的是网站系统,当用户输入http://www.mydomain.com/admin打开是是管理系统。那这个管理系统的base就是admin。
这个base的设置,会影响我们的左右文件的引用路径,例如,index页面里面的一个js:

1
<script src="js/app.js"></script>

最终的请求url就是http://www.mydomain.com/admin/js/app.js

当然,你也可以不管我最终部署的url,把这个base都设置成’/‘,这样我们在测试的时候,就用http://www.mydomain.com或者http://localhost:8100打开应用。当我们部署到服务器(例如nginx)上时,再通过配置nginx的代理,让我们的应用能够从http://www.mydomain.com/admin这个路径访问。

启用html5

下面,就是修改app.js,在angular的config方法里,启用html5模式:

1
2
3
4
.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
// 其他路由等配置
})

修改完这个以后,当我们打开http://localhost:8100,跳转到默认首页的时候,路径里面就不会有’#’了。例如:http://localhost:8100/app/home

但是,如果我们在打开这个页面http://localhost:8100/app/home的时候,刷新浏览器,就会提示出错:’Cannot GET /tab/dash’。这是因为,刷新上面的网页的时候,这个url的请求http://localhost:8100/app/home,发送到服务器的时候,服务器就会从项目的根路径开始,查找目录’app/home’下面的index文件,但是,这个文件显然是不存在的,就会出现上面的404错误。
而直接访问http://localhost:8100/能跳转到主页是因为服务器先返回根目录的index.html文件,浏览器打开以后,angular加载了应用,再按照理由配置跳转到那个首页。
除非我们每次访问都从根目录进去,否则,就需要修改服务器的配置。

配置开发环境

我们在开发angular应用时,往往通过gulp等工具使用自动刷新,按上面说的,在某一个页面上自动刷新,就会出错了,为了开发方便,我需要修改我们的开发环境,让他能够正常刷新。

通过上面的分析,我们知道,无法刷新,是因为:

服务器接收到url请求http://localhost:8100/app/home的时候,服务器就会从项目的根路径开始,查找目录’app/home’下面的index文件,但是,这个文件显然是不存在的,就会出现上面的404错误。

那我们的解决办法就是,当接收到的url的path部分是’/app/home’的时候,把他重定向到’/‘,好在已经有现成的库(connect-history-api-fallback)帮我们实现了这个功能。如果你用的gulp可以用下面的方式,添加一个中间件就可以:

1
2
3
4
5
6
7
8
9
10
var historyApiFallback = require('connect-history-api-fallback');
gulp.task('serve', function() {
browserSync.init({
server: {
baseDir: "app",
middleware: [ historyApiFallback() ]
}
});
});

配置nginx

对于angular的应用而言,他就是一些静态文件,所以,我们一般使用nginx这样的web服务器去部署。
为了解决上面的刷新问题,我们同样通过nginx的代理来配置:

1
2
3
4
5
location / {
root /home/theuser/the-angular-app/dist;
index index.html;
try_files $uri $uri/ /index.html;
}

下面的’try_files $uri $uri/ /index.html;’意思就是,对于一个url请求,先尝试这个路径’$uri’,如果没有再尝试’$uri/‘,最后再尝试根目录的’/index,html’。
对于一个上面的请求:http://www.mydomain.com/app/home,它会先在根目录下查找’/app/home’,在查找’/app/home/index.html’文件(或者index.php等)。没找到的话,就会打开根目录的index.html,同时’app/home’会带过去,所以这个应用的index文件就会打开,里面的angular开始加载,并通过url后面的’app/home’找到相应的路由帮打开。

坚持原创技术分享,您的支持将鼓励我继续创作!