Preact와 Shadow DOM을 사용하여 끼워 넣을 수 있는 작은 위젯을 만듭니다
들키다
코드를 작성하기 전에 우리 팀이 발견하는 과정에서 배운 것들을 빠르게 토론하고 싶습니다.이것은 당신이 당신의 프로젝트를 위해 정확한 결정을 내리는 데 도움을 줄 수 있기를 바랍니다.
제품의 세부 사항을 이해한 후에, 우리는 코드 라이브러리에 두 가지 요구가 있다는 것을 발견했다.
봉인
우리 팀은 외부 CSS가 우리 코드에 연결되는 것을 방지해야 한다.그 밖에 우리의 스타일은 우리의 응용 프로그램에 적응해야 한다.우리는 iFrame에서 작은 부품을 포장하는 것을 탐색했고 iFrame은 a nested browsing context를 제공했다.이것은 우리가 필요로 하는 포장을 제공했지만, 우리는 iFrame을 제어하여 고품질의 전체 화면 체험을 제공하기가 매우 어렵다는 것을 발견했다.Fullscreen API는 잠재적인 해결 방안이지만 필요한 것을 수용할 수 없다browser support.iFrame을 사용하여 비교적 작은 제품을 봉인하는 것은 좋은 해결 방안일 수 있지만, 우리의 용례에 적합하지 않다.
우리는 주의력을 돌렸다Shadow DOM API.그림자 DOM은 숨겨진 DOM 트리를 모든 요소에 첨부하는 방법을 제공합니다.이것은 봉인을 만들지만, 응용 프로그램을 제어하는 능력을 제한하지 않습니다.또한 Shadow DOM API는 good browser support가 있습니다.
소포
작은 위젯은 빨리 불러와야 합니다.팀에서 제정한 정책이 있으면 응용 프로그램에 대한 코드 분리가 현저히 어렵다.CompanyCam에서 엔지니어들은 React로 사용자 인터페이스를 작성하기 때문에 이렇게 하는 것이 의미가 있다.
우리가 제3자 창고를 증가함에 따라 우리의 가방 규모도 증가하고 있다.우리는 Preact가 이 문제를 해결하는 좋은 방법이라는 것을 발견했다.그것은 React와 같은 모든 기능을 제공하지만, 포장은 훨씬 작다.당신은 Preact의 포장되지 않은 크기와 React와 React-DOM의 조합 크기를 비교하여 현저한 차이를 볼 수 있습니다!
이제 코드에 뛰어들자!작업 예시가 도움이 된다면 언제든지 복제하십시오this starter repo.
섀도우 DOM 레이어를 사용하여 응용 프로그램 설치
Preact는 조작하기 쉽다integrate into an existing project.우리의 Preact
App
구성 요소를 설치하는 것은 React와 유사하게 보일 것입니다./* @jsx h */
import { h, render } from "preact";
import App from "./components/App.jsx";
const appRoot = document.querySelector("#app-root");
render(<App />, appRoot);
이제 섀도우 DOM 레이어를 추가합니다./* @jsx h */
import { h, render } from "preact";
import App from "./components/App.jsx";
// app shadow root
const appRoot = document.querySelector("#app-root");
appRoot.attachShadow({
mode: "open",
});
render(<App />, appRoot.shadowRoot);
섀도우 DOM 레이어를 섀도우 호스트라는 일반 DOM 노드에 추가할 수 있습니다.우리는 attachShadow
방법을 호출하여 이 점을 실현할 수 있으며, 이 방법은 options
를 매개 변수로 한다.mode
전달치open
를 통해shadowRoot
속성을 통해 음영DOM에 접근할 수 있다.mode
의 또 다른 값은 closed
인데 이로 인해 shadowRoot
가 되돌아온다null
.모든 것이 정상인지 확인하기 위해서 우리는 열 수 있다
브라우저의 개발 도구 및 DOM 트리입니다.여기서 우리는 우리의 그림자 DOM층을 볼 수 있다.
섀도우 DOM 스타일 설정하기
스타일의 범위는 섀도우 DOM에서만 렌더링할 수 있습니다.
/* @jsx h */
import { h, render } from "preact";
import App from "./components/App.jsx";
import styles from "./styles.css";
// app shadow root
const appRoot = document.querySelector("#app-root");
appRoot.attachShadow({
mode: "open",
});
// inject styles
const styleTag = document.createElement("style");
styleTag.innerHTML = styles;
appRoot.appendChild(styleTag);
render(<App />, appRoot.shadowRoot);
웹 패키지를 사용한다면 css-loader 이 방법을 발휘할 수 있다는 것을 기억하십시오.마커style
를 생성하고 마커innerHTML
를 가져온 스타일시트로 설정합니다.응용 프로그램이 증가함에 따라 우리의 스타일을 관리하는 것은 매우 번거로워졌고, 우리 팀은 다른 해결 방안을 찾기를 희망했다.CompanyCam에서 저희 디자이너들은 styled-components로 저희 제품을 디자인하는 것을 좋아합니다.문서의
styled-components
끝에 generated stylesheet is injected를 덧붙이다.섀도우 DOM 레이어 때문에 일부 구성이 없으면 작업을 수행할 수 없습니다./* @jsx h */
import { h } from "preact";
import styled, { StyleSheetManager } from "styled-components";
const Heading = styled.h3`
color: #e155f5;
font-family: sans-serif;
`;
const App = () => {
return (
<StyleSheetManager target={document.querySelector("#app-root").shadowRoot}>
<Heading>Hey, Shadow DOM!</Heading>
</StyleSheetManager>
);
};
export default App;
StyleSheetManager 조수 모듈은 스타일의 처리 방식을 수정할 수 있습니다.어셈블리head
를 둘러싸고 그림자 바디App
를 children
의 값으로 전달합니다.이것은 스타일을 주입하기 위한 대체 DOM 노드를 제공합니다.앞의 기술처럼 우리는 음영DOM에서 우리의 스타일을 볼 수 있다.
상속 방지
섀도우 DOM은 포함된 태그에 대한 외부 CSS 선택기의 액세스를 차단합니다.그러나 섀도우 DOM의 요소는 inherit CSS values일 수도 있습니다.우리는 속성
shadowRoot
을 응용 프로그램 부모 요소의 값 target
으로 명시함으로써 실현할 수 있다. reset properties to their default values/* @jsx h */
import { h } from "preact";
import styled, { StyleSheetManager } from "styled-components";
const Heading = styled.h3`
color: #e155f5;
font-family: sans-serif;
`;
const WidgetContainer = styled.div`
all: initial;
`;
const App = () => {
return (
<StyleSheetManager target={document.querySelector("#app-root").shadowRoot}>
<WidgetContainer>
<Heading>Hey, Shadow DOM!</Heading>
</WidgetContainer>
</StyleSheetManager>
);
};
export default App;
포털 사이트와의 겹치는 순서 싸움 승리
Wordpress, Squarespace, Wix, 처음부터 시작하는 것이든, 우리의 작은 위젯은 모든 사이트에서 사용해야 한다.stacking order depends on the DOM tree hierarchy부터 시작하여 전체 화면 구성 요소에서
all
문제를 즉시 확인할 수 있습니다.Portals는
initial
를 응용 프로그램 상하문 이외의 DOM 노드에 보여주는 방법을 제공했다.z-index
를 DOM 노드에 마운트할 수 있습니다.우리의 예에서, 우리는 이 전체 화면 구성 요소들을 DOM 트리에서 가능한 한 높은 위치에 보여야 한다.따라서 우리는 작은 부품을 설치한 문서children
에 우리의 Portal
를 추가할 수 있다.응용 프로그램의 루트부터 만듭니다.
Portal
// index.js
/* @jsx h */
import { h, render } from "preact";
import App from "./components/App.jsx";
// shadow portal root
const portalRoot = document.createElement("div");
portalRoot.setAttribute("id", "portal-root");
portalRoot.attachShadow({
mode: "open",
});
document.body.appendChild(portalRoot);
// app shadow root
const appRoot = document.querySelector("#app-root");
appRoot.attachShadow({
mode: "open",
});
render(<App />, appRoot.shadowRoot);
body
어셈블리에 섀도우 바디를 생성하고 해당 바디에 Portal
를 지정합니다.그리고 우리가 사용Portal
한 것처럼 새로운 음영DOM층을 추가합니다./* @jsx h */
import { h, Fragment } from "preact";
import { useLayoutEffect, useRef } from "preact/hooks";
import { createPortal } from "preact/compat";
import styled, { StyleSheetManager } from "styled-components";
const Portal = ({ children, ...props }) => {
const PortalContainer = styled.div`
all: initial;
`;
const node = useRef();
const portalRoot = document.querySelector("#portal-root");
useLayoutEffect(() => {
const { current } = node;
if (current) {
portalRoot.appendChild(current);
}
}, [node, portalRoot]);
return (
<Fragment ref={node} {...props}>
{createPortal(
<StyleSheetManager target={portalRoot.shadowRoot}>
<PortalContainer>{children}</PortalContainer>
</StyleSheetManager>,
portalRoot.shadowRoot
)}
</Fragment>
);
};
export default Portal;
다음에 id
구성 요소를 만듭니다.어셈블리 모 피쳐 요소에 추가할 효과를 추가합니다.그곳에서 appRoot
과Portal
를 통해portalRoot
까지.children
를 사용하여 스타일 범위를 portalRoot.shadowRoot
섀도우 DOM 레이어로 설정하고 하위 요소의 스타일을 기본값으로 재설정합니다./* @jsx h */
import { h } from "preact";
import styled, { StyleSheetManager } from "styled-components";
import Portal from "./Portal.jsx";
const Heading = styled.h3`
color: #e155f5;
font-family: sans-serif;
`;
const WidgetContainer = styled.div`
all: initial;
`;
const App = () => {
return (
<StyleSheetManager target={document.querySelector("#app-root").shadowRoot}>
<WidgetContainer>
<Heading>Hey, Shadow DOM!</Heading>
<Portal>
<Heading>Hey, Shadow Portal!</Heading>
</Portal>
</WidgetContainer>
</StyleSheetManager>
);
};
export default App;
현재 우리는 createPortal
에서 모든 전체 화면 구성 요소를 포장할 수 있다.결론
최근에 우리 팀은 released the widget to GA이 있다.상기 개술한 기술은 우리로 하여금 작은 코드 라이브러리로 풍부한 응용 프로그램 체험을 구축할 수 있게 한다. 즉...대부분 봉인되어 있습니다.Google은 사이트 생성기 테마가 제공하는 간혹
Portal
문제나 자바스크립트 이벤트 충돌을 만날 수 있습니다.전반적으로widget 설치는 성공적입니다.
Reference
이 문제에 관하여(Preact와 Shadow DOM을 사용하여 끼워 넣을 수 있는 작은 위젯을 만듭니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/companycam/build-an-embeddable-widget-using-preact-and-the-shadow-dom-33lm텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)