위젯
GitLab v19.4요약
프론트엔드 위젯은 페이지에 추가해 기능의 일부를 담당하는 독립형 Vue 애플리케이션 또는 Vue 컴포넌트 트리입니다. 대표적인 위젯으로 사이드바 담당자와 사이드바 기밀 설정이 있습니다. 위젯을 만들 때는 아래에 설명하는 몇 가지 원칙을 따릅니다.
프론트엔드 위젯은 페이지에 추가해 기능의 일부를 담당하는 독립형 Vue 애플리케이션 또는 Vue 컴포넌트 트리입니다.
대표적인 위젯으로 사이드바 담당자와 사이드바 기밀 설정이 있습니다.
위젯을 만들 때는 아래에 설명하는 몇 가지 원칙을 따릅니다.
Vue Apollo 필수#
모든 위젯은 동일한 스택(Vue + Apollo Client)을 사용해야 합니다. 이를 위해 (위젯을 컴포넌트로 사용하는 경우) 애플리케이션 루트에 Vue Apollo를 추가하거나 위젯에 직접 제공해야 합니다. 사이드바 위젯에는 issuable Apollo Client와 Apollo Provider를 사용합니다.
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import { apolloProvider } from '~/graphql_shared/issuable_client';
function mountConfidentialComponent() {
new Vue({
apolloProvider,
components: {
SidebarConfidentialityWidget,
},
/* ... */
});
}
필수 주입 항목#
편집 가능한 모든 사이드바 위젯은 접힘/펼침 상태를 다루기 위해 SidebarEditableItem을 사용해야 합니다. 이 컴포넌트는 애플리케이션 루트에서 제공하는 canUpdate 속성을 필요로 합니다.
전역 상태 매핑 금지#
위젯은 최대한 재사용할 수 있도록 만드는 것이 목표입니다. 그래서 위젯이나 그 하위 컴포넌트에 외부 상태 바인딩을 추가하지 않습니다. Vuex 매핑과 중재자 스토어도 여기에 해당합니다.
위젯의 책임#
위젯은 자신이 담당하도록 설계된 엔터티(담당자, 이터레이션 등)를 가져오고 업데이트하는 일을 맡습니다. 즉, 위젯은 (Apollo 캐시에 이미 없다면) 항상 데이터를 직접 가져와야 합니다. 위젯에 초기값을 제공하더라도, 위젯은 백그라운드에서 GraphQL 쿼리를 실행해 그 결과를 Apollo 캐시에 저장해야 합니다.
장기적으로 Apollo Client 캐시를 애플리케이션 전역 상태로 사용하게 되면 사이드바 위젯에 초기 데이터를 전달할 필요가 없어집니다. 그때는 위젯이 캐시에서 데이터를 가져올 수 있습니다.
GraphQL 쿼리와 뮤테이션 사용#
위젯은 서로 다른 엔터티(에픽, 이슈, 머지 리퀘스트 등)와 함께 동작할 수 있을 만큼 유연해야 합니다. 사이드바마다 다른 GraphQL 쿼리와 뮤테이션이 필요하므로 매핑을 만듭니다.
export const assigneesQueries = {
[TYPE_ISSUE]: {
query: getIssueParticipants,
mutation: updateAssigneesMutation,
},
[TYPE_MERGE_REQUEST]: {
query: getMergeRequestParticipants,
mutation: updateMergeRequestParticipantsMutation,
},
};
쿼리 업데이트에 같은 로직을 적용하기 위해 쿼리 필드에 별칭을 붙입니다. 예를 들면 다음과 같습니다.
group또는project는namespace가 됩니다issue,epic,mergeRequest는issuable이 됩니다
아쉽게도 Apollo는 별칭이 붙은 필드의 typename을 undefined로 지정하므로 __typename을 명시적으로 가져와야 합니다.
query issueConfidential($fullPath: ID!, $iid: String) {
namespace: project(fullPath: $fullPath) {
__typename
issuable: issue(iid: $iid) {
__typename
id
confidential
}
}
}
다른 Vue 애플리케이션과의 통신#
위젯 상태의 변경을 (예를 들어 뮤테이션이 성공한 뒤) 상위 애플리케이션에 알려야 한다면 이벤트를 발행합니다.
updateAssignees(assigneeUsernames) {
return this.$apollo
.mutate({
mutation: this.$options.assigneesQueries[this.issuableType].mutation,
variables: {...},
})
.then(({ data }) => {
const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || [];
this.$emit('assignees-updated', assignees);
})
}
NotesApp처럼 다른 Vue 애플리케이션의 변경을 수신해야 할 때도 있습니다.
이 경우에는 클라이언트를 가져와 특정 쿼리를 수신하는 렌더리스 컴포넌트를 사용할 수 있습니다.
import { fetchPolicies } from '~/lib/graphql';
import { confidentialityQueries } from '~/sidebar/constants';
import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client';
created() {
if (this.issuableType !== IssuableType.Issue) {
return;
}
gqlClient
.watchQuery({
query: confidentialityQueries[this.issuableType].query,
variables: {...},
fetchPolicy: fetchPolicies.CACHE_ONLY,
})
.subscribe((res) => {
this.setConfidentiality(issuable.confidential);
});
},
methods: {
...mapActions(['setConfidentiality']),
},
머지 리퀘스트 위젯#
머지 리퀘스트 위젯 프레임워크 전용 문서를 참고합니다.