Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
The State of Web Components
Search
Shogo Sensui
September 24, 2017
Technology
9
8.9k
The State of Web Components
2017年9月24日に開催された HTML5 Conference 2017 の「The State of Web Components」のセッション資料です。
Shogo Sensui
September 24, 2017
Tweet
Share
More Decks by Shogo Sensui
See All by Shogo Sensui
三年間の関わりから見る PR TIMES エンジニアリングの変化 / Transition of PRTimes Engineering
1000ch
0
1.1k
EU のデジタル市場法と Apple / DMA and Apple
1000ch
0
91
Web Share API
1000ch
0
110
2023 年の Web 開発のベースライン / Web Development Baseline 2023
1000ch
0
34
開発生産性と組織 / Productivity and Organization
1000ch
0
1.1k
なぜ私達は働くのか / Why We Work?
1000ch
0
56
新しいメルカリ Web とそのパフォーマンス / The New Mercari Web and its performance
1000ch
0
58
Web Standards Interop 2022
1000ch
0
280
パフォーマンスを高める CSS / Performance Optimized CSS
1000ch
1
770
Other Decks in Technology
See All in Technology
最近のSfM手法まとめ - COLMAP / GLOMAPを中心に -
kwchrk
8
1.7k
AWS環境におけるランサムウェア攻撃対策の設計
nrinetcom
PRO
1
310
型情報を用いたLintでコード品質を向上させる
sansantech
PRO
2
200
株式会社ログラス − エンジニア向け会社説明資料 / Loglass Comapany Deck for Engineer
loglass2019
3
33k
メンタル面でもつよつよエンジニアになる/登壇資料(井田 献一朗)
hacobu
0
160
[トレノケ雲の会 mod.13] 3回目のre:Inventで気づいたこと -CloudOperationsを添えて-
shintaro_fukatsu
0
120
日本版とグローバル版のモバイルアプリ統合の開発の裏側と今後の展望
miichan
1
170
ゼロから創る横断SREチーム 挑戦と進化の軌跡
rvirus0817
3
740
効率的な技術組織が作れる!書籍『チームトポロジー』要点まとめ
iwamot
2
180
Google Cloud で始める Cloud Run 〜AWSとの比較と実例デモで解説〜
risatube
PRO
0
130
OCI技術資料 : ファイル・ストレージ 概要
ocise
3
12k
20240522 - 躍遷創作理念 @ PicCollage Workshop
dpys
0
290
Featured
See All Featured
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2k
Building Your Own Lightsaber
phodgson
104
6.1k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
Fireside Chat
paigeccino
34
3.1k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
49
2.2k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Typedesign – Prime Four
hannesfritz
40
2.5k
Designing for Performance
lara
604
68k
RailsConf 2023
tenderlove
29
960
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Measuring & Analyzing Core Web Vitals
bluesmoon
5
190
Mobile First: as difficult as doing things right
swwweet
222
9k
Transcript
)5.-$POGFSFODF 4IPHP4FOTVJBLB!DI 5IF4UBUFPG8FC$PNQPOFOUT
!DI
‣ 4IPHP4FOTVJ ‣ ؎ٝة٦طحزדכDIדׅ ‣ $ZCFS"HFOU *OD ‣ 8FC*OJUJBUJWF$FOUFS ‣
4PGUXBSF&OHJOFFS ‣ 8FC䪮遭Ⰻ菙ָ㥨ֹדׅ ‣ 044崞⹛׃גתׅ
馄鸞劤ָ⳿תׅ 涪㡰✮㹀
8IZ8FC$PNQPOFOUT
)5.- $44 8FC涪罏
8FCחֶֽ鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣鴥$44ך䕦갟眔㔲ָ鎘濼זְ ‣ せ瑞ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ䗳銲ָ֮ ‣ ⡲鿇ㅷⱄⵃ欽׃חְֻ ‣
)5.- $44 +BWB4DSJQUתה➬穈ָזְ ‣ תה鿇ㅷꂁ䋒ׅؒ؝ءأذيָזַ
نةٝ⡲חכ˘ GBODZCVUUPO
<button> fancy button </button> button { background: #0086b3; color: white;
padding: 1em; border-radius: 0.5em; border: none; } )5.-ה$44剅ֽל0,
GBODZCVUUPO
GBODZCVUUPO GBODZCVUUPO
<button class="a"> fancy button </button> <button class="b"> fancy button </button>
button { color: white; padding: 1em; border-radius: 0.5em; border: none; } button.a { background: #0086b3; } button.b { background: #008080; }
GBODZCVUUPO GBODZCVUUPO
GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO
GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO PWBM TRVBSF
fancy button </button> <button class="b"> fancy button </button> <button class="c">
fancy button </button> <button class="oval"> oval </button> <button class="square"> border-radius: 0.5em; border: none; } button.a { background: #0086b3; } button.b { background: #008080; } button.oval { ... }
GBODZCVUUPO GBODZCVUUPO GBODZCVUUPO PWBM TRVBSF
<fancy-button color="a"> fancy button </fancy-button> <fancy-button color="b"> fancy button </fancy-button>
<fancy-button color="c"> fancy button </fancy-button> <oval-button>oval</oval-button> <square-button>square</square-button>
4IBEPX%0. $VTUPN&MFNFOUT 5FNQMBUFT )5.-*NQPSUT ˟׳התד
˟䎃猧植㖈 4IBEPX%0. $VTUPN&MFNFOUT 5FNQMBUFT &4.PEVMFT
4IBEPX%0.
4IBEPX%0.הכ ‣ )5.-ծ$44ծ+BWB4DSJQUך䕦갟眔㔲ꣲ㹀ׅ ‣ مأزהז銲稆חTIBEPX3PPU欰װ׃ծך⚥ד饯ֿֿה4IBEPX %0.ⰻח殅 ‣ 4IBEPX%0.㢩鿇ַך䕦갟ꣲ㹀ׅ ‣ TIBEPX3PPUפך،ؙإأꣲ㹀涸ח׃ծ䮶莸ְ䬐⥂ׅ
‣ TIBEPX3PPUפ،ؙإأדֹPQFOٌ٦سהծ黪倖ׅDMPTFEٌ٦سָ֮
const button = document.querySelector('button'); const shadowRoot = button.attachShadow({ mode: 'open'
// or 'close' }); // readonly property console.log(button.shadowRoot); 4IBEPX%0.ך欰װ׃倯
GBODZCVUUPO ⢽ִלְֲֲֿنةٝ
<button> fancy button </button> ֲֿ剅ֽءٝفٕ˘ <style> button { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; }ɹ </style>
<button> #shadow-root fancy button </button> <style> button { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button>
<button> #shadow-root fancy button </button> <style> button { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; }ɹ </style> <button> <slot></slot> </button>
<button> #shadow-root fancy button </button> <style> button { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> 4DPQFE
$VTUPN&MFNFOUT
$VTUPN&MFNFOUTהכ ‣ 杝荈ך)5.-銲稆㹑鎉ׅ ‣ )5.-ד㹑鎉涸חⵃ欽דֹ ‣ %0."1*鸐ׄגㄏ⟀涸חⵃ欽דֹ ‣ ⟣䠐ך䮶莸ְ㹀纏ׅ ‣
㹀纏ׁٓ؎ؿ؟؎ؙٕؿحؙׅ
class FancyButton extends HTMLElement { constructor() { ... } connectedCallback()
{ ... } disconnectedCallback() { ... } attributeChangedCallback() { ... } adoptedCallback() { ... } } ؕأةي銲稆ٓ؎ؿ؟؎ؙٕ
䖞勻ך8FC鿇ㅷךⱄⵃ欽 ‣ 鿇ㅷ圓䧭ׅ)5.-鎸鶢ׅ ‣ $44ח״أة؎ؚٔٝ黝欽ׅ ‣ $44ؿ؋؎ٕٗ٦سׅծTUZMF銲稆剅ֻծFUD ‣ +BWB4DSJQUח״䮶莸ְ黝欽ׅ ‣
+BWB4DSJQUؿ؋؎ٕٗ٦سׅծTDSJQU銲稆剅ֻծFUD
GBODZCVUUPO نةٝ⢪ְְ˘
.fancy { background: #0086b3; color: white; padding: 1em; border-radius: 0.5em;
border: none; } CVUUPODTT
CVUUPOKT document .querySelector('.fancy') .addEventListener('click', () => { //... });
<button class="fancy"> fancy button </button> JOEFYIUNM
<link rel="stylesheet" href="button.css"> ... <button class="fancy"> fancy button </button> ...
<script src="button.js"></script> 穈さׇג⢪ֲ
None
class FancyButton extends HTMLElement { connectedCallback() { this.innerHTML = `
<style>button { … }</style> <button>fancy button</button> `; } } customElements .define('fancy-button', FancyButton);
<fancy-button> fancy button </fancy-button> GBODZCVUUPO GBODZCVUUPO⢪ִ
<fancy-button> <style> button { background: #0086b3; color: white; padding: 1em;
border-radius: 0.5em; border: none; } </style> <button> fancy button </button> </fancy-button> /PUTDPQFE
4IBEPX%0. $VTUPN&MFNFOUT
class FancyButton extends HTMLElement { connectedCallback() { this.innerHTML = `
<style>button { … }</style> <button>fancy button</button> `; } } customElements .define('fancy-button', FancyButton);
class FancyButton extends HTMLElement { connectedCallback() { this.shadowRoot.innerHTML = `
<style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
<fancy-button> <style> button { background: #0086b3; color: white; padding: 1em;
border-radius: 0.5em; border: none; } </style> <button> fancy button </button> </fancy-button>
<fancy-button> #shadow-root <style> button { background: #0086b3; color: white; padding:
1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> fancy button </fancy-button> 4DPQFE
5FNQMBUFT
5FNQMBUFTהכ ‣ ꬊ崞䚍ז)5.-銲稆㹑鎉ׅ ‣ ذٝفٖ٦زה׃ג)5.-銲稆䪔ִ ‣ 䖞勻ךعحؙ涸ז،فٗ٦ثׇ׆ח幥
<div style="display:none;"> <p>This is an image</p> <img src="foo.jpg" alt=""> </div>
4FOEBSFRVFTU
<script type="text/template"> <p>This is an image</p> <img src="foo.jpg" alt=""> </script>
&WBMXJUIJOOFS)5.-
<template> <p>This is an image</p> <img src="foo.jpg" alt=""> </template> *OFSU✨
4IBEPX%0. $VTUPN&MFNFOUT 5FNQMBUFT
class FancyButton extends HTMLElement { connectedCallback() { this.shadowRoot.innerHTML = `
<style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
<template> <style>button { … }</style> <button><slot></slot></button> </template> <script> class FancyButton
extends HTMLElement { // ... } customElements .define('fancy-button', FancyButton); </script>
<link rel="import" href="fancy-button.html"> <fancy-button> fancy button </fancy-button>
)5.-*NQPSUT… IUUQTHJUIVCDPNXDXFCDPNQPOFOUTJTTVFTJTTVFDPNNFOU
)5.-.PEVMFT… IUUQTHJTUHJUIVCDPN5BLBZPTIJ,PDIJGEDFEGECCEBGFGF
import fancy from './fancy.html' as HTMLTemplateElement; export class FancyButton extends
HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }).appendChild(fancy.content.cloneNode(true)); } }
&4.PEVMFT
&4.PEVMFTהכ ‣ &4.PEVMFTךـٓؐؠ㹋鄲 ‣ TDSJQUUZQFˑNPEVMF˒ד+BWB4DSJQUؿ؋؎ٕٗ٦سׅ ‣ TDSJQUOPNPEVMFדꬊ㼎䘔橆㞮罋䣁ׅ ‣ &4.PEVMFTך/PEFKT㹋鄲 ‣
NKT&4.PEVMFTך+BWB4DSJQUؿ؋؎ٕה׃גٗ٦سׅ
export default class FancyButton { ... } GBODZCVUUPOKT
import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes
from 'prop-types'; import FancyButton from './fancy-button.js'; JOEFYKT
<script type="module"> import FancyButton from './fancy-button.js'; customElements .define('fancy-button', FancyButton); </script>
4IBEPX%0. $VTUPN&MFNFOUT &4.PEVMFT
class FancyButton extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open'
}).innerHTML = ` <style>button { … }</style> <button><slot></slot></button> `; } } customElements .define('fancy-button', FancyButton);
export default class FancyButton extends HTMLElement { connectedCallback() { this.attachShadow({
mode: 'open' }).innerHTML = ` <style>button { … }</style> <button><slot></slot></button> `; } }
<fancy-button> fancy button </fancy-button> <script type="module"> import FancyButton from './fancy-button.js';
customElements .define('fancy-button', FancyButton); </script>
8FCחֶֽ鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣鴥$44ך䕦갟眔㔲ָ鎘濼זְ ‣ せ瑞ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ䗳銲ָ֮ ‣ ⡲鿇ㅷⱄⵃ欽׃חְֻ ‣
)5.- $44 +BWB4DSJQUתה➬穈ָזְ ‣ תה鿇ㅷꂁ䋒ׅؒ؝ءأذيָזַ
4IBEPX%0. $VTUPN&MFNFOUT &4.PEVMFT OQN ZBSO 8FCחֶֽ鿇ㅷךꨇ׃ׁ ‣ )5.-ה$44חأ؝٦فָ㶷㖈׃זְ ‣ 铣鴥$44ך䕦갟眔㔲ָ鎘濼זְ
‣ せ瑞ָ遼瑱׃זְ״ֲծ䌢ח䠐陎ׅ䗳銲ָ֮ ‣ ⡲鿇ㅷⱄⵃ欽׃חְֻ ‣ )5.- $44 +BWB4DSJQUתה➬穈ָזְ ‣ תה鿇ㅷꂁ䋒ׅؒ؝ءأذيָזַ
1PMZNFS4VNNJU JO$PQFOIBHFO
#PXFSJTEFQSFDBUFE
6TFOQN ZBSO
// fancy-button v1.0.0 customElements .define('fancy-button', FancyButton); // fancy-button v1.1.0 customElements
.define('fancy-button', FancyButton); ZBSO⢪ֲץֹ椚歋 ☠ ⣛㶷ٌآُ٦ٕؿٓحزזخٔ٦ד鍑寸דֹ✨
‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF
8FC$PNQPOFOUTTBOECPY IUUQTDIHJUIVCJPXFCDPNQPOFOUTTBOECPY
‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF
✅ ✅ $VTUPN&MFNFOUTW 4IBEPX%0.W 5FNQMBUFT &4.PEVMFT ✅ ✅ ✅ ✅
✅ ✅ ✅ ✅ ✅ ✅ 䎃猧ـٓؐؠ؟ه٦ز
8FC$PNQPOFOUT JT BWBJMBCMFOPX PO UIFNPCJMFXFC✨
None
:PV5VCFJTCVJMU POUIFUPQPG1PMZNFS
None
6TFXFCDPNQPOFOUTKT ‣ $VTUPN&MFNFOUTWךهٔؿ؍ٕ ‣ 4IBEZ%0.4IBEPX%0.ך%0."1*هٔؿ؍ٕ ‣ 4IBEZ$444IBEPX%0.ךأة؎ٕꟼ鸬هٔؿ؍ٕ ‣ )5.-*NQPSUT
8IZ4IBEZ%0. ‣ %0.خٔ٦ך،ؙإ؟ⵖ䖴ׅךָꨇ׃ְ ‣ ぐ珏%0."1*װ/PEF-JTUךؒىُٖ٦زָꨇ׃ְ ‣ EPDVNFOUCPEZ瘝ך،ؙإ؟♳剅ֹדֹזְ ‣ ؝٦سꆀָ花㣐חז♳ծػؿؓ٦وٝأח䕦갟ׅ
‣ 4IBEZ%0."1*➜׃ג،ؙإأׇׁ ‣ 㸜㹀䚍⥂אאծػؿؓ٦وٝأ⳿ׅ
None
8FC$PNQPOFOUT JTBMTP BWBJMBCMFOPX PO UIFEFTLUPQXFC
‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF
"DDFTTJCJMJUZ ‣ 4IBEPX%0.ך)5.-،ؙإءـٕח ‣ 鸐䌢ך%0.ず圫חծإوٝذ؍ؙأ䠐陎ׅ ‣ )5.-ֽד♶⼧ⴓז㜥さכծ8"*"3*"ד؟ه٦زׅ ‣ 孡חזךכأ؝٦فⰻפך،ؙإأ ‣
4IBEPX%0.ָꪪ⳿ׁגְֽ ‣ ،ؙإءؽٔذ؍ָ⡚ְ؝ٝه٦طٝز⢪ֲ㜥さכ˘
<fancy-button> #shadow-root fancy button </fancy-button> <style> button { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <button> <slot></slot> </button> &YQPTFE
<fancy-button> #shadow-root fancy button </fancy-button> <style> div { background: #0086b3;
color: white; padding: 1em; border-radius: 0.5em; border: none; } </style> <div role="button" tabindex="0"> <slot></slot> </div> &YQPTFE
‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF
-PBE1FSGPSNBODF ‣ TDSJQUח״؝ٝه٦طٝزךٗ٦س ‣ ؙٔؒأز侧כ)551ד֮ל孡ח׃ֺׅזֻג葺ְ ‣ ؝ٝه٦طٝزך+BWB4DSJQUؿ؋؎ٕכNJOJGZׅ ‣ UZQFˑNPEVMF˒㾩䚍ח״EFGFSٗ٦س ‣
ؔفءّٝדBTZOD㾩䚍➰♷דֹ
TDSJQUח״ぐ珏ٗ٦س IUUQTIUNMTQFDXIBUXHPSHNVMUJQBHFTDSJQUJOHIUNMUIFTDSJQUFMFNFOU
ثُ٦صؚٝه؎ٝز ‣ ٔا٦أ㙵鴥ךַٍؗحءُׅךַ ‣ 㙵鴥כ剑傍ֻٖٝتֲָׁؚٔٝծⴱ劍ٗ٦سָ曯暨חז ‣ ״כ$BDIF$POUSPMقحتװ4FSWJDF8PSLFSזודٍؗحءُ׃ְ ‣ ⴱ劍ٗ٦س傍ְ ‣
MJOLSFMˑQSFMPBE˒ד"5'חꟼٔا٦أٗ٦س׃גֶֻ ‣ 如㔐鼂獳ח䗳銲זٔا٦أכMJOLSFMˑQSFGFUDI˒דٗ٦س׃גֶֻ
‣ #SPXTFS4VQQPSU ‣ "DDFTTJCJMJUZ ‣ -PBE1FSGPSNBODF ‣ 3FOEFS1FSGPSNBODF
3FOEFS1FSGPSNBODF ‣ -JHIU%0.ה4IBEPX%0.ך䊴 ‣ 4IBEPX%0.ךךךכـٓؐؠ㹋鄲ך剑黝⻉ח㨻י״ֲ ‣ ע㣐䊴כזְ⦐➂ך✮䟝דׅ ‣ 7JSUVBM%0.ח״䊴ⴓ䲽歗ך⡭㖑 ‣
➙תד鸐3FBDUזוך7JFXٓ؎ـٓٔה穈さׇ ‣ 8FC$PNQPOFOUTⰻד䊴ⴓ䲽歗㹋倵ׅ
import React from 'react'; export default class Button extends React.Component
{ handleClick(e) { if (this.props.onClick) { this.props.onClick(e); } } render() { const handleClick = this.handleClick.bind(this); return ( <fancy-button onClick={handleClick}> {this.props.children} </fancy-button> ); } }
1PMZNFS-BCTMJUIUNM ‣ 5BHHFE5FNQMBUF-JUFSBMדUFNQMBUF⢪ֲ➬穈 ‣ IUNMAAדذٝفٖ٦ز⡲ծSFOEFS ד)5.-欰䧭ׅ ‣ SFOEFS ד床ׅ⹛涸ז鿇ⴓך䊴ⴓ䲽歗ׅ
const helloTemplate = (name) => html`<div>Hello ${name}!</div>`; // renders <div>Hello
Steve!</div> to the document body render(helloTemplate('Steve'), document.body); // updates to <div>Hello Kevin!</div>, but only updates the ${name} part render(helloTemplate('Kevin'), document.body);
import { html, render } from './lit-html.js'; export default class
IconButton extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); render(this.template, this.shadowRoot); } get template() { return html` <style>...</style> <button> <i class="${this.getAttribute('icon')}"></i> <slot></slot> </button> `; } };
תה ‣ 8FC$PNQPOFOUTחꟼׅぐ珏➬圫ָ㸜㹀׃גֹ ‣ ـٓؐؠ㹋鄲滠㹋ח鹌ծ暴חٌغ؎ٕ8FCדכه ٔؿ؍ٕז׃ד⢪ִ ‣ ➙⢪גְ䪮遭أةحؙח《鴥דְֽ ‣ ـٓؐؠⰻ鿇Ⳣ椚ך剑黝⻉䖉אאծطحزٙ٦ؙ
ꟼ鸬כ㛇劤ח屟ثُ٦صؚٝד0,
:PVBSFSFBEZUPVTF 8FC$PNQPOFOUT✨
5IBOLZPV !DI "DI