深色模式
2019 年即将结束,回顾这一年,前端领域依然保持着高速迭代的节奏。React Hooks 全面铺开、Vue 3 进入 RFC 阶段、TypeScript 成为越来越多团队的标配。站在 2019 年末,我想对 2020 年的技术趋势做一些预判,既是给自己定方向,也希望能给大家一些参考。
Vue 3 正式版即将到来
Vue 3 从 2018 年底宣布重写,到 2019 年陆续公开 RFC,核心团队在 Composition API、响应式系统、TypeScript 重写等方面做了大量工作。从 Evan You 和核心团队的动态来看,Vue 3.0 正式版大概率会在 2020 年 Q1-Q2 发布。
Composition API 是最受关注的变更,它让逻辑复用不再依赖 mixins:
javascript
// Vue 2.x 的 mixins 方式,存在命名冲突和来源不明的问题
const loggerMixin = {
created() {
console.log('组件创建:', this.$options.name)
},
methods: {
log(message) {
console.log(`[${this.$options.name}]`, message)
}
}
}
// Vue 3 Composition API,逻辑清晰、类型友好
import { ref, onMounted, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
onMounted(() => {
console.log('Counter 组件已挂载, 初始值:', initialValue)
})
return { count, double, increment, decrement }
}Composition API 的优势显而易见:逻辑复用更清晰、TypeScript 推导更友好、代码组织更灵活。对于我们的组件库来说,Vue 3 的支持将是 2020 年的重要工作。
React Concurrent Mode 的探索
React 16.8 引入 Hooks 之后,React 团队将重心转向了 Concurrent Mode。这是一项根本性的调度机制变革,允许 React 同时准备多个版本的 UI,根据优先级决定哪些更新先渲染。
jsx
// Concurrent Mode 的核心理念示例
// 开启 Concurrent Mode
import { createRoot } from 'react-dom'
const root = createRoot(document.getElementById('app'))
root.render(<App />)
// 使用 useTransition 标记低优先级更新
import { useState, useTransition } from 'react'
function SearchResults() {
const [query, setQuery] = useState('')
const [results, setResults] = useState([])
const [isPending, startTransition] = useTransition()
function handleSearch(e) {
const value = e.target.value
setQuery(value) // 高优先级:输入框立即响应
startTransition(() => {
// 低优先级:搜索结果可以延迟
setResults(performSearch(value))
})
}
return (
<div>
<input value={query} onChange={handleSearch} />
{isPending ? (
<Spinner />
) : (
<ResultList results={results} />
)}
</div>
)
}Concurrent Mode 目前仍是实验性特性,2020 年预计会进入稳定阶段。它的核心价值在于:用户输入永远不会被高开销的渲染阻塞,体验将大幅提升。
Vite 的萌芽
Evan You 在开发 Vue 3 的过程中,创造了一个名为 Vite 的开发服务器。Vite 利用浏览器原生 ES Module 支持,在开发环境下无需打包,实现秒级启动和即时热更新。
javascript
// Vite 的核心原理非常简洁
// 开发环境下,浏览器直接请求 ES Module
// index.html
// <script type="module" src="/src/main.js"></script>
// 浏览器发出请求时,Vite 按需编译
// /src/main.js -> 编译后返回
// /src/components/Foo.vue -> 实时编译 .vue 文件返回
// vite.config.js 基础配置
export default {
// 开发服务器配置
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
// 生产构建使用 Rollup
build: {
rollupOptions: {
input: 'index.html'
}
}
}Vite 在 2019 年还处于非常早期的阶段,但它代表的理念——利用浏览器原生能力而非重度打包——很可能是 2020 年乃至更远未来的重要方向。
Deno 能否撼动 Node.js
Node.js 之父 Ryan Dahl 在 2018 年 JSConf 上公开了他对 Node.js 的 10 大遗憾,并发布了 Deno 项目。到了 2019 年,Deno 已经具备了不少实用特性:
typescript
// Deno 的核心特性对比 Node.js
// 1. 原生 TypeScript 支持,无需配置
// hello.ts
const greeting: string = 'Hello, Deno!'
console.log(greeting)
// 2. 使用 URL 导入,无需 npm/yarn
import { serve } from 'https://deno.land/std/http/server.ts'
const server = serve({ port: 8000 })
console.log('HTTP server running on http://localhost:8000/')
for await (const req of server) {
req.respond({ body: 'Hello World\n' })
}
// 3. 安全模型:默认无权限,需显式授权
// deno run --allow-net --allow-read server.ts
// 4. 内置工具链
// deno test 运行测试
// deno fmt 代码格式化
// deno bundle 打包
// deno doc 生成文档Deno 的理念先进,但在 2020 年要撼动 Node.js 的地位仍然很难。生态是最大的壁垒——npm 上百万个包不会一夜迁移。但 Deno 在内部工具、脚本场景中值得尝试。
pnpm 的增长趋势
包管理器领域,npm 和 yarn 占据了绝大多数份额。但 pnpm 凭借其独特的 node_modules 结构,在 2019 年获得了越来越多的关注。
bash
# pnpm 使用硬链接和符号链接,避免重复安装
# 安装速度对比(内部项目测试)
npm install # 45s
yarn install # 32s
pnpm install # 12s
# node_modules 结构差异
# npm/yarn: 扁平化,存在幽灵依赖问题
node_modules/
lodash/ # 直接依赖
axios/ # 依赖的依赖也能被项目访问到(幽灵依赖)
# pnpm: 严格隔离
node_modules/
.pnpm/
lodash@4.17.21/node_modules/lodash/
axios@0.19.2/node_modules/axios/
lodash -> .pnpm/lodash@4.17.21/node_modules/lodash # 符号链接
axios -> .pnpm/axios@0.19.2/node_modules/axiospnpm 的严格依赖隔离解决了幽灵依赖问题,这在大型 monorepo 项目中尤为重要。2020 年我预计 pnpm 的市场份额会有显著提升。
CSS-in-JS vs Utility CSS 的争论
2019 年,CSS 方案的争论依然激烈。一边是 styled-components、Emotion 等 CSS-in-JS 方案,另一边是 Tailwind CSS 代表的 Utility First 方案。
jsx
// CSS-in-JS 方案 (styled-components)
import styled from 'styled-components'
const Button = styled.button`
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
background: ${props => props.primary ? '#1890ff' : '#fff'};
color: ${props => props.primary ? '#fff' : '#333'};
border: ${props => props.primary ? 'none' : '1px solid #d9d9d9'};
&:hover {
opacity: 0.85;
}
`
// Utility CSS 方案 (Tailwind CSS)
function Button({ primary, children }) {
return (
<button
className={`
px-4 py-2 rounded text-sm
${primary
? 'bg-blue-500 text-white border-none'
: 'bg-white text-gray-800 border border-gray-300'
}
hover:opacity-85
`}
>
{children}
</button>
)
}我的判断是:大型应用中 CSS-in-JS 依然有其价值(主题化、动态样式),但 Tailwind CSS 代表的 Utility CSS 在 2020 年会有更大的增长。它的学习曲线虽然陡峭,但一旦团队适应,开发效率和样式一致性都有保障。
小结
- Vue 3 正式版预计 2020 年上半年发布,Composition API 将改变 Vue 的代码组织方式
- React Concurrent Mode 仍处实验阶段,但 useTransition 等 API 值得提前学习
- Vite 利用浏览器原生 ES Module,可能改变开发服务器的工作方式
- Deno 理念先进但生态薄弱,2020 年适合观望和内部尝试
- pnpm 凭借严格的依赖隔离,在大型项目中优势明显
- CSS-in-JS 和 Utility CSS 各有适用场景,Tailwind CSS 增长势头强劲
- 作为前端工程师,保持对新趋势的敏感度,但不过度追逐,选择性深入学习