0%

什么是前端工程化?

前端工程化是用工程方法管理前端开发过程。包括代码规范、自动化构建、测试、部署等,让团队更高效协作。

代码规范

1. ESLint

检查代码质量。

1
npm install eslint --save-dev

创建 .eslintrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
env: {
browser: true,
es2021: true
},
extends: 'eslint:recommended',
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
'no-unused-vars': 'error',
'no-console': 'warn'
}
};

2. Prettier

自动格式化代码。

1
npm install prettier --save-dev

.prettierrc

1
2
3
4
5
6
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80
}

版本控制

用 Git 管理代码。

1
2
3
git init
git add .
git commit -m "初始提交"

CI/CD

持续集成/持续部署。

GitHub Actions 示例

.github/workflows/ci.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm ci
- run: npm test
- run: npm run build

包管理

用 npm 或 yarn 管理依赖。

1
2
npm init -y
npm install lodash

模块化

用 ES6 模块或 CommonJS。

1
2
3
4
5
6
7
// ES6
import { sum } from './math.js';
export { sum };

// CommonJS
const sum = require('./math');
module.exports = { sum };

构建工具

  • Webpack:打包和优化
  • Vite:快速开发服务器
  • Parcel:零配置打包

测试

  • 单元测试:Jest
  • E2E 测试:Cypress

文档

用 JSDoc 或 TypeScript 生成文档。

1
2
3
4
5
6
7
8
9
/**
* 计算两个数的和
* @param {number} a 第一个数
* @param {number} b 第二个数
* @returns {number} 和
*/
function sum(a, b) {
return a + b;
}

性能监控

用 Lighthouse 或 Web Vitals 监控性能。

团队协作

  • 代码审查
  • 标准化工作流
  • 知识分享

总结

工程化让前端开发更专业。从规范代码开始,逐步引入工具。记住,工具是为开发服务,不是反过来。

前端安全的重要性

前端安全直接影响用户数据和网站信誉。常见攻击包括 XSS、CSRF 等。了解这些威胁,能帮你写出更安全的代码。

XSS (跨站脚本攻击)

攻击者注入恶意脚本。

防范措施

  1. 转义用户输入
1
2
3
4
5
// 危险
const html = `<div>${userInput}</div>`;

// 安全
const html = `<div>${escapeHtml(userInput)}</div>`;
  1. 使用 CSP (内容安全策略)
1
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
  1. 框架内置防护

React、Vue 等框架默认转义内容。

CSRF (跨站请求伪造)

攻击者诱导用户执行非预期操作。

防范措施

  1. SameSite Cookie
1
Set-Cookie: session=abc123; SameSite=Strict
  1. CSRF Token

表单中添加隐藏 token。

1
2
3
4
<form action="/transfer" method="post">
<input type="hidden" name="csrf_token" value="abc123">
<!-- 其他字段 -->
</form>

点击劫持

用透明 iframe 覆盖页面。

防范措施

1
2
3
4
// 禁止 iframe 嵌套
if (window.top !== window.self) {
window.top.location = window.self.location;
}

HTTPS

强制使用 HTTPS,防止中间人攻击。

1
2
3
4
// 重定向到 HTTPS
if (location.protocol !== 'https:') {
location.replace('https:' + location.href.substring(location.protocol.length));
}

敏感信息处理

  • 不要在前端存储敏感数据
  • 用环境变量管理 API 密钥
  • 定期轮换密钥

依赖安全

  • 定期更新依赖
  • 用 npm audit 检查漏洞
  • 避免使用有风险的包

输入验证

  • 前端验证:用户体验
  • 后端验证:安全保障
1
2
3
4
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}

错误处理

不要暴露内部错误信息。

1
2
3
4
5
6
7
try {
// 危险操作
} catch (error) {
console.error(error);
// 显示用户友好的错误信息
alert('操作失败,请重试');
}

总结

安全是持续的过程。从小事做起:转义输入、使用 HTTPS、定期审计。多学习 OWASP 指南,保持警惕。

Composition API 是什么?

Vue 3 的 Composition API 是一种新的组织组件逻辑的方式。它用函数式编程风格,让代码更易复用和维护。与 Options API 相比,更灵活。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<p>计数:{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>

<script>
import { ref } from 'vue'

export default {
setup() {
const count = ref(0)

const increment = () => {
count.value++
}

return {
count,
increment
}
}
}
</script>

响应式数据

ref 和 reactive

  • ref:基本类型
  • reactive:对象类型
1
2
3
4
5
6
7
import { ref, reactive } from 'vue'

const count = ref(0)
const state = reactive({
name: '小明',
age: 25
})

计算属性

1
2
3
4
5
6
7
8
import { ref, computed } from 'vue'

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed(() => {
return firstName.value + ' ' + lastName.value
})

监听器

1
2
3
4
5
6
7
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
console.log(`count 从 ${oldVal} 变成 ${newVal}`)
})

生命周期钩子

1
2
3
4
5
6
7
8
9
10
11
12
13
import { onMounted, onUnmounted } from 'vue'

export default {
setup() {
onMounted(() => {
console.log('组件挂载')
})

onUnmounted(() => {
console.log('组件卸载')
})
}
}

组合函数 (Composables)

复用逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
const x = ref(0)
const y = ref(0)

const update = (e) => {
x.value = e.pageX
y.value = e.pageY
}

onMounted(() => {
window.addEventListener('mousemove', update)
})

onUnmounted(() => {
window.removeEventListener('mousemove', update)
})

return { x, y }
}

在组件中使用:

1
2
3
4
5
6
7
8
9
import { useMouse } from './useMouse'

export default {
setup() {
const { x, y } = useMouse()

return { x, y }
}
}

与 Options API 的比较

  • Composition API:逻辑集中,易复用
  • Options API:简单直观,适合小组件

迁移指南

Vue 3 支持两种 API,可以逐步迁移。

总结

Composition API 让 Vue 更强大。多练习 composables,体会函数式编程的魅力。

为什么需要测试?

测试确保代码质量,防止 bug。Jest 是 Facebook 开发的测试框架,零配置,开箱即用。

安装

1
npm install --save-dev jest

package.json 中添加:

1
2
3
"scripts": {
"test": "jest"
}

基本测试

创建 sum.js

1
2
3
4
5
function sum(a, b) {
return a + b;
}

module.exports = sum;

创建 sum.test.js

1
2
3
4
5
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});

运行 npm test

匹配器 (Matchers)

  • toBe():严格相等
  • toEqual():对象相等
  • toBeTruthy():真值
  • toContain():包含
1
2
3
4
5
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});

测试异步代码

1
2
3
4
5
6
7
8
9
10
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => resolve('peanut butter'), 100);
});
}

test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});

设置和清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
beforeEach(() => {
// 每个测试前运行
});

afterEach(() => {
// 每个测试后运行
});

beforeAll(() => {
// 所有测试前运行一次
});

afterAll(() => {
// 所有测试后运行一次
});

Mock 函数

模拟依赖。

1
2
3
const mockCallback = jest.fn(x => 42 + x);
mockCallback(1);
expect(mockCallback).toHaveBeenCalledWith(1);

测试 React 组件

需要额外安装:

1
npm install --save-dev @testing-library/react @testing-library/jest-dom
1
2
3
4
5
6
7
8
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

配置

创建 jest.config.js

1
2
3
4
module.exports = {
testEnvironment: 'jsdom', // DOM 测试环境
setupFilesAfterEnv: ['<rootDir>/setupTests.js']
};

总结

Jest 让测试变得简单。从单元测试开始,逐步覆盖更多场景。测试是代码质量的保障。

Webpack 是什么?

Webpack 是一个现代 JavaScript 应用的静态模块打包器。它分析项目结构,找到依赖关系,把它们打包成适合浏览器使用的文件。

安装

1
npm install webpack webpack-cli --save-dev

基本配置

创建 webpack.config.js

1
2
3
4
5
6
7
8
9
const path = require('path');

module.exports = {
entry: './src/index.js', // 入口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};

加载器 (Loaders)

处理非 JS 文件。

1. CSS 加载器

1
npm install css-loader style-loader --save-dev
1
2
3
4
5
6
7
8
9
10
11
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};

2. Babel 加载器

转换 ES6+ 代码。

1
npm install babel-loader @babel/core @babel/preset-env --save-dev
1
2
3
4
5
6
7
8
9
10
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}

3. 图片加载器

1
npm install file-loader --save-dev
1
2
3
4
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
}

插件 (Plugins)

扩展 Webpack 功能。

1. HtmlWebpackPlugin

自动生成 HTML 文件。

1
npm install html-webpack-plugin --save-dev
1
2
3
4
5
6
7
8
9
10
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};

2. CleanWebpackPlugin

清理 dist 目录。

1
npm install clean-webpack-plugin --save-dev
1
2
3
4
5
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [
new CleanWebpackPlugin()
]

开发服务器

1
npm install webpack-dev-server --save-dev
1
2
3
4
5
6
7
module.exports = {
// ...
devServer: {
contentBase: './dist',
port: 3000
}
};

package.json 中添加:

1
2
3
4
"scripts": {
"start": "webpack serve --open",
"build": "webpack"
}

代码分割

1
2
3
4
5
6
7
8
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'all'
}
}
};

总结

Webpack 配置灵活但复杂。从基础开始,逐步添加功能。推荐看官方文档和示例项目。

typescript 是什么?

typescript 是 JavaScript 的超集,由 Microsoft 开发。它添加了静态类型检查,让代码更健壮,易于维护。编译时会检查类型错误,减少运行时 bug。

为什么用 typescript?

  • 类型安全:提前发现错误
  • 更好的 IDE 支持:自动补全、重构
  • 代码可读性:类型注解像文档
  • 大型项目友好:团队协作更顺畅

安装和配置

1
npm install -g typescript

创建 tsconfig.json

1
2
3
4
5
6
7
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true
}
}

基本类型

1
2
3
4
let name: string = "小明";
let age: number = 25;
let isStudent: boolean = true;
let hobbies: string[] = ["阅读", "编程"];

接口和类型

1
2
3
4
5
6
7
8
interface Person {
name: string;
age: number;
}

function greet(person: Person) {
console.log(`你好,${person.name}!`);
}

类和继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

speak() {
console.log(`${this.name} 发出声音`);
}
}

class Dog extends Animal {
speak() {
console.log(`${this.name} 汪汪叫`);
}
}

泛型

让函数或类适用于多种类型。

1
2
3
4
5
function identity<T>(arg: T): T {
return arg;
}

let output = identity<string>("myString");

在 React 中使用

1
2
3
4
5
6
7
8
9
10
import React from 'react';

interface Props {
name: string;
age: number;
}

const Person: React.FC<Props> = ({ name, age }) => {
return <div>{name} 今年 {age} 岁</div>;
};

编译和运行

1
2
tsc main.ts  // 编译为 JS
node main.js // 运行

常见坑

  • 严格模式下不能用隐式 any
  • 接口 vs 类型别名
  • 可选属性用 ?

总结

typescript 学习曲线稍陡,但好处多。多写代码,熟悉类型系统。推荐用在大型项目或团队开发中。

为什么需要性能优化?

网站加载慢会让用户流失。好的性能能提升用户体验和搜索引擎排名。前端性能优化涉及多个方面,从代码到网络。

网络层面优化

1. 压缩资源

  • Gzip 压缩:服务器端启用 Gzip,压缩 HTML、CSS、JS 文件
  • 图片优化:用 WebP 格式,压缩图片大小

2. 减少 HTTP 请求

  • 合并文件:把多个 CSS/JS 文件合并
  • 雪碧图:小图标合成一张大图
  • 内联小资源:小 CSS/JS 直接写在 HTML 中

3. 使用 CDN

把静态资源放在 CDN 上,加速加载。

代码层面优化

1. 减少重绘重排

  • 避免频繁操作 DOM
  • 用 CSS3 动画代替 JS 动画
  • 批量修改样式

2. 懒加载

图片和组件等到需要时再加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 图片懒加载
<img data-src="image.jpg" alt="懒加载图片">

// JS 实现
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});

images.forEach(img => imageObserver.observe(img));

3. 代码分割

用 Webpack 等工具分割代码,按需加载。

1
2
3
4
// 动态导入
import('./module.js').then(module => {
// 使用模块
});

缓存优化

1. 浏览器缓存

设置合适的 Cache-Control 头。

2. Service Worker

用 Service Worker 缓存资源,实现离线访问。

工具和监控

1. Lighthouse

Chrome 开发者工具的 Lighthouse 可以分析性能。

2. Web Vitals

Google 的性能指标:LCP、FID、CLS。

移动端优化

  • 响应式设计
  • 触摸事件优化
  • 减少电池消耗

总结

性能优化是个持续的过程。从小事做起:压缩资源、优化图片、减少请求。定期用工具检查,保持网站快速加载。

CSS Grid 是什么?

CSS Grid 是一种强大的二维布局系统,可以轻松创建复杂的网页布局。它比传统的浮动或 Flexbox 更灵活,特别适合构建网格状的界面。

基本概念

  • 网格容器:设置 display: grid 的元素
  • 网格项:容器内的直接子元素
  • 网格线:划分网格的线
  • 网格轨道:行或列之间的空间

创建网格

1
2
3
4
5
.container {
display: grid;
grid-template-columns: 200px 200px 200px; /* 三列,每列200px */
grid-template-rows: 100px 100px; /* 两行,每行100px */
}

常用属性

1. grid-template-columns 和 grid-template-rows

定义列和行的尺寸。

1
2
3
4
5
6
7
8
/* 固定尺寸 */
grid-template-columns: 100px 200px 100px;

/* 比例单位 fr */
grid-template-columns: 1fr 2fr 1fr; /* 1:2:1 比例 */

/* 重复函数 */
grid-template-columns: repeat(3, 1fr); /* 三列相等 */

2. grid-gap

设置网格项之间的间距。

1
2
3
grid-gap: 10px; /* 行和列间距都是10px */
grid-row-gap: 10px; /* 行间距 */
grid-column-gap: 10px; /* 列间距 */

3. justify-items 和 align-items

控制网格项在单元格内的对齐。

1
2
justify-items: center; /* 水平居中 */
align-items: center; /* 垂直居中 */

4. grid-column 和 grid-row

让网格项跨越多个单元格。

1
2
3
4
.item {
grid-column: 1 / 3; /* 从第1列线到第3列线,跨越2列 */
grid-row: 1 / 3; /* 跨越2行 */
}

实际例子

1
2
3
4
5
6
<div class="grid-container">
<div class="item1">Header</div>
<div class="item2">Sidebar</div>
<div class="item3">Main</div>
<div class="item4">Footer</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.grid-container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 100px 1fr 100px;
grid-gap: 10px;
}

.item1 {
grid-column: 1 / 3; /* 跨越两列 */
}

.item2 {
grid-row: 2 / 4; /* 跨越两行 */
}

浏览器支持

现代浏览器都支持 CSS Grid,但记得检查兼容性。可以用 Autoprefixer 来添加厂商前缀。

总结

CSS Grid 让布局变得简单直观。多练习几个例子,你就能掌握它了。结合 Flexbox,可以解决几乎所有布局问题。

ES6 是什么?

ES6 是 ECMAScript 6 的简称,是 javascript 的一个重要版本,于 2015 年发布。它引入了许多新特性,让 javascript 变得更强大和易用。如果你还在用老版本的 JS,这些新特性能帮你写出更简洁、更高效的代码。

主要新特性

1. let 和 const 声明变量

以前我们用 var 声明变量,但它有作用域问题。现在可以用 letconst

  • let:声明可重新赋值的变量
  • const:声明常量,不能重新赋值
1
2
3
4
5
let name = "小明";
name = "小红"; // 可以

const age = 25;
// age = 26; // 报错,不能改

2. 箭头函数

简化函数写法,尤其在回调函数中很方便。

1
2
3
4
5
6
7
// 传统写法
function add(a, b) {
return a + b;
}

// 箭头函数
const add = (a, b) => a + b;

3. 模板字符串

用反引号 ` 包围,可以直接插入变量,不用拼接字符串。

1
2
3
const name = "小明";
const greeting = `你好,${name}!`;
console.log(greeting); // 你好,小明!

4. 解构赋值

从数组或对象中提取值,赋值给变量。

1
2
3
4
5
// 数组解构
const [a, b] = [1, 2];

// 对象解构
const {name, age} = {name: "小明", age: 25};

5. 默认参数

函数参数可以设置默认值。

1
2
3
4
function greet(name = "客人") {
console.log(`你好,${name}!`);
}
greet(); // 你好,客人!

6. Promise

处理异步操作,避免回调地狱。

1
2
3
4
5
6
7
8
9
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功!");
}, 1000);
});

promise.then(result => {
console.log(result);
});

7. 类 (Class)

面向对象编程更简单。

1
2
3
4
5
6
7
8
9
10
11
12
class Person {
constructor(name) {
this.name = name;
}

sayHello() {
console.log(`你好,我是${this.name}`);
}
}

const person = new Person("小明");
person.sayHello();

总结

ES6 让 javascript 更现代化。建议多练习这些特性,它们在现代前端开发中很常用。记得用 Babel 转换器来兼容老浏览器。

在 Web 应用架构中,渲染策略影响页面性能、SEO 和开发体验。主要有两种模式:服务端渲染(SSR)和客户端渲染(CSR)。本文分析它们的优缺点,并提供实践建议。

客户端渲染(CSR)

在 CSR 中,服务器返回一个最小 HTML 框架,JavaScript 在客户端执行并构建 UI。典型流程:

  1. 浏览器请求 HTML。
  2. 返回的 HTML 包含 <div id="app"></div> 和脚本。
  3. JS 下载、解析、执行,随后渲染页面。

优点

  • 无需服务器模板,同构代码少。
  • 页面交互快,之后路由切换无需刷新。
  • 比较容易实现 PWA。

缺点

  • 首屏加载时间长,首屏内容可能为空白(白屏)。
  • 对 SEO 不友好,爬虫需执行 JS。虽然现代搜索引擎可以执行 JS,但效果不及 SSR。
  • 对低端设备和慢网络体验较差。

服务端渲染(SSR)

SSR 在服务器生成完整的 HTML,包括初始数据,然后发送给客户端。客户端可以选择水合(hydrate)以启用交互。

优点

  • 首屏更快,用户更快看到内容。
  • 更好的 SEO 友好性。
  • 对于较旧设备,初始性能更好。

缺点

  • 服务器负载增加,需要处理渲染逻辑。
  • 开发和部署更复杂,需保证服务器环境支持。
  • 水合时可能出现闪烁或不一致问题。

两者比较

特性 CSR SSR
SEO 较差 良好
首屏性能 依赖 JS 通常更好
开发复杂度 简单 较复杂
缓存策略 静态资源缓存 页面缓存、CDN 缓存
架构灵活性 SPA 为主 可融合多种模式

混合模式(同构/泛用渲染)

许多框架支持 SSR + CSR 的混合,例如 Next.js、Nuxt.js、Remix 等。它们通常在服务器端渲染初始页面,然后客户端接管交互。还有渐进式增强(progressive hydration)技术,将页面拆分少量组件渐进水合。

延迟渲染与水合优化

  • 部分水合:只水合可交互区域,减少 JS 负荷。
  • 延迟水合:将非关键组件水合延迟到用户交互时。
  • 静态生成(SSG):结合构建时渲染和缓存。

SEO 实践

在 SSR 中可生成 meta 标签、Open Graph 以及结构化数据,提升搜索排名。CSR 可使用预渲染或 Prerender 服务。

状态管理

CSR 使用纯客户端状态库(Redux、MobX、Vuex)。

SSR 需在服务器生成初始状态并注入到 HTML,然后客户端读取该状态。比如:

1
<script>window.__INITIAL_STATE__ = {...};</script>

开发体验与工具

  • Next.js/Remix:提供 SSR 路由、数据加载逻辑。
  • Nuxt.js:Vue 生态中流行。
  • SvelteKit:轻量级 SSR 框架。

测试时需考虑服务器端和客户端渲染的一致性。

性能配置

  • SSR 服务器可以缓存渲染结果。
  • 使用 CDN 分发静态资源,减轻服务器负载。
  • 对 SSR 页面启用 HTTP 缓存头,例如 Cache-Control

SEO & 社交媒体

使用 SSR 可以在HTML中直接生成预览图和描述,而 CSR 则需要第三方服务或动态渲染。

渲染策略选择指南

  1. 内容驱动型网站(如博客、新闻):优先 SSR 或静态生成。
  2. 应用型平台(如仪表盘、管理后台):CSR 常见,可在登录后使用 SSR 首页。
  3. 混合型:使用 SSR 生成 shell,内部路由 CSR。

性能测量

使用 Lighthouse 或 WebPageTest 分别测试 SSR 和 CSR 页面,比较 FCP、LCP、Total Blocking Time 等指标。

常见陷阱

  • 保证同构代码在服务器和客户端行为一致,否则出现“水合失败”错误。
  • SSR 中依赖浏览器 API(如 window)时需加条件检查。

安全考虑

动态渲染时注意 XSS、CSP 等安全策略,因为服务器可能直接插入用户数据。

未来趋势

  • Edge Rendering:将 SSR 推到边缘 CDN 节点,例如 Cloudflare Workers、Vercel Edge。
  • Streaming SSR:通过流式传输片段提高首屏速度。
  • PHTML/Islands Architecture:大部分静态,仅少数交互组件水合,例如 Astro 框架。

总结

CSR 和 SSR 各有千秋。选择时需要权衡首屏性能、SEO、服务器成本和开发复杂度。对于需要快速加载和更好 SEO 的公共内容,SSR 或静态生成是优选。对于交互密集的单页应用,可考虑 CSR 或混合。随着边缘渲染和逐步水合等技术的发展,两者的界限正在模糊,但理解基础原理仍然重要,这样才能根据项目的具体需求制定最佳策略。