⚡ 第十七章:性能优化与安全

打造高性能、安全的 JavaScript 应用

17.1 减少重绘重排

重绘 (Repaint) 和重排 (Reflow) 是影响页面性能的重要因素。

重绘与重排的区别

优化技巧

// 避免频繁操作 DOM
const element = document.querySelector('.container');

// 坏的做法
for (let i = 0; i < 1000; i++) {
    element.innerHTML += `<div>Item ${i}
`; } // 好的做法:使用文档片段 const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const div = document.createElement('div'); div.textContent = `Item ${i}`; fragment.appendChild(div); } element.appendChild(fragment); // 避免频繁读取布局属性 // 坏的做法 for (let i = 0; i < 1000; i++) { const width = element.offsetWidth; element.style.left = `${width + i}px`; } // 好的做法:缓存布局属性 const width = element.offsetWidth; for (let i = 0; i < 1000; i++) { element.style.left = `${width + i}px`; } // 使用 CSS 类批量修改样式 // 坏的做法 element.style.color = 'red'; element.style.fontSize = '16px'; element.style.backgroundColor = '#f0f0f0'; // 好的做法 element.classList.add('active');

17.2 Web Workers

// 创建 Worker
const worker = new Worker('worker.js');

// 发送消息给 Worker
worker.postMessage({
    type: 'calculate',
    data: 1000000
});

// 接收 Worker 的消息
worker.onmessage = (event) => {
    console.log('Result:', event.data);
};

// 错误处理
worker.onerror = (error) => {
    console.error(error);
};

// worker.js
// self.onmessage = (event) => {
//     const { type, data } = event.data;
//     if (type === 'calculate') {
//         let result = 0;
//         for (let i = 0; i < data; i++) {
//             result += i;
//         }
//         self.postMessage(result);
//     }
// };
//

17.3 内容安全策略与 XSS 防御

内容安全策略 (CSP)

// 在 HTTP 响应头中设置 CSP
// Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com;

// 或在 HTML 中设置
<!--
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted-cdn.com">
-->

XSS 防御

// 避免直接插入 HTML
// 坏的做法
const userInput = '<script>alert("XSS")</script>';
element.innerHTML = userInput; // 危险!

// 好的做法:使用 textContent
element.textContent = userInput; // 安全

// 或使用 DOMPurify
// const clean = DOMPurify.sanitize(userInput);
// element.innerHTML = clean;

// 对 URL 参数进行编码
const safeUrl = encodeURIComponent(userInput);

// 使用 CSP 禁止内联脚本
// Content-Security-Policy: script-src 'self';

17.4 代码打包与压缩

Vite 简介

// 安装 Vite
// npm create vite@latest my-project -- --template vanilla

// vite.config.js
// import { defineConfig } from 'vite'
// 
// export default defineConfig({
//   build: {
//     minify: 'terser',
//     rollupOptions: {
//       output: {
//         manualChunks: {
//           vendor: ['react', 'react-dom'],
//           common: ['lodash']
//         }
//       }
//     }
//   }
// })
// 

// 构建命令
// npm run build

Webpack 简介

// 安装 Webpack
// npm install webpack webpack-cli --save-dev

// webpack.config.js
// const path = require('path');
// 
// module.exports = {
//   entry: './src/index.js',
//   output: {
//     path: path.resolve(__dirname, 'dist'),
//     filename: 'bundle.js'
//   },
//   mode: 'production'
// };
// 

// 构建命令
// npx webpack

动手练习

练习 1:减少重绘重排

  1. 测试频繁操作 DOM 的性能
  2. 使用文档片段优化
  3. 缓存布局属性

练习 2:Web Workers

  1. 创建一个 Worker
  2. 在 Worker 中执行密集计算
  3. 测试性能提升

练习 3:XSS 防御

  1. 测试 XSS 攻击
  2. 使用 textContent 防御
  3. 配置 CSP

练习 4:代码打包

  1. 使用 Vite 创建项目
  2. 构建并分析输出
  3. 测试打包后的性能