← Назад к вопросам
Как оптимизировать скрипты?
2.0 Middle🔥 171 комментариев
#Оптимизация и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Оптимизация скриптов в браузере
Оптимизация JavaScript скриптов критична для производительности веб-приложений. Это включает минимизацию размера кода, уменьшение времени выполнения и оптимизацию работы с памятью.
1. Минификация и Code Splitting
Минификация удаляет ненужные символы без изменения функциональности:
// До минификации
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price * items[i].quantity;
}
return total;
}
// После минификации (Terser/UglifyJS)
// function calculateTotal(a){let b=0;for(let c=0;c<a.length;c++)b+=a[c].price*a[c].quantity;return b}
// Code splitting - динамический импорт
const Dashboard = lazy(() => import('./Dashboard.js'));
const Analytics = lazy(() => import('./Analytics.js'));
2. Ленивая загрузка (Lazy Loading)
Загружайте скрипты и компоненты только при необходимости:
// Динамический импорт при клике
document.querySelector('#load-btn').addEventListener('click', async () => {
const module = await import('./heavy-module.js');
module.initialize();
});
// React Suspense для ленивой загрузки компонентов
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./Heavy.jsx'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
// Vue 3 - асинхронные компоненты
import { defineAsyncComponent } from 'vue';
const HeavyComponent = defineAsyncComponent(() =>
import('./Heavy.vue')
);
3. Кеширование в памяти (Memoization)
Храните результаты дорогостоящих вычислений:
// Простое кеширование
const cache = new Map();
function expensiveCalculation(n) {
if (cache.has(n)) return cache.get(n);
const result = fibonacci(n);
cache.set(n, result);
return result;
}
// React useMemo
import { useMemo } from 'react';
function Component({ data }) {
const sortedData = useMemo(() => {
console.log('Sorting...');
return data.sort((a, b) => a - b);
}, [data]);
return <div>{sortedData}</div>;
}
// Vue computed (автоматически кешируется)
import { computed } from 'vue';
const sortedData = computed(() => {
return props.data.sort((a, b) => a - b);
});
4. Оптимизация DOM манипуляций
Минимизируйте обращения к DOM, используйте батчинг:
// ❌ Плохо - множество переголосовок DOM
for (let i = 0; i < 1000; i++) {
const element = document.createElement('div');
element.textContent = `Item ${i}`;
document.body.appendChild(element);
// После каждого appendChild происходит reflow/repaint
}
// ✅ Хорошо - батчинг обновлений
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const element = document.createElement('div');
element.textContent = `Item ${i}`;
fragment.appendChild(element);
}
document.body.appendChild(fragment);
// Один reflow/repaint
// ✅또는использовать requestAnimationFrame
let batch = [];
function scheduleUpdate(element) {
batch.push(element);
if (batch.length === 1) {
requestAnimationFrame(() => {
batch.forEach(el => document.body.appendChild(el));
batch = [];
});
}
}
5. Уменьшение размера Bundle'а
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor': ['vue', 'vue-router', 'pinia'],
'utils': ['lodash-es', 'date-fns']
}
}
},
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Удалить console.log из production
pure_funcs: ['console.log', 'console.info']
}
}
}
};
// Избегайте импорта целых библиотек
// ❌ import _ from 'lodash';
// ✅ import debounce from 'lodash-es/debounce';
// Используйте tree-shaking
// package.json
{
"sideEffects": false
}
6. Оптимизация асинхронных операций
// Дебаунс для API запросов
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
const debouncedSearch = debounce(async (query) => {
const results = await fetch(`/api/search?q=${query}`);
}, 300);
// Параллельные запросы с Promise.all
async function fetchUserData(userId) {
const [user, posts, comments] = await Promise.all([
fetch(`/api/users/${userId}`).then(r => r.json()),
fetch(`/api/posts?userId=${userId}`).then(r => r.json()),
fetch(`/api/comments?userId=${userId}`).then(r => r.json())
]);
return { user, posts, comments };
}
// Ограничение параллельных запросов
function promisePool(tasks, poolSize) {
const results = [];
let inProgress = 0;
return new Promise((resolve) => {
async function process() {
while (tasks.length > 0) {
if (inProgress >= poolSize) {
await new Promise(r => setTimeout(r, 10));
continue;
}
inProgress++;
const task = tasks.shift();
task().then(result => {
results.push(result);
inProgress--;
});
}
if (inProgress === 0) resolve(results);
}
process();
});
}
7. Web Workers для тяжёлых вычислений
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
console.log('Result from worker:', e.data);
};
// worker.js
self.onmessage = (e) => {
const result = performHeavyCalculation(e.data);
self.postMessage(result);
};
function performHeavyCalculation(data) {
// Тяжёлые вычисления без блокировки main thread
return data.reduce((acc, val) => acc + val, 0);
}
8. Профилирование и мониторинг
// Performance API
performance.mark('start');
expensiveOperation();
performance.mark('end');
performance.measure('operation', 'start', 'end');
const measure = performance.getEntriesByName('operation')[0];
console.log(`Operation took ${measure.duration}ms`);
// Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
getLCP(console.log); // Largest Contentful Paint
getFID(console.log); // First Input Delay
getCLS(console.log); // Cumulative Layout Shift
// Анализ памяти
if (performance.memory) {
console.log('Used JS heap:', performance.memory.usedJSHeapSize);
console.log('Total JS heap:', performance.memory.totalJSHeapSize);
}
9. Оптимизация критического пути рендеринга
<!-- Минимизировать blocking ресурсы -->
<head>
<!-- Критические стили inline -->
<style>body { margin: 0; }</style>
<!-- Отложить некритические стили -->
<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">
<!-- Отложить скрипты -->
<script src="app.js" defer></script>
</head>
10. Инструменты для анализа
# Анализ размера bundle
npm install --save-dev webpack-bundle-analyzer
# Проверка производительности
speed insights url
# Lighthouse CI
npm install --save-dev @lhci/cli@latest
lhci autorun
Оптимизация скриптов - это не одноразовое действие, а постоянный процесс мониторинга, анализа и улучшения производительности приложения.