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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Shogo Sensui
September 24, 2017
Technology
9.2k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
The State of Web Components
2017年9月24日に開催された HTML5 Conference 2017 の「The State of Web Components」のセッション資料です。
Shogo Sensui
September 24, 2017
More Decks by Shogo Sensui
See All by Shogo Sensui
三年間の関わりから見る PR TIMES エンジニアリングの変化 / Transition of PRTimes Engineering
1000ch
0
2.6k
EU のデジタル市場法と Apple / DMA and Apple
1000ch
0
170
Web Share API
1000ch
0
200
2023 年の Web 開発のベースライン / Web Development Baseline 2023
1000ch
0
100
開発生産性と組織 / Productivity and Organization
1000ch
0
1.3k
なぜ私達は働くのか / Why We Work?
1000ch
0
130
新しいメルカリ Web とそのパフォーマンス / The New Mercari Web and its performance
1000ch
0
160
Web Standards Interop 2022
1000ch
0
390
パフォーマンスを高める CSS / Performance Optimized CSS
1000ch
1
890
Other Decks in Technology
See All in Technology
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
0
370
生成 AI × MCP で切り拓く次世代 SRE!自律型運用への挑戦と開発者体験の進化
_awache
0
170
Dynamic Workersについて
yusukebe
2
630
チームで実践する AI-DLC 思考の軌跡を残すチェックポイント設計
belongadmin
0
2.9k
製造業のクラウド活用最適解〜AI,DXを加速するデータ基盤の作り方〜
hamadakoji
0
410
Djangoユーザが知っ得なPostgreSQL機能 - 設計の選択肢を増やす / Djang-use-PostgreSQL
soudai
PRO
0
210
探して_入れて_作って_使う_Agent_Skills___LT.pdf
peintangos
2
180
AI Testing Talks: Challenges of Applying AI in Software Testing: From Hype to Practical Use
exactpro
PRO
1
140
非定型業務をAI slackbotで自動化する ~ 社内要望を自動壁打ちするbotを作った ~/automating-ad-hoc-work-with-ai-slackbot
shibayu36
0
150
AIプラットフォームを運用し続けるための可観測性
tanimuyk
4
1.1k
実装は速くなった、レビューはどうする? ― 自身のレビューをAIで再現させるサーヴァントエンジニアリングのすゝめ / Implementation got faster. So what about reviews? — An invitation to Servant Engineering: Recreating your own code reviews with AI
nrslib
7
4.2k
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/3 - 2026/5
oracle4engineer
PRO
1
210
Featured
See All Featured
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
310
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.2k
What's in a price? How to price your products and services
michaelherold
247
13k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
220
Thoughts on Productivity
jonyablonski
76
5.2k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
320
Abbi's Birthday
coloredviolet
2
8k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Scaling GitHub
holman
464
140k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.5k
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