AngularJs自学心得
1.angularjs的SEO問題解決方案
我的前端用到angularjs,服務器用到nginx。?
大體流程:
nginx服務器檢測到爬蟲訪問,跳轉到專門的url,此url是angularjs已經渲染過后的頁面。非常的簡單。
a).首先是angularjs的渲染問題
angular添加一個模塊‘seo’,引入文件 angular-seo.js文件(附件中有)。
? <script src="js/app/angular-seo.js"></script>
? angular.module('app', ['ng', 'seo']);
? 然后你可以在每個controller中,覺得頁面差不多已經創建好之后調用 $scope.htmlReady()(就是數據請求完成之后,隨便你放哪里)。
? 然后用phantomjs進行頁面的渲染,安裝完成之后(自己百度怎么安裝,很簡單),用下面代碼進行調用。
? phantomjs --disk-cache=no /path/xxxxxx...../angular-seo-server.js 9001 http://localhost:8080
? 這個就是開啟9001端口,調用angular-seo-server.js文件(附件中有)獲得8080端口渲染的頁面,渲染完成標志就是上面的$scope.htmlReady()。?
? 那localhost:9001這個url地址就是爬蟲應該訪問的地址。
? b).讓nginx知道爬蟲進行訪問
? 在實際頁面head中加入下面代碼
? <meta name="fragment" content="!" >
爬蟲看到這段代碼之后,它會知道這個頁面有動態的javascript需要爬取。它會在你的url中添加?_escaped_fragment_=/,這個標志就是讓nginx知道是爬蟲進行訪問了?
? nginx中進行下面配置
? if ($args ~ _escaped_fragment_) { #這里面寫你們的處理代碼 rewrite ^ /bot/ ; }
? 還有angularjs的路徑時 xxx/#/xxxx這種形式,爬蟲是沒辦法識別 /#/之后的內容的,所以我們需要改成 xxxxx/!#/xxxxxx這種形式,很簡答,添加下面代碼即可
? angular.config(['$routeProvider','$locationProvider', function ($routeProvider, $locationProvider,$httpProvider) { $routeProvider.when('/index', { templateUrl: '', controller: '' }); $locationProvider.hashPrefix('!'); }]);
? c).跳轉url,地址我們已經有了,即為localhost:9001,nginx配置如下(與前面的if語句代碼呼應)?
? location /bot/ { proxy_pass http://localhost:9001/;?proxy_http_version 1.1; proxy_set_header Host $host:80; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forworded-For $proxy_add_x_forwarded_for; proxy_set_header Via "nginx"; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
? 注意:proxy_pass中的url地址一定要以“/"結尾,就是這個東西,我調試了大半天才搞出來,因為沒有“\”則方位地址會變成 xxxx/bot/?_escaped_fragment_=/xxxxx,這樣是不對的,應該是xxxx/?_escaped_fragment_=/xxxxx。
? 這樣就大功告成了。以后只要在適當的地方添加$scope.htmlReady()即可。ps:經過測試貌似不需要$scope.htmlReady()
? d).測試可以使用curl
? 例如本地測試 curl localhost:9001,最終測試 curl host/?_escaped_fragment_=/ ,這會返回頁面內容,查看一下是否渲染完成即可。
? 測試:監聽時,url沒帶上相對路徑(https://www.hansap.com/XXX)
解決辦法:
? ? 通過github查到phantomJs官網,查看API,request包含的信息。
?
?
?可以在angular-seo-server.js內把頭部信息打印出來。既然如此,如果想對路徑(/protal/product/1000)沒帶過來,那就可以在nginx端做處理。把爬蟲的請求路勁塞到頭部信息內(real_url?$request_uri),然后在phontomJs端用request取到。
?
?
? ? nginx配置:?
? ? server{
? ? ? ? ......
? ? ? ? ?if?(?$http_user_agent?~*?"qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo!?Slurp|Yahoo!?Slurp?China|YoudaoBot|Sosospider|Sogou?spider|Sogou?web?spider|MSNBot|ia_archiver|Tomato?Bot|HaosouSpider|360Spider|Bingbot"?)?{
????????????????rewrite?^?/bot/?;
? ? ? ? ?}
? ? ? ? location?/bot/?{
????????????????proxy_pass?http://192.168.11.179:9001/;
????????????????proxy_http_version?1.1;
????????????????proxy_set_header?real_url?$request_uri; ? ?//請求想對路勁
????????????????proxy_set_header?Host?$host:80;
????????????????proxy_set_header?X-Real-IP?$remote_addr;
????????????????proxy_set_header?X-Forworded-For?$proxy_add_x_forwarded_for;
????????????????proxy_set_header?Via?"nginx";
????????????????proxy_set_header?Upgrade?$http_upgrade;
????????????????proxy_set_header?Connection?"upgrade";
????????}
? ? }
?解決思路:
? ? a).定位問題
? ? ? ? a.在angular-seo-server.js端打印出request.url每次都為'/'
? ? ? ? 問題為nginx重定向時,URL地址的想對路勁沒帶過來
? ? b).解決問題
? ? ? ? a.在phantomJsAPI中查出request的信息,可以查到頭部相關信息,這就簡單了,只需要在nginx重定向時,把想對路徑加到頭部信息即可
? ? ? ? b.nginx中配置?proxy_set_header?real_url?$request_uri;
? ? ? ? ? ??real_url(自定義名稱)?$request_uri(nginx全局變量:想對路徑);
? ? ? ? c.phantomJs端取到想對路徑即可
?
2.優化AngularJs的URL # 號問題
a).在index.html頁面添加<base?href="/">
b).在路由js內添加
? ? .config(
???????? ['$stateProvider',?'$urlRouterProvider','$locationProvider',
???????????? function($stateProvider,?$urlRouterProvider,$locationProvider)?{
? ? ? ? ? ? ? ? ......
? ? ? ? ? ? ? ? $locationProvider.html5Mode(true);
? ? ? ? ? ? ? ??/*var?mode?=?{enabled:true,requireBase:false,rewriteLinks:true};
????????????????$locationProvider.html5Mode(mode);
? ? ? ? ? ? ? ??$locationProvider.html5Mode(true).hashPrefix('!');*/
? ? ? ? ? ? }
???????? ]
???? );
c).定義前臺過濾器(Filter)
? ??<filter>
????????<filter-name>pageFilter</filter-name>
????????<filter-class>com.whicloud.filter.PageFilter</filter-class>
????????<init-param>
????????????<param-name>prefix</param-name>
????????????<param-value>/ajax;/buildrequest;/download;/upload</param-value>
????????</init-param>
????????<init-param>
????????????<param-name>suffix</param-name>
????????????<param-value>.do;.action</param-value>
????????</init-param>
????????<init-param>
????????????<param-name>include</param-name>
????????????<param-value>.</param-value>
????????</init-param>
????</filter>
?
????<filter-mapping>
????????<filter-name>pageFilter</filter-name>
????????<url-pattern>*</url-pattern>
????</filter-mapping>
?
? ??public?class?PageFilter?implements?Filter?{
? private?final?static?Logger?log?=?LoggerFactory.getLogger(PageFilter.class);
?
????private?final?static?List<String>?PREFIX_MATCH?=?new?ArrayList<>();
????private?final?static?List<String>?SUFFIX_MATCH?=?new?ArrayList<>();
????private?final?static?List<String>?INCLUDE_MATCH?=?new?ArrayList<>();
?
????@Override
????public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
????????log.info("初始化page?filter");
?
????????//前綴
????????String?prefix?=?filterConfig.getInitParameter("prefix");
????????if?(!StringUtils.isEmpty(prefix))?{
????????????String[]?prefixs?=?prefix.split(";");
????????????PREFIX_MATCH.addAll(Arrays.asList(prefixs));
????????}
?
????????//后綴
????????String?suffix?=?filterConfig.getInitParameter("suffix");
????????if?(!StringUtils.isEmpty(suffix))?{
????????????String[]?suffixs?=?suffix.split(";");
????????????SUFFIX_MATCH.addAll(Arrays.asList(suffixs));
????????}
?
????????//包含
????????String?include?=?filterConfig.getInitParameter("include");
????????if?(!StringUtils.isEmpty(include))?{
????????????String[]?includes?=?include.split(";");
????????????INCLUDE_MATCH.addAll(Arrays.asList(includes));
????????}
?
????????log.info("初始化page?filter完成");
????}
?
????private?boolean?isMatch(String?uri)?{
????????for?(String?prefix?:?PREFIX_MATCH)?{
????????????if?(uri.startsWith(prefix))
????????????????return?true;
????????}
?
????????for?(String?suffix?:?SUFFIX_MATCH)?{
????????????if?(uri.endsWith(suffix))
????????????????return?true;
????????}
?
????????for?(String?include?:?INCLUDE_MATCH)?{
????????????if?(uri.indexOf(include)?>=?0)
????????????????return?true;
????????}
????????return?false;
????}
????@Override
????public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?chain)?throws?IOException,?ServletException?{
????????HttpServletRequest?req?=?(HttpServletRequest)?request;
????????String?root?=?req.getContextPath();
????????String?uri?=?req.getRequestURI();
????????uri?=?uri.substring(root.length());
?
????????if?(isMatch(uri))?{
????????????chain.doFilter(request,?response);
????????}?else?{
????????????req.setAttribute("root",?root);
????????????req.getRequestDispatcher("/index.html").forward(request,?response); ? ? ? ?//服務器端重定向到首頁,前臺angularJs會自動吧路由狀態帶上,并解析
????????}
????}
????@Override
????public?void?destroy()?{
????}
? ? }
?
轉載于:https://www.cnblogs.com/yield/p/8465950.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的AngularJs自学心得的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库特点
- 下一篇: 20179214 《网络攻防实践》第五周