最近,接到反饋說百度統計無法對#號后的URL進行分析,需要前端這邊去掉URL中的#,下面我分享一下這個問題的處理過程。
1、Angular2+ 路由策略
1.1 HashLocationStragegy
通過hash實現,當url的hash發生改變時,觸發hashchange注冊的回調(低版本的瀏覽器沒有hashchange事件,通過輪回檢測url實現),回調中去進行不同的操作,進行不同的內容展示。使用hash來實現的話,URI規則中要帶上#,路由中#后邊的內容就是hash,而我們常說的錨點嚴格來說應該是頁面中的a[name]等元素。url格式如下:
http://121.201.95.249/#/home
適用於基於錨點標記的路徑,比如/#/concat,/#/about,后端只需要配置一個根路由即可。
1.2 PathLocationStrategy
通過history實現,angular2的默認策略,也就是HTML5路由,使用這個路由的常規路徑就是/concat,/about,不帶#。url格式如下:
http:// 121.201.95.249/home
這種策略需要后台配置支持,因為我們的應用是單頁面應用,如果后台沒有正確的配置,當用戶在瀏覽器從http: // 121.201.95.249/concat跳轉到http: // 121.201.95.249/about或者刷新時就會返回404,需要在服務端里面覆蓋所有的路由情況(后端可以通過nginx或者apache等配置)。
2、如何去除#
主要分兩部分,前端路由策略模式修改,以及后端服務器配置。我的項目中后端服務器用的是Apache,下面我將以這個為例子進行解析。
2.1 前端修改
index.html文件:
在head里設置base-href,如果沒有設置,當通過“深鏈接”進入該應用時,瀏覽器就不能正確的加載網站資源(圖片、CSS、腳本)。如下:
<base href="/">
base-href,主要是設置你的項目訪問的根目錄,如果你的項目是放在服務器某一文件夾里面的,比如通過http: // 121.201.95.249/myApp/home才訪問到你的項目,那么根目錄設置如下:
<base href="/myApp/">
app.module.ts文件:
import { ROUTER_CONFIG } from './app.routes.ts';
@NgModule({
imports: [
...
RouterModule.forRoot(routes)
// RouterModule.forRoot(routes, { useHash: true } ) 這樣寫是帶#的
],
})
app.routes.ts文件:
import { NgModule } from '@angular/core';
import { Routes } from '@angular/router';
export const routes: Routes = [
{
...
}
];
設置到這里便可以實現去掉“#”跳轉了,但是每次刷新或者直接輸鏈接進到頁面時會報錯提示:404找不到頁面。因此,我們需要后端配合做路由重定向。
2.2 后端服務器配置
Apache配置文件修改:
RewriteEngine On
# 如果請求的是現有資源,則按原樣執行
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# 如果請求的資源不存在,則使用index.html
RewriteRule ^ /index.html
Apache Rewrite配置就是用來設置重定向的,上面5行(不包括#的注釋內容)配置內容的意思是:
第一行: 將RewriteEngine引擎設置為on,就是讓url重寫生效,用於開啟rewrite功能;
第二行: RewriteCond是指令定義了一個規則的條件,即在一個RewriteRule指令之前有一個或多個RewriteCond指令。 條件之后的重寫規則(RewirteRule)僅在當前URI與pattern匹配並且符合這些條件的時候才會起作用。上面的匹配規則意思是,如果文件存在,就直接訪問文件,執行第四行重寫規則(RewirteRule)停止分析,否則執行第三行
第三行: 如果目錄存在就直接訪問目錄,然后執行第四行重寫規則(RewirteRule)停止分析
第四行: 表明當前規則是最后一條規則,停止分析后面的規則
第五行: 意思是把請求發送到index.html;當第二第三條規則都不滿足的時候,就不執行第四行的RewriteRule,直接執行第五行的RewriteRule,把請求發送到index.html,實現重定向
想對規則進行更多了解,請查看這篇文章(https://www.jb51.net/article/82158.htm) ,下面我說一下Apache的配置步驟。
大家如果是在集成環境比如uwamp,wamp或者Apache1可以打開配置文件httpd.conf,如果是Apache2則打開配置文件/etc/apache2/apache2.conf,進行修改。
(1) 引入重寫rewrite模塊
如果是集成環境或者Apache1,找到#LoadModule rewrite_module modules/mod_rewrite.so,去掉前面的”#”:
LoadModule rewrite_module modules/mod_rewrite.so
如果是Apache2的話,執行命令加載Rewrite模塊:
a2enmod rewrite
執行后,會提示OK和重啟Apache命令(/etc/init.d/apache2 restart)。
(2)添加配置規則
<VirtualHost *:80>
ServerName myApp
DocumentRoot /www/myApp
<Directory /www/myApp>
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html [L]
</Directory>
</VirtualHost>
這里的“/www/myApp”是存放項目的根目錄路徑。
可能前端的同學使用集成環境的比較多,如果不能完全理解的話,我拿uwamp環境做例子解析一下。
index.html文件:
<base href="/dist">
項目打包到dist文件中,然后把dist文件內容放到www下面,也就是www/dist里面就是打包后的內容index.html以及各種js包,然后打開配置文件httpd.conf:
引入重寫rewrite模塊,找到#LoadModule rewrite_module modules/mod_rewrite.so,去掉前面的”#”:
添加規則:
<VirtualHost *:80>
DocumentRoot "{DOCUMENTPATH}/"
<Directory "{DOCUMENTPATH}/dist">
Options FollowSymLinks
AllowOverride All
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html
</Directory>
</VirtualHost>
(3)重啟Apache
Apache1重啟
# service httpd restart
Apache2的重啟:
# /etc/init.d/apache2 restart
或者
# service apache2 restart
uwamp環境的重啟,打開uwamp界面,先點擊關閉,然后再開啟即可:
(4)刷新頁面,會發現不再是404報錯了,設置成功。設置過程中需要留意的幾個坑是:
- 沒有設置base-href,或者設置錯誤
- Rewrite模塊沒有引入
- 忘記重啟Apache