feat: 添加面包屑导航组件并优化页面布局

refactor: 重构页面结构和导航逻辑

fix: 修复移动端菜单导航和滚动行为

perf: 优化图片加载性能和资源请求

test: 添加端到端测试和性能测试用例

docs: 更新.gitignore文件

chore: 更新依赖和配置

style: 优化代码格式和类型安全

ci: 调整Playwright测试超时时间

build: 更新Next.js配置和构建选项
This commit is contained in:
张翔
2026-02-28 09:09:04 +08:00
parent 9d01e0982f
commit 9451814ca4
60 changed files with 4078 additions and 148 deletions
@@ -0,0 +1,121 @@
import { test, expect } from '../../fixtures/base.fixture';
import { HomePage } from '../../pages/HomePage';
test.describe('Image Performance Tests', () => {
test('Home page images load efficiently', async ({ page }) => {
const homePage = new HomePage(page);
const startTime = Date.now();
await homePage.navigate('/');
await page.waitForLoadState('networkidle');
const loadTime = Date.now() - startTime;
console.log(`Home page load time: ${loadTime}ms`);
expect(loadTime).toBeLessThan(15000);
const images = await page.locator('img').all();
console.log(`Found ${images.length} images on home page`);
for (const image of images) {
const src = await image.getAttribute('src');
if (src && !src.startsWith('data:')) {
const alt = await image.getAttribute('alt');
expect(alt).toBeTruthy();
}
}
});
test('Images have proper dimensions', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const images = await page.locator('img').all();
for (const image of images) {
const width = await image.evaluate((el) => el.naturalWidth);
const height = await image.evaluate((el) => el.naturalHeight);
if (width > 0 && height > 0) {
expect(width).toBeLessThanOrEqual(3840);
expect(height).toBeLessThanOrEqual(3840);
}
}
});
test('Lazy loading is applied to below-fold images', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('domcontentloaded');
const images = await page.locator('img[loading="lazy"]').count();
console.log(`Found ${images} lazy-loaded images`);
expect(images).toBeGreaterThanOrEqual(0);
});
test('Images have appropriate quality and format', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
const images = await page.locator('img').all();
for (const image of images) {
const src = await image.getAttribute('src');
if (src) {
const isOptimized =
src.includes('webp') ||
src.includes('avif') ||
src.includes('data:image') ||
src.includes('svg') ||
src.includes('image');
if (!isOptimized) {
console.log(`Image may need optimization: ${src}`);
}
}
}
});
test('About page images load efficiently', async ({ page }) => {
const startTime = Date.now();
await page.goto('/about');
await page.waitForLoadState('networkidle');
const loadTime = Date.now() - startTime;
console.log(`About page load time: ${loadTime}ms`);
expect(loadTime).toBeLessThan(15000);
const images = await page.locator('img').count();
console.log(`Found ${images} images on about page`);
});
test('Products page images load efficiently', async ({ page }) => {
const startTime = Date.now();
await page.goto('/products');
await page.waitForLoadState('networkidle');
const loadTime = Date.now() - startTime;
console.log(`Products page load time: ${loadTime}ms`);
expect(loadTime).toBeLessThan(15000);
const images = await page.locator('img').count();
console.log(`Found ${images} images on products page`);
});
test('Network requests are optimized', async ({ page }) => {
const requests: string[] = [];
page.on('request', (request) => {
if (request.resourceType() === 'image') {
requests.push(request.url());
}
});
await page.goto('/');
await page.waitForLoadState('networkidle');
console.log(`Total image requests: ${requests.length}`);
const uniqueRequests = new Set(requests);
expect(uniqueRequests.size).toBeLessThanOrEqual(requests.length);
});
});