Angular에서 사전 렌더링 — 단일 다국어 빌드

오늘 우리는 Replace i18n Package in Angular에 대한 이전의 노력을 계속할 것이며 Express 서버를 조정하여 언어당 여러 정적 페이지를 생성할 것입니다. 계획은 다음과 같습니다.
  • 다국어 지원을 위해 적응, URL 기반
  • APP_BASE_URL 지원 테스트
  • 쿠키 기반 앱에 대해 실행되도록 조정
  • Firebase Netlify 및 Surge 지원 살펴보기

  • 다국어 URL 기반 앱



    끝을 염두에 두고 계획할 때 언어 폴더가 다른 동일한 경로를 만들어야 하므로 /client/projects/index.html 내부에 있어야 합니다 /client/en/projects/index.html . 이를 위해서는 지원되는 모든 언어를 반복하도록 가져오기 모듈을 조정해야 합니다.

    참고: 여러 빌드가 있는 경우(기본 Angular 동작에 따라) 출력 디렉터리가 교체됩니다. 예: /en/static/projects/index.html
    // host/prerender/fetch.js
    // example of supported languages which probably should be in a config file
    const languages = ['en', 'ar', 'tr'];
    
    // adapt by accepting language
    async function renderToHtml(lang, route, port, outFolder) {
      // adapt to call fetch with the language prefixed in URL
      const response = await fetch(`http://localhost:${port}/${lang}/${route}`);
      // ...
    
      // adapt to place in /client/static/en/route/index.html
        const d = `${outFolder}${lang}/${route}`;
        // ...
    }
    
    module.exports = async (port) => {
        // ...
      // adapt to loop through languages
      for (const lang of languages) {
        for (const route of routes) {
          await renderToHtml(lang, route, port, prerenderOut);
        }
      }
    };
    
    base href 값이 URL driven apps에서 예상되는 동작인 올바른 언어로 설정되어 있는 한 우리가 가지고 있던 Express 규칙을 변경할 필요가 없습니다.

    module.exports = function (app) {
        // this rule holds, as long as the base href is set to the right language folder
        // for example "/en/"
      app.use('/', express.static(rootPath + 'client/static'));
        // ... other routes
    }
    

    서버를 실행하고 http://localhost:port/en/projects로 이동한 다음 자바스크립트를 비활성화하고 테스트합니다. 파일의 정적 버전이 표시되어야 합니다.

    fetch script is on StackBlitz .

    APP_BASE_HREF 토큰


    base href가 루트/로 설정되어 있다는 점을 제외하면 URL 기반 애플리케이션과 정확히 같습니다. 적응이 필요하지 않습니다. Using Angular APP_BASE_HREF에서 이 솔루션에 대해 읽어보세요.

    쿠키 기반 앱



    쿠키 값을 기반으로 하는 단일 빌드 앱은 권장되지 않습니다. 그럼에도 불구하고 파헤쳐 보자. 두 가지를 조정해야 합니다.
  • 사전 렌더링 전에 쿠키를 설정합니다 fetch (허용되지 않음)
  • 사이트를 제공하기 전에 실제 파일을 확인하십시오
  • .

    가져오기에서는 쿠키 헤더를 설정할 수 없지만 다른 헤더를 설정하도록 해결할 수 있습니다. 그런 다음 언어 미들웨어에서 다른 요소와 함께 해당 헤더 값을 확인합니다.

    // prerender/fetch.js
    // adapt the function to set custom header 
    async function renderToHtml(lang, route, port, config) {
        const response = await fetch(`http://localhost:${port}/${route}`, 
            {
                headers: {'cr-lang': lang}
            });
    
        // ... the rest, save in different language folder as usual
        // ... the output index files all have base href set to '/'
    }
    

    어떤 인덱스를 제공할지 알기 위해 미들웨어에서 헤더를 잡기만 하면 됩니다.

    // language.js middleware, adapt the value to read "custom header" 
    // before resolving to cookie then to default
    res.locals.lang = req.get('cr-lang') || req.cookies['cr-lang'] || 'en';
    

    위의 언어 루프는 생성된 base href가 루트/로 설정된다는 점을 제외하고는 URL 구동 앱에서와 같이 언어 폴더 내에 정적 파일을 생성합니다. 이제 이러한 파일을 제공하려면 Express 경로가 물리적으로 일치해야 합니다. 이것은 미들웨어(예: serve-static middleware )로 수행할 수 있지만 여기서는 간단하게 유지하겠습니다.

    // express routes for cookie driven apps
    // ...
    const { existsSync } = require('fs');
    
    app.get('/*', (req, res) => {
        // first find the physical page, relative to __dirname and routes file
            // res.locals.lang is assumed to be set by middleware cookie reader
            // strip out the URL params if used in Angular ";param=something"
    
        const static =  rootPath + 'client/static/' + res.locals.lang + req.path.split(';')[0] + '/index.html';
        if (existsSync(static)) {
          res.sendFile(static);
          return;
        }
            // then render Angular SSR (a previous article)
        res.render(rootPath + `index/index.${res.locals.lang}.html`, {
          req,
          res
        });
    
    });
    

    불행하게도 StackBlitz에서는 사전 렌더링 기능을 테스트하기 위해 쿠키를 설정하거나 사용자 지정 헤더를 감지할 수 없었지만 로컬에서 작동하는 것을 확인했습니다.

    cookie based app is on StackBlitz .

    클라우드 호스팅



    공개 호스트의 주요 차이점은 강력한 Express 정적 미들웨어가 없다는 것입니다. 하지만 해결 방법은 파일을 그대로 client (공용) 폴더에 저장하는 것입니다. 따라서 Firebase, Netlify 및 Surge에서 호스팅하는 경우 유일한 차이점은 prerenderOut 폴더를 client로 설정하는 것입니다. 그러나 사전 렌더링된 파일을 생성하려면 최소한 로컬로 SSR을 생성해야 합니다. 따라서 로컬 Express 서버에서 실행할 방법이 없습니다. 음, 한 가지 방법이 있습니다. 그것은 노력을 더 작게 만들 것입니다. RenderModule를 사용하는 Angular 빌더입니다. 이건 다음화까지 기다려야 합니다. 😴

    계속 읽어 주셔서 감사합니다. 샌딩이 필요한 자국을 발견하면 알려주세요.

    서버리스 기능 정보



    Firebase와 같은 서버리스 기능으로 클라우드에서 SSR을 호스팅하는 경우 Express 서버만큼 좋습니다. Express 정적 미들웨어를 사용하여 정적 폴더를 노출하고 Firebase 에뮬레이터를 로컬에서 실행할 수 있습니다.
    firebase emulators:start
    그런 다음 별도의 익스프레스 스크립트를 실행하여 이미 실행 중인 Firebase 앱을 가져옵니다(일반적으로 포트 5000 ). 이와 같이:

    // simple script /prerender/serverless.js to run while firebase emulators are running
    const config = require('../server/config');
    const prerender = require('./fetch-url');
    
    async function act(port) {
      await prerender(port, config);
      console.log('Done prerendering');
    }
    
    act(5000);
    

    이렇게 하면 포트가 닫히지 않으며 Node.js에서 실행firebase하는 것보다 쉽습니다.
    cd prerender && node serverless
    The code is in StackBlitz .





    Angular 사전 렌더링 - 파트 II, Angular - Sekrab Garage



    단일 다국어 빌드



    garage.sekrab.com

    좋은 웹페이지 즐겨찾기