Share
Embed
最近の Web パフォーマンス改善について知っておきたいコト
HTML5 Conference 2017 http://events.html5j.org/conference/2017/9/ で使用したスライドです。本編45分。
Ayumu Sato
September 24, 2017
Transcript
83 slides
-
‣ ⡟谏娄ׁהֲ֮ײ ‣ せ〢㾊ה幪靼䖂䗁⚥ך8FCر؍كٗحػ٦ ‣ 剑鵚ךꟼ䗰כXFCQFSGהBZ ‣ $ZCFS"HFOU *OD
䪮遭劤鿇8FC*OJUJBUJWF$FOUFSًر؍،窟䭍䪮遭䨌殛㹓 !BIPNV -
PGWJTJUTBSFMJLFMZUPCFBCBOEPOFEJG QBHFTUBLFMPOHFSUIBOTFDPOETUPMPBE The need for mobile speed: How mobile latency
impacts publisher revenue https://www.thinkwithgoogle.com/intl/en-154/insights-inspiration/research-data/need-mobile-speed-how-mobile-latency-impacts-publisher-revenue/ -
‣ شؽ٦ءّٝך㨣ַل٦آָ邌爙ׁתדך鸞䏝 ؙٔذ؍ٕٖؕٝتؚٔٝػأך剑黝⻉ ꂁ⥋ٔا٦أ 歗⫷זו ך侧הؿ؋؎ٕ؟؎ؤך剑黝⻉ )5.-鵤⽱
͑؟٦غ؟؎سⳢ椚 ך넝鸞⻉FUD ل٦آٗ٦س -
ِ٦ؠ٦ 䎃ךأوم 㖑♴ꉟד獳⹛⚥ 4/4ة؎يٓ؎ַٝ ِ٦ؠ٦# 剑倜أوم 㖑倯ח䌓満⚥ ـحؙو٦ַؙ ِ٦ؠ٦$ 䎃ךأوم
궪굸䏄ך窫劄涸8J 锃ץ暟ד嗚稊ַ -
6*ךٖأهٝأ NT ،صً٦ءّٝG NT NT ،؎سٕ⚥ךⳢ椚 NT ل٦آٗ٦س NT
WJBIUUQTEFWFMPQFSTHPPHMFDPNXFCGVOEBNFOUBMTQFSGPSNBODFSBJM וְֻז黝ⴖז䘔瘶鸞䏝ה鎉ִךַ ٓٝة؎ي -
‣ 嚂錁׃ֹזְ傈劤ך鸐⥋笨♴䎂㖱.CQT ٌغ؎ٕ.CQT WJB"LBNBJ24UBUFPGUIF*OUFSOFU$POOFDUJWJUZ3FQPSU ‣ 涪罏ך䠐陎זח넝תגֹגְ ‣ 黝ⴖז歗⫷䕎䒭ד剑黝⻉הַծذؗأزך剑㼭⻉ H[JQהַזװ״י
‣ رְؕ歗⫷ծ搀꼽זٔا٦أծסא٦ח罋ִלتًגⴓַ طحزٙ٦ؙך橆㞮ה涪罏ך䠐陎 -
MPEBTI,# SFBDUEPN,# SY,# BDNFKT,#
DPSFKT,# WFMPDJUZBOJNBUF,# JNNVUBCMF,# SFBDU,# ˟NJOJGZ黝欽䖓ծH[JQ黝欽 Generated by https://alexkuz.github.io/webpack-chart -
‣ [PQJכEFBUF✼䳔דծְַֻ㖇簭桦ָ넝ְ את"DDFQU&ODPEJOHH[JQזؙٓ؎،ٝز湱䩛ז⢪ִ 鸐䌢ךH[JQ״儗ַֽג♨㻝ח㖇簭ׅأة؎ٕ̔H[JQ@TUBUJD嗚鎢ׅה葺 ‣ CSPUMJכ倜鋉ך،ٕ؞ٔؤيדծ[PQJ״刿ח넝㖇簭 "DDFQU&ODPEJOHCS鵤ׇךכ&EHF
'JSFGPY $ISPNFծֲּׅ4BGBSJ [PQJ CSPUMJוأ؎أךػٝךせ׃ְ -
‣ 1SFMPBEכ植㖈ךل٦آךח䭷㹀ٔا٦أ⮚⯓׃גٗ٦سׅ ‣ 3FTPVSDF)JOUTכ⟃꣬ךل٦آךח䫎堣涸Ⳣ椚ׅ EOTQSFGFUDI%/4鍑寸ך✲Ⳣ椚 QSFDPOOFDU5$1䱸竲ך✲Ⳣ椚 QSFGFUDIٔا٦أ《䖤ך✲Ⳣ椚
QSFSFOEFSل٦آךٖٝتؚٔٝך✲Ⳣ椚 1SFMPBE 3FTPVSDF)JOUTזהזֻ⡂גֽוⴽ➬圫 -
<link rel="preload" href="font.woff" as="font" crossorigin> <link rel="stylesheet" href="main.css"> <link rel="dns-prefetch"
href="//cdn.example.com"> <link rel="preconnect" href="https://api.example.com"> <link rel="prefetch" href="/libs.js" as="script"> <link rel="prerender" href="/next-page.html"> $44鐰⣣ח1SFMPBEד8FCؿؓٝزך⯓遤ٗ٦س 8FCؿؓٝز䖉ד涪欰ׅذؗأزךٖٝتؚٔٝـٗحؙ鯪幾 3FTPVSDF)JOUTぐ⡘ -
‣ 暴㹀橆㞮ַ8FC؟؎زח،ؙإأ׃גر٦ة ꧊ ‣ 植㹋ךِ٦ؠדכזְָ鸞䏝ך♳♴鐰⣣׃װְׅ ‣ 畭劣װ㔐简זו勴⟝؝ٝزٗ٦ٕדֹ ‣ 鑫稢ז䞔㜠הךד涪罏כְָ֮ 4ZOUIFUJD.POJUPSJOH Ý
☁⚙ ⬇ ⬇ 8FC؟؎زח ،ؙإأ׃ג鎘庠 ؙٓؐس♳ךؒ٦آؑٝز 鎘庠ر٦ة꧊琎 -
‣ ؒٝسِ٦ؠך畭劣♳ד鎸ꐮ׃ر٦ة ꧊ ‣ 㹋ꥷחِ٦ؠָ⡤꿀׃⦼ה ‣ 鑫稢זفٗؿ؋؎ٕ鋅ךדכזְ ‣ ,1*הךꟼ鸬鋅זֿךקֲָ葺ְ 3FBM6TFS.POJUPSJOH ☁
Ý ⬇ ➡ ⬇ 鎘庠ر٦ة꧊琎 ؒٝسِ٦ؠ橆㞮ד䞔㜠《䖤 -
dumpTiming(performance.timing); performance.getEntriesByType('resource').forEach(dumpTiming); // φϏήʔγϣϯ·ͨϦιʔεͷϩʔυʹ͓͚Δ֤ϑΣʔζͷॴཁ࣌ؒΛग़ྗ function dumpTiming(timing) { console.log(` Name: ${timing.name
|| location.href} Unload: ${timing.unloadEventEnd - timing.unloadEventStart} Redirect: ${timing.redirectEnd - timing.redirectStart} DNS: ${timing.domainLookupEnd - timing.domainLookupStart} TCP: ${timing.connectEnd - timing.connectStart} Request: ${timing.responseStart - timing.requestStart} Response: ${timing.responseEnd - timing.responseStart} Processing: ${timing.loadEventStart - timing.responseEnd} OnLoad: ${timing.loadEventEnd - timing.loadEventStart}`); } /BWJHBUJPO5JNJOH"1* 3FTPVSDF5JNJOH"1* WJBIUUQTDIOFUQPTUTQFSGPSNBODFBQJIUNM♧鿇何㢌 -
〢➿ ـٓؐؠ؎كٝز劍 %0.$POUFOU-PBEFE MPBE ـٓؐؠ؎كٝزד➿欽׃גְ 湱ꟼ䚍כָ֮劤䔲ח鋅ְ⦼דכזְ 鵚➿ ؽآُ،ٕ䲽歗ך鎘ꆀ劍 4UBSU3FOEFS 'JSTU1BJOU
4QFFE*OEFY 䲽歗Ⳣ椚ךة؎ىؚٝחꟼ䗰ָ獳 8FC1BHFUFTUָ崧遤㨣 植➿ ِ٦ؠ٦⡤꿀劍 'JSTU$POUFOUGVM1BJOU 'JSTU.FBOJOHGVM1BJOU 5JNFUP$POTJTUFOUMZ*OUFSBDUJWF ״ِ٦ؠ٦⡤꿀ה湫穠ׅ䭷垥ָ涫㜥 䠐ָ⠗邌爙חזة؎ىؚٝ 㹋ꥷחⵃ欽〳腉חזة؎ىؚٝ ֻׂⴓַ孡חז䭷垥ך㢌鼂 4FFBMTP8FCؙٓ؎،ٝز؟؎سךػؿؓ٦وٝأًزؙٔأعـּ IUUQTIBWFMPHBZVNVTBUPDPNEFWFMPQQFSGPSNBODFFQFSGPSNBODF@NFUSJDTIUNM -
const observer = new PerformanceObserver((list) => { for (const entry
of list.getEntries()) { // `name` will be either 'first-paint' or 'first-contentful-paint'. const metricName = entry.name; const time = Math.round(entry.startTime + entry.duration); ga('send', 'event', { eventCategory: 'Performance Metrics', eventAction: metricName, eventValue: time, nonInteraction: true, }); } }); // Start observing paint entries. observer.observe({entryTypes: ['paint']}); WJBIUUQTEFWFMPQFSTHPPHMFDPNXFCVQEBUFTVTFSDFOUSJDQFSGPSNBODFNFUSJDTUSBDLJOH@GQGDQ 1BJOU5JNJOH"1*ח״'1ה'$1ך《䖤 -
let reqCount = 0; const req = new XMLHttpRequest(); req.open('GET',
url, true); performance.mark('mark_start_xhr'); req.onload = (e) => { performance.mark('mark_end_xhr'); reqCnt++; performance.measure( `measure_xhr_${reqCnt}`, 'mark_start_xhr', 'mark_end_xhr' ); do_something(e.responseText); } req.send(); const entries = performance.getEntriesByType('measure'); entries.forEach((e)=>console.log(`XHR ${e.name} took ${e.duration}ms`)) WJBIUUQTXXXIUNMSPDLTDPNKBUVUPSJBMTXFCQFSGPSNBODFVTFSUJNJOH♧鿇何㢌 6TFS5JNJOH"1*ד⟣䠐ך挿ך䨽銲儗鎘庠ׅ⢽ -
‣ ؾٝه؎ٝزד鸞ֻׅىحءָّٝ䗳銲זֿה֮חכָ֮ ‣ ✮皾 㛇彊⦼ 寸ծ״鹼ֻזזְ״ֲ麊欽ׅךָك٦أٓ؎ٝ ‣ 傈䌢涸ח侧㶵הぢֹさגֿ溪䔲ז넝鸞⻉ך䩛ָ䩧ג ‣ 剣俱ֽו4QFFE$VSWFכֶ䩛鯪ד涪罏ָ㥨ֲֹז䠬ׄ
✮皾ך鏣㹀ה㹀䌢涸ז鎘庠 4FFBMTP1FSGPSNBODF#VEHFU.FUSJDT IUUQTUJNLBEMFDDPNQFSGPSNBODFCVEHFUNFUSJDT -
‣ 㹋꿀㜥ד֮4FSWPך䧭卓ծ؝ٝه٦طٝزה׃ג(FDLPח《鴥 ‣ 2VBOUVN$44 4UZMP أة؎ٕⳢ椚הإؙٖةوحثך⚛⻉ ‣ 2VBOUVN3FOEFS0QFO(-ك٦أד$44ח暴⻉׃ٖٝتٓפך縧ֹ䳔ִ ‣ 2VBOUVN$PNQPTJUPS$PNQPTJUPSךأٖحسַفٗإأפך杝甧
‣ 2VBOUVN%0.ぐةـךوٕثفٗإأأٖحس⻉הأ؛آُ٦ٕ盖椚 ‣ FUD 1SPKFDU2VBOUVN 4FFBMTP.P[JMMBכ2VBOUVNفٗآؙؑزד麓ה鏐ⴽ׃ծ劢勻ח颺ֽ IUUQSPDLSJEHFIBUFOBCMPHDPNFOUSZ -
const target = document.getElementById('target'); let viewport = getViewportSize(); function getViewportSize()
{ return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }; } window.addEventListener('scroll', () => { const { width, height } = viewport; const rect = target.getBoundingClientRect(); // ਫฏํʹ͓͍ͯཁૉͷҰ෦·ͨશ෦͕ը໘ʹଘࡏ͠ಘΔ͔ const isInHorizontal = rect.left > 0 && rect.left < width || rect.right > 0 && rect.right < width || rect.left < 0 && rect.right > width; // ਨํʹ͓͍ͯཁૉͷҰ෦·ͨશ෦͕ը໘ʹଘࡏ͠ಘΔ͔ const isInVertical = rect.top > 0 && rect.top < height || rect.bottom > 0 && rect.bottom < height || rect.top < 0 && rect.bottom > height; // ཁૉͷҰ෦·ͨશ෦͕ը໘ʹଘࡏ͢Δ͔ if (isInHorizontal && isInVertical) console.log('ཁૉ͕ը໘ʹೖΓ·ͨ͠'); else console.log('ཁૉ͕ը໘͔Βग़·ͨ͠'); }, false); 䖞勻ך銲稆ך歗ⰻךⰅ⳿嗚濼 -
const target = document.getElementById('target'); const observer = new IntersectionObserver(entries =>
{ const entry = entries[0]; // ཁૉ͕গ͠Ͱը໘ʹೖ͍ͬͯΕਅ if (entry.intersectionRatio > 0) { console.log('ཁૉ͕ը໘ʹೖΓ·ͨ͠'); } else { console.log('ཁૉ͕ը໘͔Βग़·ͨ͠'); } }); observer.observe(target); *OUFSTFDUJPO0CTFSWFSדずֿׄה㹋植ׅ -
‣ Ⳣ椚ׅץֹةأָؙזֻ㸣ⰋחⰅ⸂䖉ךהֹ *EMF ח涪抟ׅ؝٦ٕغحؙ ‣ TFU5JNFPVU GO ״䛬䠐涸 ‣
ؿٖ٦يך刿倜⮚⯓דֹ ‣ ⢪ְ麣כ葿ղֲ֮ SFRVFTU*EMF$BMMCBDL 6TJOHSFRVFTU*EMF$BMMCBDL]8FC](PPHMF%FWFMPQFST IUUQTEFWFMPQFSTHPPHMFDPNXFCVQEBUFTVTJOHSFRVFTUJEMFDBMMCBDL -
function myNonEssentialWork (deadline) { // rIC ͷ࣋ͪ࣌ؒ 50ms Ͱ͋ΓɺtimeRemaining() ͦͷΓ࣌ؒΛฦ͢
while (deadline.timeRemaining() > 0 && tasks.length > 0) { tasks.shift()(); } if (tasks.length > 0) { requestIdleCallback(myNonEssentialWork); } } requestIdleCallback(myNonEssentialWork); SFRVFTU*EMF$BMMCBDLד内זהֹח剑㣐NT➬✲ׅ -
‣ ך銲稆ח㢌刿ָ涪欰ֿׅהծـٓؐؠח✮デׅفٗػذ؍ ‣ ✉凐חְֲהtransform: translate3d(0, 0, 0)عحؙך姻䒭晛 ‣ (16،ؙإٖٓ٦ءّٝזוծـٓؐؠָ䩛ח剑黝⻉ׅךو٦ؚؗٝ $448JMM$IBOHF姻׃ֻ⢪זְהⶰ⡲欽ָֽ֮ו⤑ⵃ
.element { transform: scale(1); will-change: transform; } .element.clicked { transform: scale(2); } 4FFBMTP$44XJMMDIBOHFفٗػذ؍חאְג濼גֶֻץֹֿה IUUQTEFWPQFSBDPNBSUJDMFTKBDTTXJMMDIBOHFQSPQFSUZ -
‣ أة؎ٕծٖ؎،ؐزծ䲽歗ך鎘皾眔㔲ꣲ㹀׃ג剑黝⻉דֹ ‣ ֮銲稆ⰻך朐䡾ח״㢩歲פך䕦갟㼓ׄ鴥فٗػذ؍ DPOUBJOTJ[F̔䭷㹀ׁ銲稆ך؟؎ؤָ؝ٝذٝخծ㶨㷝銲稆ח䕦갟ׁזֻז DPOUBJOMBZPVU̔䭷㹀ׁ銲稆ָ鋵⯌䓌銲稆ךٖ؎،ؐزח䕦갟♷ִזֻז DPOUBJOTUZMF̔䭷㹀ׁ銲稆ך㢩ח䕦갟⿹רׅ♧鿇ךأة؎ٕⰻ⩎ד㸣穠ׇׁ
DPOUBJOQBJOU̔䭷㹀ׁ銲稆ך㞮歲ך㢩⩎ח㶨㷝銲稆ָل؎ٝزׁזֻז $44$POUBJONFOU⠗זְ$44فٗػذ؍痥⡘˟⦐➂ך䠬䟝