From 612d84431164fbb0c0f0cd25a4ce98e5ff5ae61e Mon Sep 17 00:00:00 2001 From: SooY2 Date: Fri, 25 Jul 2025 12:43:05 +0900 Subject: [PATCH] feat: preload --- optimization-http2/css/style1.css | 49 +++++ optimization-http2/css/style2.css | 69 +++++++ optimization-http2/css/style3.css | 114 ++++++++++++ optimization-http2/css/style4.css | 258 ++++++++++++++++++++++++++ optimization-http2/css/style5.css | 145 +++++++++++++++ optimization-http2/index.html | 292 ++++++++++++++++++++++++++++++ optimization-http2/js/app1.js | 31 ++++ optimization-http2/js/app2.js | 52 ++++++ optimization-http2/js/app3.js | 57 ++++++ optimization-http2/js/app4.js | 69 +++++++ optimization-http2/js/app5.js | 109 +++++++++++ 11 files changed, 1245 insertions(+) create mode 100644 optimization-http2/css/style1.css create mode 100644 optimization-http2/css/style2.css create mode 100644 optimization-http2/css/style3.css create mode 100644 optimization-http2/css/style4.css create mode 100644 optimization-http2/css/style5.css create mode 100644 optimization-http2/js/app1.js create mode 100644 optimization-http2/js/app2.js create mode 100644 optimization-http2/js/app3.js create mode 100644 optimization-http2/js/app4.js create mode 100644 optimization-http2/js/app5.js diff --git a/optimization-http2/css/style1.css b/optimization-http2/css/style1.css new file mode 100644 index 0000000..ddbc178 --- /dev/null +++ b/optimization-http2/css/style1.css @@ -0,0 +1,49 @@ +/* style1.css - Base styles and typography */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'pretendard', sans-serif; + line-height: 1.6; + color: #333; + background-color: #ffffff; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +.section { + padding: 80px 0; + opacity: 0; + transform: translateY(30px); + transition: all 0.8s ease; +} + +.section.visible { + opacity: 1; + transform: translateY(0); +} + +.section-title { + font-size: 2.5rem; + font-weight: 700; + color: #2563eb; + margin-bottom: 20px; + text-align: center; +} + +.section-description { + font-size: 1.1rem; + color: #64748b; + margin-bottom: 30px; + text-align: center; + max-width: 800px; + margin-left: auto; + margin-right: auto; +} diff --git a/optimization-http2/css/style2.css b/optimization-http2/css/style2.css new file mode 100644 index 0000000..2ab68f2 --- /dev/null +++ b/optimization-http2/css/style2.css @@ -0,0 +1,69 @@ +/* style2.css - Header and navigation styles */ +.header { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.nav-brand { + font-size: 1.8rem; + font-weight: 700; + color: white; + text-decoration: none; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.brand-icon { + width: 32px; + height: 32px; + filter: brightness(0) invert(1); +} + +.nav-menu { + display: flex; + list-style: none; + gap: 2rem; +} + +.nav-menu a { + color: white; + text-decoration: none; + font-weight: 500; + transition: color 0.3s ease; + padding: 0.5rem 1rem; + border-radius: 5px; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.nav-icon { + width: 16px; + height: 16px; + filter: brightness(0) invert(1); +} + +.nav-menu a:hover { + background-color: rgba(255, 255, 255, 0.2); + color: #e0f2fe; +} + +/* Add top margin to body to account for fixed header */ +body { + margin-top: 70px; +} \ No newline at end of file diff --git a/optimization-http2/css/style3.css b/optimization-http2/css/style3.css new file mode 100644 index 0000000..2852dc2 --- /dev/null +++ b/optimization-http2/css/style3.css @@ -0,0 +1,114 @@ +/* style3.css - Introduction section styles */ +.intro-section { + background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); + min-height: 100vh; + display: flex; + align-items: center; +} + +.content-wrapper { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; +} + +.intro-icons { + display: flex; + gap: 1rem; + margin-bottom: 1rem; + justify-content: flex-start; +} + +.intro-icon { + width: 48px; + height: 48px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.text-content .section-title { + text-align: left; + font-size: 3rem; + margin-bottom: 1.5rem; +} + +.text-content .section-description { + text-align: left; + font-size: 1.2rem; + margin-bottom: 2rem; +} + +.feature-highlights { + display: flex; + gap: 2rem; + margin-bottom: 2rem; + flex-wrap: wrap; +} + +.highlight-item { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1rem; + background: rgba(59, 130, 246, 0.1); + border-radius: 20px; + border: 1px solid rgba(59, 130, 246, 0.2); +} + +.highlight-icon { + width: 20px; + height: 20px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.highlight-item span { + font-size: 0.9rem; + color: #2563eb; + font-weight: 500; +} + +.cta-button { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + color: white; + border: none; + padding: 15px 30px; + font-size: 1.1rem; + font-weight: 600; + border-radius: 8px; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.button-icon { + width: 20px; + height: 20px; + filter: brightness(0) invert(1); +} + +.cta-button:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(59, 130, 246, 0.4); +} + +.image-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; +} + +.grid-image { + width: 100%; + height: 150px; + object-fit: cover; + border-radius: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + transition: transform 0.3s ease; +} + +.grid-image:hover { + transform: scale(1.05); +} \ No newline at end of file diff --git a/optimization-http2/css/style4.css b/optimization-http2/css/style4.css new file mode 100644 index 0000000..fc4c724 --- /dev/null +++ b/optimization-http2/css/style4.css @@ -0,0 +1,258 @@ +/* style4.css - Features and performance section styles */ +.features-section { + background-color: #ffffff; +} + +.section-header { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + margin-bottom: 3rem; +} + +.section-icon { + width: 40px; + height: 40px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; + margin: 3rem 0; +} + +.feature-card { + background: white; + border-radius: 12px; + padding: 2rem; + text-align: center; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + transition: all 0.3s ease; + border: 1px solid #e2e8f0; +} + +.feature-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); +} + +.feature-header { + position: relative; + margin-bottom: 1.5rem; +} + +.feature-icon { + position: absolute; + top: 10px; + right: 10px; + width: 32px; + height: 32px; + background: white; + border-radius: 50%; + padding: 6px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); + z-index: 1; +} + +.feature-image { + width: 100%; + height: 200px; + object-fit: cover; + border-radius: 8px; +} + +.feature-card h3 { + font-size: 1.3rem; + color: #2563eb; + margin-bottom: 1rem; + font-weight: 600; +} + +.feature-card p { + color: #64748b; + line-height: 1.6; + margin-bottom: 1rem; +} + +.feature-tags { + display: flex; + justify-content: center; + gap: 0.5rem; +} + +.tag { + display: flex; + align-items: center; + gap: 0.3rem; + background: rgba(59, 130, 246, 0.1); + color: #2563eb; + padding: 0.3rem 0.8rem; + border-radius: 15px; + font-size: 0.8rem; + font-weight: 500; +} + +.tag-icon { + width: 14px; + height: 14px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.tools-section { + margin: 4rem 0; + text-align: center; +} + +.tools-title { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + font-size: 1.5rem; + color: #2563eb; + margin-bottom: 2rem; +} + +.tools-icon { + width: 32px; + height: 32px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.tools-grid { + display: flex; + justify-content: center; + gap: 3rem; + flex-wrap: wrap; +} + +.tool-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 0; +} + +/* style4.css - Features and performance section styles */ +.features-section { + background-color: #ffffff; +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; + margin: 3rem 0; +} + +.feature-card { + background: white; + border-radius: 12px; + padding: 2rem; + text-align: center; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + transition: all 0.3s ease; + border: 1px solid #e2e8f0; +} + +.feature-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); +} + +.feature-image { + width: 100%; + height: 200px; + object-fit: cover; + border-radius: 8px; + margin-bottom: 1.5rem; +} + +.feature-card h3 { + font-size: 1.3rem; + color: #2563eb; + margin-bottom: 1rem; + font-weight: 600; +} + +.feature-card p { + color: #64748b; + line-height: 1.6; +} + +.additional-images { + display: flex; + justify-content: center; + gap: 2rem; + margin-top: 3rem; +} + +.additional-image { + width: 200px; + height: 150px; + object-fit: cover; + border-radius: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); +} + +/* Performance Section */ +.performance-section { + background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%); +} + +.performance-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; +} + +.performance-text .section-title { + text-align: left; +} + +.performance-text .section-description { + text-align: left; +} + +.performance-stats { + display: flex; + gap: 2rem; + margin-top: 2rem; +} + +.stat-item { + text-align: center; +} + +.stat-number { + display: block; + font-size: 1.2rem; + font-weight: 700; + color: #2563eb; +} + +.stat-label { + display: block; + font-size: 0.9rem; + color: #64748b; + margin-top: 0.5rem; +} + +.performance-images { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; +} + +.perf-image { + width: 100%; + height: 120px; + object-fit: cover; + border-radius: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); +} \ No newline at end of file diff --git a/optimization-http2/css/style5.css b/optimization-http2/css/style5.css new file mode 100644 index 0000000..bb51555 --- /dev/null +++ b/optimization-http2/css/style5.css @@ -0,0 +1,145 @@ +/* style5.css - Contact section and footer styles */ +.contact-section { + background-color: #ffffff; +} + +.contact-content { + display: grid; + grid-template-columns: 2fr 1fr; + gap: 4rem; + align-items: start; +} + +.contact-info .section-title { + text-align: left; +} + +.contact-info .section-description { + text-align: left; + margin-bottom: 2rem; +} + +.resource-categories { + display: grid; + gap: 2rem; +} + +.resource-category h4 { + display: flex; + align-items: center; + gap: 0.5rem; + color: #2563eb; + font-size: 1.2rem; + margin-bottom: 1rem; +} + +.category-icon { + width: 24px; + height: 24px; + filter: brightness(0) saturate(100%) invert(27%) sepia(98%) saturate(1896%) hue-rotate(215deg) brightness(91%) contrast(94%); +} + +.resource-list { + list-style: none; + margin-left: 2rem; +} + +.resource-list li { + padding: 8px 0; + border-bottom: 1px solid #e2e8f0; + color: #475569; + font-weight: 500; + position: relative; + padding-left: 30px; +} + +.resource-list li:before { + content: "✓"; + position: absolute; + left: 0; + color: #3b82f6; + font-weight: bold; +} + +.contact-images { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.contact-image { + width: 100%; + height: 200px; + object-fit: cover; + border-radius: 8px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); +} + +/* Footer */ +.footer { + background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); + color: white; + padding: 3rem 0; + text-align: center; +} + +.footer-content { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +.footer-content p { + color: #cbd5e1; + font-size: 0.95rem; +} + +.footer-content p:first-child { + font-weight: 600; + color: white; + font-size: 1.1rem; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .content-wrapper, + .performance-content, + .contact-content { + grid-template-columns: 1fr; + gap: 2rem; + } + + .image-grid { + grid-template-columns: repeat(2, 1fr); + } + + .performance-images { + grid-template-columns: 1fr; + } + + .nav-menu { + display: none; + } + + .section-title { + font-size: 2rem; + } + + .text-content .section-title { + font-size: 2.2rem; + } + + .feature-highlights { + flex-direction: column; + gap: 1rem; + } + + .tools-grid { + gap: 1.5rem; + } + + .intro-icons { + justify-content: center; + } +} \ No newline at end of file diff --git a/optimization-http2/index.html b/optimization-http2/index.html index e69de29..40b0497 100644 --- a/optimization-http2/index.html +++ b/optimization-http2/index.html @@ -0,0 +1,292 @@ + + + + + + H-LAB - optimization http2 + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+
+
+
+

HTTP Performance Lab에 오신 것을 환영합니다

+

+ HTTP/1.1, HTTP/2, HTTP/3의 성능 차이를 실제로 측정하고 비교할 수 있는 + 전문적인 테스트 환경입니다. 다양한 리소스를 통해 실제 웹 사이트 환경을 시뮬레이션합니다. +

+
+
+ Real-time Icon + 실시간 모니터링 +
+
+ Multi-protocol Icon + 다중 프로토콜 +
+
+ Optimization Icon + 최적화 전략 +
+
+ +
+
+ HTTP Lab Image 1 + HTTP Lab Image 2 + HTTP Lab Image 3 + HTTP Lab Image 4 + HTTP Lab Image 5 + HTTP Lab Image 6 +
+
+
+
+ + +
+
+
+

주요 기능

+
+
+
+
+ Monitor Icon + Performance Monitoring +
+

실시간 성능 모니터링

+

Lighthouse와 DevTools를 활용한 정확한 성능 측정

+
+ + Tag Icon + 실시간 + +
+
+
+
+ Protocol Icon + Multi Protocol +
+

다중 프로토콜 지원

+

HTTP/1.1, HTTP/2, HTTP/3 프로토콜별 성능 비교

+
+ + Multi Icon + 멀티 + +
+
+
+
+ Analysis Icon + Resource Analysis +
+

리소스 분석

+

CSS, JS, 이미지, 폰트 등 다양한 리소스 로딩 분석

+
+ + Analysis Icon + 분석 + +
+
+
+
+ Optimization Icon + Network Optimization +
+

네트워크 최적화

+

병렬 연결, 압축, 캐싱 전략 테스트

+
+ + Speed Icon + 최적화 + +
+
+
+
+

+ 지원 도구 +

+
+
+ Lighthouse Icon + Lighthouse +
+
+ DevTools Icon + DevTools +
+
+ WebPageTest Icon + WebPageTest +
+
+
+
+ Additional Image 1 + Additional Image 2 + Additional Image 3 +
+
+
+ + +
+
+
+
+

성능 측정 결과

+

+ 실제 테스트 환경에서 측정된 HTTP 프로토콜별 성능 데이터를 확인하세요. + 각 프로토콜의 장단점과 최적화 전략을 비교 분석할 수 있습니다. +

+
+
+ HTTP/1.1 + 기준 프로토콜 +
+
+ HTTP/2 + 멀티플렉싱 +
+
+ HTTP/3 + 최신 표준 +
+
+
+
+ Performance Chart 1 + Performance Chart 2 + Performance Chart 3 + Performance Chart 4 + Performance Chart 5 +
+
+
+
+ + +
+
+
+

테스트 환경 구성

+
+
+
+

+ 이 테스트 페이지는 다양한 리소스를 포함하여 실제 웹사이트와 + 유사한 환경을 제공합니다. Network 탭에서 로딩 패턴을 확인해보세요. +

+
+
+

+ 스타일시트 +

+
    +
  • CSS 파일 5개 (스타일링)
  • +
  • 반응형 디자인 지원
  • +
  • 애니메이션 효과
  • +
+
+
+

+ 스크립트 +

+
    +
  • JavaScript 파일 5개 (인터랙션)
  • +
  • 성능 모니터링
  • +
  • 사용자 경험 개선
  • +
+
+
+

+ 미디어 +

+
    +
  • 이미지 파일 20개 (JPG/PNG 혼합)
  • +
  • 아이콘 파일 20개 (PNG)
  • +
  • 웹폰트 2개 (Regular/Bold)
  • +
+
+
+
+
+ Contact Image 1 + Contact Image 2 +
+
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/optimization-http2/js/app1.js b/optimization-http2/js/app1.js new file mode 100644 index 0000000..5d88721 --- /dev/null +++ b/optimization-http2/js/app1.js @@ -0,0 +1,31 @@ +// app1.js - Scroll animations and section visibility +document.addEventListener('DOMContentLoaded', function () { + const sections = document.querySelectorAll('.section'); + + // Intersection Observer for scroll animations + const observerOptions = { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px', + }; + + const observer = new IntersectionObserver(function (entries) { + entries.forEach((entry) => { + if (entry.isIntersecting) { + entry.target.classList.add('visible'); + } + }); + }, observerOptions); + + // Observe all sections + sections.forEach((section) => { + observer.observe(section); + }); + + // Initial load animation for header + setTimeout(() => { + document.querySelector('.header').style.transform = 'translateY(0)'; + document.querySelector('.header').style.opacity = '1'; + }, 100); + + console.log('App1.js: Scroll animations initialized'); +}); diff --git a/optimization-http2/js/app2.js b/optimization-http2/js/app2.js new file mode 100644 index 0000000..f14316b --- /dev/null +++ b/optimization-http2/js/app2.js @@ -0,0 +1,52 @@ +// app2.js - Smooth scrolling navigation +document.addEventListener('DOMContentLoaded', function () { + const navLinks = document.querySelectorAll('.nav-menu a'); + + // Smooth scrolling for navigation links + navLinks.forEach((link) => { + link.addEventListener('click', function (e) { + e.preventDefault(); + + const targetId = this.getAttribute('href').substring(1); + const targetSection = document.getElementById(targetId); + + if (targetSection) { + const headerHeight = document.querySelector('.header').offsetHeight; + const targetPosition = targetSection.offsetTop - headerHeight - 20; + + window.scrollTo({ + top: targetPosition, + behavior: 'smooth', + }); + + // Add active state animation + this.style.transform = 'scale(0.95)'; + setTimeout(() => { + this.style.transform = 'scale(1)'; + }, 150); + } + }); + }); + + // Active link highlighting based on scroll position + window.addEventListener('scroll', function () { + const scrollPosition = window.scrollY + 100; + + navLinks.forEach((link) => { + const targetId = link.getAttribute('href').substring(1); + const targetSection = document.getElementById(targetId); + + if (targetSection) { + const sectionTop = targetSection.offsetTop; + const sectionBottom = sectionTop + targetSection.offsetHeight; + + if (scrollPosition >= sectionTop && scrollPosition < sectionBottom) { + navLinks.forEach((l) => l.classList.remove('active')); + link.classList.add('active'); + } + } + }); + }); + + console.log('App2.js: Navigation system initialized'); +}); diff --git a/optimization-http2/js/app3.js b/optimization-http2/js/app3.js new file mode 100644 index 0000000..3f77d9e --- /dev/null +++ b/optimization-http2/js/app3.js @@ -0,0 +1,57 @@ +// app3.js - Image lazy loading and hover effects +document.addEventListener('DOMContentLoaded', function () { + const images = document.querySelectorAll('img'); + + // Image loading observer + const imageObserver = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const img = entry.target; + img.style.opacity = '0'; + img.style.transition = 'opacity 0.5s ease-in-out'; + + img.onload = function () { + this.style.opacity = '1'; + }; + + // Simulate loading delay for performance testing + setTimeout(() => { + img.src = img.src; + }, Math.random() * 100); + + imageObserver.unobserve(img); + } + }); + }); + + // Observe all images + images.forEach((img) => { + imageObserver.observe(img); + }); + + // Add hover effects to feature cards + const featureCards = document.querySelectorAll('.feature-card'); + featureCards.forEach((card) => { + card.addEventListener('mouseenter', function () { + this.style.transform = 'translateY(-5px) scale(1.02)'; + }); + + card.addEventListener('mouseleave', function () { + this.style.transform = 'translateY(0) scale(1)'; + }); + }); + + // Grid image hover effects + const gridImages = document.querySelectorAll('.grid-image'); + gridImages.forEach((img) => { + img.addEventListener('mouseenter', function () { + this.style.filter = 'brightness(1.1) contrast(1.1)'; + }); + + img.addEventListener('mouseleave', function () { + this.style.filter = 'brightness(1) contrast(1)'; + }); + }); + + console.log('App3.js: Image effects initialized'); +}); diff --git a/optimization-http2/js/app4.js b/optimization-http2/js/app4.js new file mode 100644 index 0000000..8d851ce --- /dev/null +++ b/optimization-http2/js/app4.js @@ -0,0 +1,69 @@ +// app4.js - Performance monitoring and stats +document.addEventListener('DOMContentLoaded', function () { + // Performance monitoring + const performanceData = { + loadTime: 0, + resourceCount: 0, + totalSize: 0, + }; + + // Measure page load time + window.addEventListener('load', function () { + const loadTime = performance.now(); + performanceData.loadTime = Math.round(loadTime); + + // Count resources + const resources = performance.getEntriesByType('resource'); + performanceData.resourceCount = resources.length; + + // Calculate total transfer size (approximation) + performanceData.totalSize = resources.reduce((total, resource) => { + return total + (resource.transferSize || 0); + }, 0); + + console.log('Performance Data:', performanceData); + + // Update stats display if elements exist + const statNumbers = document.querySelectorAll('.stat-number'); + if (statNumbers.length >= 3) { + statNumbers[0].textContent = performanceData.resourceCount + ' Resources'; + statNumbers[1].textContent = + Math.round(performanceData.totalSize / 1024) + ' KB'; + statNumbers[2].textContent = performanceData.loadTime + ' ms'; + } + }); + + // CTA Button click tracking + const ctaButton = document.querySelector('.cta-button'); + if (ctaButton) { + ctaButton.addEventListener('click', function () { + const clickTime = performance.now(); + console.log('CTA clicked at:', Math.round(clickTime), 'ms'); + + // Add click animation + this.style.transform = 'scale(0.95)'; + setTimeout(() => { + this.style.transform = 'scale(1)'; + }, 150); + }); + } + + // Resource timing analysis + setTimeout(() => { + const navigation = performance.getEntriesByType('navigation')[0]; + if (navigation) { + console.log('Navigation Timing:', { + domContentLoaded: Math.round( + navigation.domContentLoadedEventEnd - + navigation.domContentLoadedEventStart + ), + loadComplete: Math.round( + navigation.loadEventEnd - navigation.loadEventStart + ), + totalTime: Math.round(navigation.loadEventEnd - navigation.fetchStart), + }); + } + }, 1000); + + console.log('App4.js: Performance monitoring initialized'); +}); diff --git a/optimization-http2/js/app5.js b/optimization-http2/js/app5.js new file mode 100644 index 0000000..ecf4cae --- /dev/null +++ b/optimization-http2/js/app5.js @@ -0,0 +1,109 @@ +// app5.js - UI interactions and theme management +document.addEventListener('DOMContentLoaded', function () { + // Dynamic color theme adjustments + const themeColors = { + primary: '#3b82f6', + secondary: '#1d4ed8', + accent: '#2563eb', + }; + + // Apply dynamic theme colors + function applyThemeColors() { + document.documentElement.style.setProperty( + '--primary-color', + themeColors.primary + ); + document.documentElement.style.setProperty( + '--secondary-color', + themeColors.secondary + ); + document.documentElement.style.setProperty( + '--accent-color', + themeColors.accent + ); + } + + applyThemeColors(); + + // Parallax effect for background elements + window.addEventListener('scroll', function () { + const scrolled = window.pageYOffset; + const rate = scrolled * -0.5; + + const introSection = document.querySelector('.intro-section'); + if (introSection) { + introSection.style.transform = `translateY(${rate}px)`; + } + }); + + // Interactive elements animation + const interactiveElements = document.querySelectorAll( + '.cta-button, .feature-card, .nav-menu a' + ); + + interactiveElements.forEach((element) => { + element.addEventListener('mouseenter', function () { + this.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'; + }); + }); + + // Footer animation on scroll + const footer = document.querySelector('.footer'); + const footerObserver = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + entry.target.style.animation = 'slideInUp 0.8s ease-out'; + } + }); + }, + { threshold: 0.1 } + ); + + if (footer) { + footerObserver.observe(footer); + } + + // Add CSS animation keyframes dynamically + const style = document.createElement('style'); + style.textContent = ` + @keyframes slideInUp { + from { + transform: translateY(30px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } + } + + .nav-menu a.active { + background-color: rgba(255, 255, 255, 0.2); + color: #e0f2fe; + } + `; + document.head.appendChild(style); + + // Random image loading simulation for testing + const testImages = document.querySelectorAll('img'); + testImages.forEach((img, index) => { + // Add loading states + img.addEventListener('loadstart', function () { + this.style.filter = 'blur(2px)'; + }); + + img.addEventListener('load', function () { + this.style.filter = 'blur(0px)'; + this.style.transition = 'filter 0.3s ease'; + }); + }); + + // Resource loading simulation + setTimeout(() => { + console.log('All resources loaded - App5.js ready'); + document.body.classList.add('fully-loaded'); + }, 2000); + + console.log('App5.js: UI interactions and theme initialized'); +});