정적 웹 페이지용 AngularJS SEO (S3 CDN)
각도 조절을 위해 SEO를 개선할 수 있는 방법을 찾고 있습니다.Amazon S3와 같은 CDN에서 호스팅되는 JS 애플리케이션(백엔드가 없는 단순한 스토리지).대부분의 해결책이 있어, 팬텀JS, prerender.io, seo.disc 등에서는 백엔드에 의존하여 인식합니다.?_escaped_fragment_
크롤러가 생성한 후 다른 곳에서 관련 페이지를 가져오는 URL.grunt-html-snapshot에서도 스냅샷 페이지를 미리 생성하더라도 최종적으로 이 작업을 수행해야 합니다.
이 솔루션은 기본적으로 클라우드 플레어를 리버스 프록시로 사용하는데, 이 서비스가 제공하는 보안 장치 등의 대부분이 정적 사이트에 대해 완전히 장황하다는 점을 고려하면 다소 낭비일 수 있습니다.여기서 제안하는 리버스 프록시를 직접 설정하는 것도 i) 모든 Angular를 라우팅해야 하기 때문에 문제가 있는 것 같습니다.JS 앱은 하나의 프록시 서버를 통해 사용할 정적 html이 필요합니다.이는 잠재적으로 성능을 저해할 수 있으며 ii) 각 앱에 대해 별도의 프록시 서버를 설정하는 것이 좋습니다.그때 백엔드를 설정하는 것도 좋지만, 이 경우 현재 작업하는 규모로는 감당할 수 없습니다.
이렇게 하는 것이 있습니까, 아니면 정적으로 호스트되는 AngularSEO가 뛰어난 JS 앱은 기본적으로 구글이 크롤러를 업데이트하기 전까지는 불가능합니까?
John Conde의 코멘트에 따라 웹 마스터에 재투고.
사실 이것은 매우 귀찮은 작업입니다만, SEO가 Angular와 잘 동작하도록 할 수 있었습니다.JS SPA 사이트(AWS S3에서 호스팅됨)는 http://www.jobbies.co/에 있습니다.주요 아이디어는 콘텐츠를 미리 생성하여 HTML에 채우는 것입니다. 페이지가 로드될 때 템플릿은 계속 로드되고 사전 렌더링된 콘텐츠는 교체됩니다.
제 솔루션에 대한 자세한 내용은 http://www.ericluwj.com/2015/11/17/seo-for-angularjs-on-s3.html,에서 보실 수 있습니다.다만, 많은 조건이 있습니다.
다음은 S3와 같은 스토리지 서비스에서 멋진 URL(no #) 및 빌드 후 간단한 명령으로 모든 것을 grunt로 SEO 친화적으로 만드는 방법에 대한 전체 개요입니다.
grunt seo
아직 해결방법의 퍼즐이지만, 효과가 있고, 당신이 할 수 있는 최선의 방법입니다.영감을 준 @ericluwj와 그의 블로그 포스트에 감사드립니다.
개요
목표와 URL 구조
목표는 각진 앱에 상태당 1개의 html 파일을 만드는 것입니다.유일한 주요 전제는 html5history를 사용하여 URL에서 '#'을 삭제하고(이것을 수행해야 함) 모든 경로가 절대 또는 각도 상태를 사용한다는 것입니다.그렇게 하는 방법을 설명하는 게시물이 많이 있습니다.
URL은 다음과 같은 후행 슬래시로 끝납니다.http://yourdomain.com/page1/
개인적으로 저는 http://yourdomain.com/page1(후행 슬래시 없음)도 목적지에 도착하도록 확인했지만, 여기서는 주제를 벗어났습니다.또한 모든 언어가 다른 상태와 URL을 가지고 있는지 확인했습니다.
SEO 로직
당사의 목표는 누군가가 http 요청을 통해 귀하의 웹사이트에 접속할 때 다음과 같이 하는 것입니다.
- 검색 엔진 크롤러인 경우: 필요한 html이 포함된 페이지에 계속 표시합니다.페이지에는 각도 로직(예를 들어 앱을 기동하기 위한 것)도 포함되어 있습니다만, 크롤러는 그것을 읽을 수 없기 때문에, 의도적으로 당신이 제공한 html에 고정되어 그것을 색인화합니다.
- 일반인이나 인텔리전트 머신의 경우 : 각도가 활성화 되어 있는지 확인하고 생성된html을 지우고 정상적으로 앱을 기동합니다.
grunt 태스크
다음으로 grunt 태스크에 대해 설명하겠습니다.
//grunt plugins you will need:
grunt.loadNpmTasks('grunt-prerender');
grunt.loadNpmTasks('grunt-replace');
grunt.loadNpmTasks('grunt-wait');
grunt.loadNpmTasks('grunt-aws-s3');
//The grunt tasks in the right order
grunt.registerTask('seo', 'First launch server, then prerender and replace', function (target) {
grunt.task.run([
'concurrent:seo' //Step 1: in parrallel launch server, then perform so-called seotasks
]);
});
grunt.registerTask('seotasks', [
'http', //This is an API call to get all pages on my website. Skipping this step in this tutorial.
'wait', // wait 1.5 sec to make sure that server is launched
'prerender', //Step 2: create a snapshot of your website
'replace', //Step 3: clean the mess
'sitemap', //Create a sitemap of your production environment
'aws_s3:dev' //Step 4: upload
]);
순서 1: 동시 로컬서버를 기동합니다.seo
먼저 로컬 서버(grunt serve 등)를 기동하여 웹 사이트의 스냅샷을 작성해야 합니다.
//grunt config
concurrent: {
seo: [
'connect:dist:keepalive', //Launching a server and keeping it alive
'seotasks' //now that we have a running server we can launch the SEO tasks
]
}
순서 2: grunt preender를 사용하여 웹 사이트의 스냅샷을 만듭니다.
그룬트 프레렌더 플러그인을 사용하면 팬텀을 사용하여 모든 웹 사이트의 스냅샷을 만들 수 있습니다.JS. 이 경우 방금 시작한 로컬 호스트 웹 사이트의 모든 페이지를 스냅샷으로 찍고자 합니다.
//grunt config
prerender: {
options: {
sitePath: 'http://localhost:9001', //points to the url of the server you just launched. You can also make it point to your production website.
//As you can see the source urls allow for multiple languages provided you have different states for different languages (see note below for that)
urls: ['/', '/projects/', '/portal/','/en/', '/projects/en/', '/portal/en/','/fr/', '/projects/fr/', '/portal/fr/'],//this var can be dynamically updated, which is done in my case in the callback of the http task
hashed: true,
dest: 'dist/SEO/',//where your static html files will be stored
timeout:5000,
interval:5000, //taking a snapshot of how the page looks like after 5 seconds.
phantomScript:'basic',
limit:7 //# pages processed simultaneously
}
}
순서 3: 그룬트 교환으로 지저분한 것을 청소합니다.
미리 렌더링된 파일을 열면 크롤러는 작동하지만 사람은 작동하지 않습니다.크롬을 사용하는 사람의 경우 지침이 두 번 로드됩니다.따라서 angular가 활성화되기 전에(즉, 헤드 직후) 지능형 브라우저를 홈 페이지로 리디렉션해야 합니다.
//Add the script tag to redirect if we're not a search bot
replace: {
dist: {
options: {
patterns: [
{
match: '<head>',
//redirect to a clean page if not a bot (to your index.html at the root basically).
replacement: '<head><script>if(!/bot|googlebot|crawler|spider|robot|crawling/i.test(navigator.userAgent)) { document.location = "/#" + window.location.pathname; }</script>'
//note: your hashbang (#) will still work.
}
],
usePrefix: false
},
files: [
{expand: true, flatten: false, src: ['dist/SEO/*/**/*.html'], dest: ''}
]
}
또한 angular가 시작되기 전에 생성된 모든 html 디렉티브를 클리어하는 UI 뷰 요소의 index.html에 이 코드가 있는지 확인하십시오.
<div ui-view autoscroll="true" id="ui-view"></div>
<!-- this script is needed to clear ui-view BEFORE angular starts to remove the static html that has been generated for search engines who cannot read angular -->
<script>
if(!/bot|googlebot|crawler|spider|robot|crawling/i.test( navigator.userAgent)) { document.getElementById('ui-view').innerHTML = ""; }
</script>
4단계: aws에 업로드
먼저 빌드가 포함된 dist 폴더를 업로드합니다.그런 다음 미리 렌더링하고 업데이트한 파일로 덮어씁니다.
aws_s3: {
options: {
accessKeyId: "<%= aws.accessKeyId %>", // Use the variables
secretAccessKey: "<%= aws.secret %>", // You can also use env variables
region: 'eu-west-1',
uploadConcurrency: 5, // 5 simultaneous uploads
},
dev: {
options: {
bucket: 'xxxxxxxx'
},
files: [
{expand: true, cwd: 'dist/', src: ['**'], exclude: 'SEO/**', dest: '', differential: true},
{expand: true, cwd: 'dist/SEO/', src: ['**'], dest: '', differential: true},
]
}
}
이상입니다. 해결 방법이 있습니다! 사람과 봇 모두 웹 앱을 읽을 수 있습니다.
만약 당신이 ng-flash를 흥미로운 방법으로 사용한다면 좋은 해결책이 있을 것이다.
저도 시도해 본 적은 없지만 이론상으로는 효과가 있을 겁니다
이 솔루션은 CSS에 크게 의존하지만 완벽하게 적합합니다.예를 들어 각도 앱에는 - 인덱스(경로 이름: #/) - 정보(경로 이름: #/about) - 연락처(경로 이름: #/contact)의 세 가지 상태가 있습니다.
인덱스 베이스 케이스도 넣을 수 있지만 까다로우므로 일단 생략하겠습니다.
HTML을 다음과 같이 만듭니다.
<body>
<div ng-app="myApp" ng-cloak>
<!-- Your whole angular app goes here... -->
</div>
<div class="static">
<div id="about class="static-other">
<!-- Your whole about content here... -->
</div>
<div id="contact" class="static-other">
<!-- Your whole contact content here... -->
</div>
<div id="index" class="static-main">
<!-- Your whole index content here... -->
</div>
</div>
</body>
(인덱스 케이스를 더 멋지게 만들고 싶다면 마지막에 넣는 것이 중요합니다.)
다음으로 CSS를 다음과 같이 만듭니다.-
[ng-cloak], .static { display: none; }
[ng-cloak] ~ .static { display: block; }
어쨌든 그것만으로도 충분할 거야.mg-cloak 지시어는 각도가 로드되지 않을 때 각도가 있는 앱을 숨긴 상태로 유지하고 대신 정적 내용을 표시합니다.Google은 HTML에서 정적 콘텐츠를 가져옵니다. 보너스로서 최종 사용자는 각도 부하를 받는 동안 정적 콘텐츠를 잘 볼 수 있습니다.
그런 다음 CSS에서 :target 의사 셀렉터를 사용하기 시작하면 창의력을 높일 수 있습니다.Static 콘텐츠에서 실제 링크를 사용할 수 있지만 다양한 ID에 링크할 수 있습니다.따라서 #index div에서 #about 및 #contact에 대한 링크가 있는지 확인합니다.링크에 '/'이(가) 없습니다.HTML ID는 슬래시로 시작할 수 없습니다.
다음으로 CSS를 다음과 같이 만듭니다.
[ng-cloak], .static { display: none; }
[ng-cloak] ~ .static { display: block; }
.static-other {display: none;}
.static-other:target {display: block;}
.static-other:target ~ .static-main {display: none;}
각도 시작 전에 ROUTING을 사용하여 완전히 작동하는 정적 앱을 사용할 수 있습니다.
또, 각도 기동시에 #about를 #about으로 자동 변환하는 스마트한 조작으로, 조작성은 전혀 저하되지 않습니다.
또한 SEO 문제도 물론 완전히 해결되었습니다.항상 서버를 설정해 왔기 때문에 아직 이 기술을 사용하지 않았습니다만, 이것이 어떻게 기능하는지에 매우 관심이 있습니다.
이게 도움이 됐으면 좋겠다.
AWS는 Lambda@Edge를 서비스로 제공하고 있기 때문에 불평이나 다른 문제 없이 이 문제를 해결할 수 있습니다.(최소한 기본적인 것은)
Lambda@Edge를 시도했는데 예상대로 동작했습니다.저 같은 경우에는 Lambda@Edge에서 모든 루트를 "/"로 설정했습니다(css, images 등 s3에 있는 파일은 제외).
제가 설정한 람다의 이벤트는 "viewerRequest"이며, 다음은 코드입니다.
'use strict';
exports.handler = (event, context, callback) => {
console.log("Event received is", JSON.stringify(event));
console.log("Context received is", context);
const request = event.Records[0].cf.request;
if (request.uri.endsWith(".rt")) {
console.log("URI is matching with .rt, the URI is ", request.uri);
request.uri = "/";
} else {
console.log("URI is not ending with rt so letting it go URI is", request.uri);
}
console.log("Final request URI is", request.uri);
callback(null, request);
};
Cloudwatch 로그는 요청을 처리하는 엣지 위치에 가까운 Cloudwatch 영역에 저장되므로 확인하기가 거의 어렵습니다.
예: 이 Lambda는 us-east용으로 배치/작성되었지만 싱가포르에서 클라우드 프런트에 접속할 때 ap-south 지역에서 볼 수 있습니다.구글 웹마스터 도구 'Fetch as google' 옵션에서 확인해보니 예상대로 페이지가 렌더링되고 표시됩니다.
해결책을 찾기 위해 며칠을 기다렸어요내가 아는 한 그 문제에 대한 좋은 해결책은 없다.파이어베이스가 최종적으로 사용자-에이전트 리다이렉트를 활성화 할 수 있기를 바랍니다.만약 당신이 돈이 있다면 MaxCDN Enterprise를 사용할 수 있습니다.이들은 사용자 에이전트에 의한 리다이렉트를 포함하는 Edge Rules를 제공합니다.
https://www.maxcdn.com/features/rules/
언급URL : https://stackoverflow.com/questions/23043336/angularjs-seo-for-static-webpages-s3-cdn
'programing' 카테고리의 다른 글
['type aliases'는 .ts 파일에서만 사용할 수 있습니다] (0) | 2023.02.25 |
---|---|
스프링 데이터: JPA 저장소 findAll()을 사용하여 목록 대신 *Map을 반환하시겠습니까? (0) | 2023.02.25 |
안정적 POST 대응을 위한 '베스트' 프랙티스 (0) | 2023.02.25 |
Reactjs를 사용하여 입력 필드를 지우시겠습니까? (0) | 2023.02.25 |
axios와 함께 bearer 토큰 전송 (0) | 2023.02.25 |