Upgrade to Pro — share decks privately, control downloads, hide ads and more …

最近の Web パフォーマンス改善について知っておきたいコト

Ayumu Sato
September 24, 2017

最近の Web パフォーマンス改善について知っておきたいコト

HTML5 Conference 2017 http://events.html5j.org/conference/2017/9/ で使用したスライドです。本編45分。

Ayumu Sato

September 24, 2017
Tweet

More Decks by Ayumu Sato

Other Decks in Programming

Transcript

  1. 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/
  2. 6*ךٖأهٝأ NT ،صً٦ءّٝG NT NT ،؎سٕ⚥ךⳢ椚 NT ل٦آٗ٦س  NT

    WJBIUUQTEFWFMPQFSTHPPHMFDPNXFCGVOEBNFOUBMTQFSGPSNBODFSBJM ו׸ֻ׵ְז׵黝ⴖז䘔瘶鸞䏝ה鎉ִ׷ךַ ٓٝة؎ي
  3. MPEBTI,#   SFBDUEPN,#   SY,#   BDNFKT,#

      DPSFKT,#   WFMPDJUZBOJNBUF,#   JNNVUBCMF,#   SFBDU,#  ˟NJOJGZ黝欽䖓ծH[JQ黝欽⵸ Generated by https://alexkuz.github.io/webpack-chart
  4. <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ぐ⡘
  5. 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♧鿇何㢌
  6. 〢➿ ـٓؐؠ؎كٝز劍 %0.$POUFOU-PBEFE MPBE ـٓؐؠ؎كٝزד➿欽׃גְ׋ 湱ꟼ䚍כ֮׷ָ劤䔲ח鋅׋ְ⦼דכזְ 鵚➿ ؽآُ،ٕ䲽歗ך鎘ꆀ劍 4UBSU3FOEFS 'JSTU1BJOU

     4QFFE*OEFY 䲽歗Ⳣ椚ךة؎ىؚٝחꟼ䗰ָ獳׏׋ 8FC1BHFUFTUָ崧遤׶㨣׭׷ 植➿ ِ٦ؠ٦⡤꿀劍 'JSTU$POUFOUGVM1BJOU 'JSTU.FBOJOHGVM1BJOU 5JNFUP$POTJTUFOUMZ*OUFSBDUJWF ״׶ِ٦ؠ٦⡤꿀ה湫穠ׅ׷䭷垥ָ涫㜥 䠐㄂ָ⠗׻׷邌爙חז׏׋ة؎ىؚٝ 㹋ꥷחⵃ欽〳腉חז׏׋ة؎ىؚٝ ׂ׏ֻ׶ⴓַ׏׋孡חז׸׷䭷垥ך㢌鼂 4FFBMTP8FCؙٓ؎،ٝز؟؎سךػؿؓ٦وٝأًزؙٔأعـ׹ּ IUUQTIBWFMPHBZVNVTBUPDPNEFWFMPQQFSGPSNBODFFQFSGPSNBODF@NFUSJDTIUNM
  7. 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ך《䖤
  8. 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*ד⟣䠐ך挿꟦ך䨽銲儗꟦׾鎘庠ׅ׷⢽
  9. ‣ 㹋꿀㜥ד֮׷4FSWPך䧭卓׾ծ؝ٝه٦طٝزה׃ג(FDLPח《׶鴥׬ ‣ 2VBOUVN$44 4UZMP أة؎ٕⳢ椚הإؙٖةوحثך⚛⴨⻉ ‣ 2VBOUVN3FOEFS0QFO(-ك٦أד$44ח暴⻉׃׋ٖٝتٓפך縧ֹ䳔ִ ‣ 2VBOUVN$PNQPTJUPS$PNQPTJUPSךأٖحسַ׵فٗإأפך杝甧

    ‣ 2VBOUVN%0.ぐةـךوٕثفٗإأأٖحس⻉הأ؛آُ٦ٕ盖椚 ‣ FUD 1SPKFDU2VBOUVN 4FFBMTP.P[JMMBכ2VBOUVNفٗآؙؑزד麓⿠ה鏐ⴽ׃ծ劢勻ח颺ֽ׷ IUUQSPDLSJEHFIBUFOBCMPHDPNFOUSZ
  10. 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); 䖞勻ך銲稆ך歗꬗ⰻךⰅ⳿嗚濼
  11. 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דずֿׄה׾㹋植ׅ׷
  12. ‣ Ⳣ椚ׅץֹةأָؙזֻ㸣ⰋחⰅ⸂䖉׍ךהֹ *EMF ח涪抟ׅ׷؝٦ٕغحؙ ‣ TFU5JNFPVU GO  ״׶䛬䠐涸 ‣

    ؿٖ٦يך刿倜׾⮚⯓דֹ׷ ‣ ⢪ְ麣כ葿ղ֮׶׉ֲ SFRVFTU*EMF$BMMCBDL 6TJOHSFRVFTU*EMF$BMMCBDL]8FC](PPHMF%FWFMPQFST IUUQTEFWFMPQFSTHPPHMFDPNXFCVQEBUFTVTJOHSFRVFTUJEMFDBMMCBDL
  13. 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➬✲׾ׅ׷
  14. ‣ ׉ך銲稆ח㢌刿ָ涪欰ׅ׷ֿה׾ծـٓؐؠח✮デׅ׷فٗػذ؍ ‣ ✉凐חְֲהtransform: translate3d(0, 0, 0)عحؙך姻䒭晛 ‣ (16،ؙإٖٓ٦ءّٝזוծـٓؐؠָ⹧䩛ח剑黝⻉ׅ׷׋׭ךو٦ؚؗٝ $448JMM$IBOHF姻׃ֻ⢪׻זְהⶰ⡲欽ָ֮׷ֽו⤑ⵃ

    .element { transform: scale(1); will-change: transform; } .element.clicked { transform: scale(2); } 4FFBMTP$44XJMMDIBOHFفٗػذ؍חאְג濼׏גֶֻץֹֿה IUUQTEFWPQFSBDPNBSUJDMFTKBDTTXJMMDIBOHFQSPQFSUZ