programing

정적 웹 페이지용 AngularJS SEO (S3 CDN)

i4 2023. 2. 25. 19:45
반응형

정적 웹 페이지용 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

반응형