After.js 项目升级指南:从 v1/v2 迁移到最新版本
前言
After.js 是一个基于 React 的服务端渲染框架,它建立在 Razzle 之上,提供了更简单的路由和数据获取方案。本文将详细介绍如何将 After.js 项目从旧版本升级到最新版本,包括从 v1 到 v2 以及从 v2 到 v3 的迁移过程。
从 v2 升级到 v3
主要变更
v3 版本的主要变更是将 react-helmet
从版本 5 升级到了版本 6。这个升级带来了一个重要的 API 变化:
依赖更新
运行以下命令更新依赖:
yarn upgrade @jaredpalmer/after react-helmet --latest
或使用 npm:
npm install @jaredpalmer/after@latest react-helmet@latest --save
代码变更
react-helmet
从版本 5 到版本 6 的升级中,将默认导出改为了命名导出:
旧代码:
import Helmet from 'react-helmet';
新代码:
import { Helmet } from "react-helmet";
这个变化不会影响 After.js 本身的功能,但需要开发者修改所有使用 Helmet 的代码文件。
从 v1 升级到 v2
为什么需要升级?
v2 版本解决了 v1 中存在的性能问题:
-
更快的资源加载:在 v1 中,浏览器需要先下载
client.js
,解析并执行后,才能开始获取当前页面所需的其他代码块(chunks)。这导致了明显的延迟。 -
样式闪烁问题:由于 CSS 文件也是按需加载的,页面会先以无样式状态渲染,然后突然应用样式,造成不好的用户体验。
-
浏览器渲染机制:浏览器对 CSS 是渲染阻塞的,如果 CSS 在页面渲染后才加载,浏览器需要重新绘制整个页面,这是非常耗性能的操作。
v2 版本通过在服务器响应中直接包含所有需要的 JS 和 CSS 文件,解决了这些问题。
升级步骤
1. 更新依赖
运行以下命令:
yarn upgrade @jaredpalmer/after razzle --latest
或使用 npm:
npm install @jaredpalmer/after@latest razzle@latest --save
2. 添加 Babel 插件
在项目根目录创建或更新 .babelrc
文件:
{
"presets": ["razzle/babel"],
"plugins": ["after"]
}
这个插件会自动处理代码分割相关的配置,简化开发流程。
3. 更新服务器文件
修改 server.js
,添加 chunks 清单:
import chunks from './build/chunks.json'; // 新增导入
const server = express();
server
.disable('x-powered-by')
.use(express.static(process.env.RAZZLE_PUBLIC_DIR))
.get('/*', async (req, res) => {
try {
const html = await render({
req,
res,
document: MyDocument,
chunks, // 新增参数
routes,
assets,
});
res.send(html);
} catch (error) {
console.log(error);
res.json(error);
}
});
4. 更新文档组件
如果你使用了自定义的 Document.js
,需要更新它以使用新的资源加载方式:
import {
AfterRoot,
AfterData,
AfterScripts,
AfterStyles, // 新增导入
} from '@jaredpalmer/after';
class Document extends React.Component {
// ... 其他代码保持不变
render() {
return (
<html>
<head>
{/* ... 其他 head 内容 */}
<AfterStyles /> {/* 替换原来的样式链接 */}
</head>
<body>
<AfterRoot />
<AfterData />
<AfterScripts /> {/* 替换原来的脚本标签 */}
</body>
</html>
);
}
}
高级配置
手动配置代码分割
如果你选择不使用 Babel 插件,需要手动配置路由:
{
path: '/about',
component: asyncComponent({
loader: () => import(/* webpackChunkName: "AboutPage" */ './About'),
chunkName: 'AboutPage', // 必须与 webpackChunkName 一致
}),
}
Babel 插件的限制
Babel 插件无法处理动态生成的路由配置。例如:
function createRoute(name) {
return {
path: `/${name.toLowerCase()}`,
component: asyncComponent({
loader: () => import(`./pages/${name}`),
}),
};
}
对于这种情况,需要手动添加 webpack 魔法注释和 chunkName:
function createRoute(name) {
return {
path: `/${name.toLowerCase()}`,
component: asyncComponent({
loader: () => import(/* webpackChunkName: "[request]" */ `./pages/${name}`),
chunkName: name,
}),
};
}
升级后的优势
- 更快的首屏渲染:所有资源在初始响应中发送,减少了额外的网络请求。
- 更好的用户体验:避免了样式闪烁问题。
- 更符合浏览器渲染机制:CSS 在正确的时间加载,减少了不必要的重绘。
- 简化的开发流程:通过 Babel 插件自动处理大部分代码分割配置。
总结
After.js 的 v2 和 v3 版本带来了显著的性能改进和开发体验提升。通过遵循本指南,你可以顺利地将项目升级到最新版本,享受这些改进带来的好处。升级过程大多数情况下只需要简单的依赖更新和少量代码修改,不会影响现有的业务逻辑。