Ember Micro 전면, 단수 치료 센터 포함

본고에서, 나는 당신에게 Ember.js 라이브러리를 사용하여 single-spa에서 마이크로 전단을 만드는 방법을 소개할 것입니다.
우리는 스타워즈 영화의 행성과 인물 참고 목록을 두 페이지만 봐도 볼 수 있는 간단한 응용 프로그램을 만들 것이다.행성 페이지에는 영화 속의 행성과 그 상세한 정보가 열거될 것이다.마찬가지로 인물 페이지에는 영화 속의 인물과 그 상세한 정보가 열거될 것이다.
here에서 embermicro 전단을 볼 수 있습니다. 원본 코드는 github repo에 위탁되어 있습니다.
본 강좌를 깊이 있게 배우기 전에, 우리는 먼저 우리가 사용할 도구와 기술을 분명히 해야 한다.

마이크로 프런트엔드


마이크로 전단은 우리로 하여금 많은 소형 응용 프로그램을 조합하여 팀으로 하여금 그들의 기술을 선택할 수 있게 한다.이것은 약간 백엔드의 마이크로서비스 같다.

잔재회사 명


Ember.js은 자신의 의견을 고집하고 효율적이며 전투 테스트를 거친 자바스크립트 프레임워크로 현대 웹 응용 프로그램을 구축하는 데 사용된다.그것은 풍부한 단일 페이지 응용 프로그램을 구축하는 데 필요한 모든 것, 그리고 훌륭한 지역 사회와 우수한 문서를 포함하고 있다.

독수리 요법


single-spa은 프런트엔드 마이크로서비스에 사용되는 JavaScript 라우터입니다.
단일 spa를 사용하면 단일 페이지 응용 프로그램에서 여러 프레임워크를 사용할 수 있습니다. 기능에 따라 코드를 구분할 수 있고 각도, 반응, Vue가 있습니다.js 등 응용 프로그램은 모두 조화롭게 생활한다.단일spa는 그것들을 함께 일할 수 있게 하고 필요하기 전에 불러오지 않습니다.

단일 스파 재


single-spa-ember은 Ember와 함께 사용할 수 있도록 단일 spa에 등록된 응용 프로그램의 생명주기 기능(안내, 마운트 및 마운트 해제)을 실현하는 데 도움을 주는 도움말 라이브러리입니다.js.더 많은 정보는github 저장소를 보십시오.

단일 spa 만들기


single spa는 웹 팩, babel, jest 등 설정을 자동으로 생성하고 관리하는 것을 좋아하는 사용자에게 CLI을 제공합니다. CLI를 사용하지 않고 single spa 프로그램을 만들 수도 있습니다.

단일 스파 핵심 팀 추천 설정


단일spa 핵심팀은 기본 설정을 사용하고 한 그룹의 약정에 따라 모든 프레임워크를 가진 마이크로 전단을 만드는 것을 권장합니다. 이것은 우리가 장기적으로 마이크로 전단을 확장하는 데 도움이 될 것입니다.
다음 설정을 따릅니다.
ember-micro-frontends
|- root-config
|- navbar
|- people
|- planets
|- styleguide

루트 구성


이것은 host app입니다. 이것은 하나의 스파를 사용하여 모든 다른 마이크로 전단을 관리합니다.
CLI를 사용하여 루트 구성 응용 프로그램을 만드는 방법을 살펴보겠습니다.
터미널에서 create-single-spa 명령 호출
create-single-spa
디렉터리, 응용 프로그램 형식 같은 옵션을 제공합니다.createsinglespa를 사용하면 브라우저 유틸리티와 루트 설정에서 singlespa 프로그램과 같은 다양한 종류의 프로그램을 만들 수 있습니다.다양한 유형의 모듈 here에 대한 정보를 더 많이 읽을 수 있습니다.
이 항목의 경우 single-spa root config 옵션을 선택하고 다른 연속 프롬프트를 따라야 합니다.
? Directory for new project 
? Select type to generate (Use arrow keys)
  single-spa application / parcel
  in-browser utility module (styleguide, api cache, etc)
❯ single-spa root config
생성기가 완료되면 두 개의 파일을 포함하는 src 폴더가 있습니다.index.ejs은 저희 호스트 응용 프로그램의 html 템플릿입니다. 저희는 다른 마이크로 전단에 자리 표시자를 제공할 것입니다.Ember 응용 프로그램은 루트 요소라고 하는 DOM 요소를 불러와야 하기 때문에 이 파일의 body 태그에 응용 프로그램을 배치합니다.
<template id="single-spa-layout">
      <single-spa-router>
        <nav class="topnav">
          <application name="navbar" loader="topNav" error="topNav"></application>
          <div id="navbar"></div>
        </nav>
        <div class="main-content mt-16">
          <route path="people">
            <application name="people"></application>
            <div id="people"></div>
          </route>
          <route path="planets">
            <application name="planets"></application>
            <div id="planets"></div>
          </route>
          <route default>
            <h1 class="flex flex-row justify-center p-16">
              <p class="max-w-md">
                This example project shows independently built and deployed
                microfrontends that use <a href="https://emberjs.com" target="_blank">Ember.js</a> and <a href="https://single-spa.js.org" target="_blank">single-spa</a>. Each nav link
                above takes you to a different microfrontend.
              </p>
            </h1>
          </route>
        </div>
      </single-spa-router>
    </template
다음 파일은 root-config.js입니다.여기서 각 spa registerApplication api를 사용하여 다음과 같이 모든 Ember micro 프런트엔드를 등록합니다.
import { registerApplication, start } from "single-spa";
const planetsApp = registerApplication(
  "planets",
  () => {
    const appName = "planets";
    const appUrl = `http://localhost:4200/planets/assets/planets.js`;
    const vendorUrl = `http://localhost:4200/planets/assets/vendor.js`;
    return loadEmberApp(appName, appUrl, vendorUrl);
  },
  (location) => location.pathname.startsWith("/planets")
);
위의 코드는 single spa에 planets이라는 Ember micro 전단을 등록하고 app.jsvendor.js 파일의 URL을 알려 줍니다.Ember는 두 개의 주요 Javascript 자산인 응용 프로그램과 공급업체를 사용하기 때문에, 이 파일들을 어디에서 불러오는지 알려야 합니다.여기서 Ember 응용 프로그램 planets에 대해 로컬 서버를 실행하고 있습니다.

탐색 표시줄


app은 URL 루트에 따라 서로 다른 마이크로 전단까지 내비게이션 표시줄을 포함한다.
ember-cli new 명령을 사용하여 프로젝트를 만듭니다.
ember new navbar
peopleplanets의 두 라우팅 생성
ember g route people
ember g route planets
app/templates/application.hbs에서 내비게이션 태그 만들기
 <div id="nav-wrapper" class="h-16 flex items-center justify-between px-6 bg-burnt-ember text-white">
      <div class="flex items-center justify-between">
        <span class="px-6 font-bold">Ember Micro-Frontends</span>
        <LinkTo @route="index" class="p-6">Home</LinkTo> 
        <LinkTo @route="people" class="p-6">People</LinkTo> 
        <LinkTo @route="planets" class="p-6">Planets</LinkTo> 
      </div>
      <div class="flex items-center justify-between">
        <a
          href="https://github.com/ember-micro-frontends"
          class="externalLink"
        >
          Github project
        </a>
      </div>
    </div>
{{outlet}}

autoRun을 닫아서 Ember build를 변경해야 합니다. 왜냐하면 Ember 응용 프로그램이 스크립트를 해석하고 실행한 후에 자동으로 시작하기 때문입니다.따라서singlespa는 실행할 때 동적 마운트/마운트 해제를 위해 이 설정을 닫는 것을 권장합니다.
module.exports = function(defaults) {
  let app = new EmberApp(defaults, {
    autoRun: false,
    storeConfigInMeta: false,
    fingerprint: {
      customHash: null
    }
  });

  app.import('node_modules/single-spa-ember/amd/single-spa-ember.js', {
    using: [
      { transformation: 'amd', as: 'single-spa-ember' }
    ]
  });

  return app.toTree();
};
마지막으로 Ember 응용 프로그램의 라이프 사이클을 파일 끝 app/app.js의 단일 spa 라이브러리와 연결해야 합니다.
import singleSpaEmber from 'single-spa-ember';

const emberLifecycles = singleSpaEmber({
  App,
  appName: 'navbar',
  createOpts: {
    rootElement: '#navbar',
  }
});

export const bootstrap = emberLifecycles.bootstrap;
export const mount = emberLifecycles.mount;
export const unmount = emberLifecycles.unmount;
우리는 우리가 만든 각 Ember 응용 프로그램에 대해 상기 절차를 수행해야 합니다.

사람


micro frontend은 인원 페이지에 사용되며, 스타워즈 API SWAPI을 사용하여 인원과 그 상세한 정보를 열거합니다.
api의 인덱스 경로에서 다음과 같은 인원 정보를 얻을 것입니다.
export default class IndexRoute extends Route {
  queryParams = {
    id: {
      refreshModel: true,
    },
  };

  async model(params) {
    const response = await fetch("https://swapi.dev/api/people/");
    const _people = await response.json();
    _people.results.forEach((p,index) => p.id = ++index);
    const people = _people.results;
    const person = people.find(p => p.id == params.id);
    return { people, person };
  }
}
api에서, 우리는 단독 구성 요소의 인원과 다른 구성 요소의 상세한 정보를 열거할 것입니다.
ember g component people-list
ember g component selected-people
색인 라우팅 템플릿은 다음과 같습니다.
<div>
  <div class="flex">
    <div class="p-6 w-1/3">
      {{#if this.nextPage}}
        <Button
          disabled={{this.disabled}}
          loading={{this.loading}}
          {{on "click" this.fetchPlanets }}
          >
          Fetch More Planets
        </Button>
        {{/if}}
        <PeopleList @people={{@model.people}}/>
    </div>
    <div class="w-2/3 p-6 border-l-2 border-white">
      <div class="selectedPlanet">
        <SelectedPeople @person={{@model.person}} />
      </div>
    </div>
  </div>
</div>
구성 요소의 표시는 색인 페이지에 선택한 인원 정보를 오른쪽에 표시하는 링크 목록을 만드는 것과 유사합니다.
<div class="people-list">
  {{#each @people as |p|}}
  <LinkTo @route="index" @query={{hash id=p.id}} class="h-12 flex items-center border-white border-b cursor-pointer no-underline">
    {{p.name}} 
  </LinkTo>
  {{/each}}
</div>
인원 세부 정보를 표시하는 구성 요소에는 다음과 같은 표시가 있습니다.
<table>
  <tr>
    <td class="font-bold pr-6 w-40">
      Name
    </td> 
    <td>{{@person.name}}</td>
  </tr>
  <tr>
  <td class="font-bold pr-6 w-40">Height</td>
  <td>{{@person.height}}</td>
  </tr>
  <tr>
  <td class="font-bold pr-6 w-40">Mass</td>
  <td>{{@person.mass}}</td>
  </tr>
  <tr>
  <td class="font-bold pr-6 w-40">Hair color</td>
  <td>{{@person.hair_color}}</td>
  </tr>
  <tr>
  <td class="font-bold pr-6 w-40">Gender</td>
  <td>{{@person.gender}}</td>
  </tr>
  <tr>
  <td class="font-bold pr-6 w-40">Birth year</td>
  <td>{{@person.birth_year}}</td>
  </tr> 
  <tr>
  <td class="font-bold pr-6 w-40">Homeworld</td>
  <td><a href="/planets#/?id=1">{{@person.homeworld}}</a></td>
    </tr>
    <tr>
      <td>Films
      </td>
    </tr>
</table>

행성


planets 마이크로 전단은 거의 피플 마이크로 전단과 비슷하지만 SWAPI에서 온planetsapi를 사용합니다.
export default class IndexRoute extends Route {
  queryParams = {
    id: {
      refreshModel: true,
    },
  };

  async model(params) {
    const response = await fetch("https://swapi.dev/api/planets/");
    const _planets = await response.json();
    _planets.results.forEach((p,index) => p.id = ++index);
    const planets = _planets.results;
    const planet = planets.find(p => p.id == params.id);
    return { planets, planet };
  }
}

스타일 마법사


micro frontend은 특수한 것이다.여기에서 Tailwind CSS 라이브러리 유틸리티를 내보내서 모든 마이크로 프론트 사이에서 공유하고 Tailwind의 CSS 유틸리티 클래스를 사용하여 스타일링할 수 있도록 합니다.
:root {
  --color-primary: #011627;
  --color-secondary: #8b8c8a;
  --color-danger: #e71d36;
  --color-warning: #ff9f1c;
  --color-info: #2ec4b6;
  --color-background: #182b3a;
  --color-black: #171817;
  --color-overlay: rgba(253, 255, 252, 0.8);
  --color-ember: #e04e39;
  --color-burnt-ember: #9b2918;
  --color-white: #fdfdfd;
}

@tailwind base;

@tailwind components;

@tailwind utilities;

body {
  background-color: var(--color-ember);
  color: var(--color-white);
}

nav.topnav {
  position: fixed;
  width: 100vw;
  top: 0px;
  z-index: 100;
}

응용 프로그램 실행


위의 모든 작업을 정확하게 완료하면 Ember microfrontends를 시작하고 yarn start 응용 프로그램에서 root-config을 시작하여 로컬 환경에서 실행할 수 있습니다.
yarn start
이것은 시작 응용 프로그램을 통해 포트 9000에서 webpack-dev-server을 시작합니다. localhost:9000에서 응용 프로그램을 볼 수 있습니다

이미 알고 있는 문제


단일 스파에서 Ember micro 전단을 실행하는 방법은 그 자체의 일련의 도전이 있다.

히스토리 라우터


보시다시피, planets 마이크로 프론트에서, 우리는 Ember에서 조회 파라미터와 해시 기반 루트를 사용합니다. 만약에 우리가 Ember에서 역사 루트를 사용한다면, Ember는 브라우저 역사와 URL을 제어할 것입니다. 이것은 다른 마이크로 프론트의 루트에 문제를 가져올 수 있습니다.따라서 하나의 spa와 함께 사용한다면, Ember micro 전단에 해시 루트를 사용하는 것을 권장합니다.만약 당신이 어떤 생각이 있다면, 저에게 우리가 평론 중의 문제를 어떻게 해결하는지 알려 주세요.

잔재 데이터


Ember micro 프런트엔드에서 직면한 또 다른 문제는 ember-data 라이브러리와 Ember 데이터가 첨부된 저장소를 사용하는 것입니다.두 Ember 응용 프로그램 모두 자신의 Ember 데이터 귀속과 전역 대상이 서로 충돌하기 때문에 다른 페이지를 탐색할 때 다음과 같은 오류가 발생했습니다.
TypeError: Cannot redefine property Inflector

창문.요구 사항항목


이전에 방문한 페이지를 탐색할 때, 내가 직면한 또 다른 문제는 Ember가 window.require.entries에서 모듈 목록을 재설정할 것이다.예를 들어 먼저 인물 페이지에 방문하면 window.require.entries은people Ember 응용 프로그램의 모듈을 채우고 제품 응용 프로그램에 방문하면 Ember는 인물 응용 프로그램의 항목을 리셋합니다. 현재 window.require.entries은planets 응용 프로그램에서 온 모듈만 포함합니다.따라서 연락처 페이지에 다시 액세스하려고 하면 빈 페이지나 콘솔에서 오류가 발생합니다.

다른 Ember 버전


나는 아직 다른 재로 미전단을 구축하려고 시도하지 않았다.js 버전, 나는 이것이 그것 자신의 일련의 문제를 가져올 수 있다고 믿는다.여기에 구축된 모든 마이크로 프론트는 동일한 Ember 버전(3.19)을 사용합니다.

이별 생각


비록 Ember 커뮤니티는 Ember Engines이 한 페이지에서 서로 다른 Ember 응용 프로그램을 실행하는 것을 권장하지만, 이러한 마이크로 전단을 만드는 방법은 그 자체의 장점이 있다.
특정 프레임워크 구현에 제한을 두지 않고 다른 Ember 응용 프로그램과 함께 이 마이크로 프론트에 추가할 수 있는 프레임워크를 자유롭게 선택할 수 있습니다.
다른 마이크로 프론트과의 의존 관계를 변경했다면, 다른 Ember 응용 프로그램을 재배치할 필요가 없습니다. 왜냐하면 하나의 spa가 다른 마이크로 프론트를 위탁 관리하는 위치에서 의존 관계를 등록하기 때문입니다.
단일 spa팀에서 제공하는 single-spa-inspector 브라우저 플러그인을 사용하여 브라우저에서 응용 프로그램을 동적 마운트/마운트 해제할 수 있습니다.Chrome 및 Firefox 브라우저를 지원합니다.

로컬 개발 환경에서 마이크로 프론트를 테스트하기 위해 실행할 때 플러그인을 사용하여 브라우저 내의 응용 프로그램을 덮어쓸 수도 있습니다.
댓글에서 단일spa를 사용하여 Ember 마이크로 전단을 구축하는 방법에 대한 생각을 알려주시고 단일spa를 사용하여 다른 프레임워크(예를 들어 React, Vue, Svelte, Preact 등)에서 마이크로 전단을 구축하십시오.
page에서 예제 목록을 찾을 수 있습니다

참고 문헌:

  • single-spa
  • single-spa-ember
  • Ember.js
  • ember-micro-frontends
  • Github source code
  • 좋은 웹페이지 즐겨찾기