如果你在 TYPO3 上工作过相当长的时间,你就知道它是一个强大的系统。不是不好的强大——它非常强大,特别是对于具有复杂内容结构、多语言设置和细粒度权限的大型欧洲企业网站。但运行 TYPO3 安装的团队中越来越多地意识到:这个单体架构正在阻碍他们的发展。前端开发人员想要使用 React 或 Vue。营销团队想要全渠道内容交付。DevOps 想要更简单的部署。每个人都想要更好的性能。

这就是无头 CMS 迁移的用武之地。我已经多次经历过这个过程——将组织从 TYPO3 迁移到无头架构——我会坦诚地说:这从来不像厂商营销页面建议的那样简单。但当条件合适时,这绝对值得做。本指南涵盖了从 TYPO3 迁移到无头 CMS 时涉及的真实决策、陷阱和策略。

目录

TYPO3 to Headless CMS Migration: A Practical Developer Guide

为什么团队离开 TYPO3

让我说清楚:TYPO3 不是坏软件。它成熟、维护良好,并有一个专业的社区,特别是在德国、奥地利和瑞士。但它带有某些架构约束,在规模扩大时变得令人痛苦。

开发者体验摩擦

TYPO3 的模板系统(Fluid)功能强大但很小众。找到懂 Fluid、TypoScript 和 Extbase/TYPO3 扩展框架的开发人员变得越来越困难。学习曲线陡峭,年轻开发人员绝大多数更喜欢使用 JavaScript 框架。我见过聘用时间加倍,因为团队找不到 TYPO3 开发人员。

性能限制

TYPO3 通过 PHP 进行服务器端页面渲染。虽然缓存有所帮助,但从根本上你受到单体请求周期的限制。静态网站生成和边缘渲染——现代框架做得很好的东西——在 TYPO3 的架构中并不原生支持。TYPO3 无头扩展(EXT:headless)存在并将 TYPO3 变成 API,但此时你维护的 PHP 后端所做的实际工作越来越少。

内容重用挑战

TYPO3 的内容模型以页面为中心。内容元素位于页面上。如果你需要同时向移动应用、数字信息亭、电子邮件系统和网站交付内容,TYPO3 的模型在每一步都会与你对抗。无头 CMS 平台从一开始就将内容视为结构化数据,使多渠道交付变得自然而非附加。

总拥有成本

运行 TYPO3 意味着维护 PHP 服务器、管理 TYPO3 核心更新(在主版本之间可能很复杂)以及保持扩展兼容性。无头 SaaS CMS 消除了大部分基础架构开销。即使自托管的无头选项如 Strapi 或 Directus 通常也需要更少的操作工作。

迁移何时真正有意义

并非每个 TYPO3 网站都需要改为无头。以下是我的诚实评估:

场景 迁移? 原因
简单宣传网站,50 页,一种语言 可能不需要 过度设计。TYPO3 在这里工作得很好。
多语言企业网站带有移动应用 无头对于全渠道交付表现出色
具有复杂产品数据的电子商务 更好的前端灵活性、API 优先集成
带有大量 TYPO3 扩展的网站(新闻、事件、表单) 也许 首先审计扩展依赖项
具有 TYPO3 后端工作流的内部门户 谨慎 你可能会失去难以替换的工作流功能
团队无法聘请 TYPO3 开发人员 可持续性比功能更重要

当你已经计划重新设计或平台升级时,迁移最有意义。纯粹出于技术原因迁移——没有业务触发——通常很难获得预算批准。

选择你的无头 CMS

这是团队卡住的地方。有数十种无头 CMS 选项,正确的选择在很大程度上取决于你的具体情况。

企业级选项

Contentful 仍然是企业无头 CMS 的市场领导者。定价从 Team 计划的约 $300/月开始,升级到自定义企业定价(通常根据使用情况在 $2,000-$10,000+/月)。它成熟、文档齐全,有优秀的 SDK。内容建模灵活,Compose 功能处理 TYPO3 编辑已习惯的页面构建用例。

Sanity 是我个人最喜欢的开发者体验。定价模型很慷慨——免费层处理许多小项目,Team 计划以 $15/用户/月的价格合理。Sanity Studio 完全可以用 React 定制,所以你可以构建与或超越 TYPO3 后端的编辑体验。GROQ 查询语言需要一些时间来适应,但一旦你掌握,它非常强大。

Storyblok 值得特别关注 TYPO3 迁移,因为它提供一个对 TYPO3 后端用户感到熟悉的可视化编辑器。定价从 Entry 计划的 €99/月开始。它在 DACH 地区特别受欢迎,这与 TYPO3 的用户基础大幅重叠。

开源替代方案

Strapi(v5 于 2024 年发布)是领先的开源选项。你可以自托管或使用 Strapi Cloud(起价 $29/月每个座位)。它基于 Node.js,使用 PostgreSQL 或 MySQL 数据库,并提供一个快速增长的插件生态系统。

Directus 用 API 和管理面板包装任何 SQL 数据库。如果你想保持现有的数据库结构并逐步迁移,这是一个很好的选择。开源版本功能完整;云版本起价 $99/月。

比较表:TYPO3 迁移的无头 CMS 选项

功能 Contentful Sanity Storyblok Strapi Directus
托管模型 SaaS SaaS + 自托管 SaaS 自托管 + Cloud 自托管 + Cloud
可视化编辑器 Compose(附加) 可定制 内置 插件 受限
多语言 优秀 很好 优秀 很好 很好
起始价格 $300/月 免费层 €99/月 免费(OSS) 免费(OSS)
TYPO3 编辑熟悉度 中等 中等 中等
内容建模 灵活 非常灵活 基于组件 灵活 数据库驱动
Webhooks/工作流

我们通过我们的无头 CMS 开发服务与大多数这些平台合作。选择通常归结为你的编辑是否需要可视化编辑体验(Storyblok、Contentful Compose)或开发者灵活性是否是优先考虑(Sanity、Strapi)。

TYPO3 to Headless CMS Migration: A Practical Developer Guide - architecture

内容建模:困难的部分

这就是大多数迁移出错的地方。TYPO3 的内容模型在根本上不同于无头 CMS 内容模型,你不能只是将一个映射到另一个。

理解 TYPO3 的内容结构

在 TYPO3 中,内容被组织为:

  • 页面(页面树)带属性和元数据
  • 内容元素(tt_content)位于页面上的列中
  • 扩展添加自定义记录类型(新闻、事件等)
  • 类别文件引用通过 sys_file_reference 表链接
  • TypoScript 配置影响渲染和数据流

这是一个以页面为中心的模型。内容存在于页面的背景下。

无头内容建模

无头 CMS 平台使用内容优先的模型。你定义内容类型(如 Article、Author、Product)带字段,然后从对这些内容项的引用组成页面。页面本身通常只是另一个内容类型。

翻译工作看起来像这样:

TYPO3 页面树          →  带有 slug/层级字段的页面内容类型
tt_content(文本)    →  富文本组件/块
tt_content(图像)    →  带有资产引用的媒体组件
tx_news_domain_model_news →  Article/News 内容类型
Categories(sys_category) →  标签/类别内容类型
文件引用              →  资产管理(DAM)

实用建议

不要尝试在无头 CMS 中复制 TYPO3 的内容模型。这是重新思考和改进内容架构的机会。从审计开始:

  1. 存在什么内容类型? 导出你的 tt_content CTypes 并列出所有扩展记录类型。
  2. 实际使用什么字段? TYPO3 表有几十个字段。大多数内容只使用少数几个。
  3. 关系是什么? 映射内容如何引用其他内容。
  4. 翻译设置是什么? TYPO3 支持连接和自由翻译模式——你的无头 CMS 需要处理你使用的任何一种。
-- 有用的 TYPO3 审计查询
-- 按类型计算内容元素
SELECT CType, COUNT(*) as count 
FROM tt_content 
WHERE deleted = 0 AND hidden = 0 
GROUP BY CType 
ORDER BY count DESC;

-- 按 doktype 计算页面
SELECT doktype, COUNT(*) as count 
FROM pages 
WHERE deleted = 0 AND hidden = 0 
GROUP BY doktype 
ORDER BY count DESC;

-- 查找正在使用的所有语言
SELECT sys_language_uid, COUNT(*) as count 
FROM tt_content 
WHERE deleted = 0 
GROUP BY sys_language_uid;

数据迁移策略

一旦在目标 CMS 中定义了内容模型,你需要实际移动数据。有三种主要方法。

方法 1:基于脚本的导出/导入

编写直接查询 TYPO3 数据库的脚本,转换数据,并通过其管理 API 将其推送到无头 CMS。这是最常见的方法,给你最多的控制。

// 示例:将 TYPO3 新闻记录迁移到 Contentful
const contentful = require('contentful-management');
const mysql = require('mysql2/promise');

async function migrateNews() {
  const db = await mysql.createConnection({
    host: 'localhost',
    database: 'typo3_db',
    user: 'root',
    password: 'password'
  });

  const client = contentful.createClient({
    accessToken: 'your-management-token'
  });

  const space = await client.getSpace('your-space-id');
  const env = await space.getEnvironment('master');

  const [rows] = await db.execute(`
    SELECT n.uid, n.title, n.teaser, n.bodytext, n.datetime,
           n.path_segment, p.slug as category_slug
    FROM tx_news_domain_model_news n
    LEFT JOIN sys_category_record_mm mm ON mm.uid_foreign = n.uid
    LEFT JOIN sys_category c ON c.uid = mm.uid_local
    WHERE n.deleted = 0 AND n.hidden = 0
  `);

  for (const row of rows) {
    const entry = await env.createEntry('article', {
      fields: {
        title: { 'en-US': row.title },
        teaser: { 'en-US': row.teaser },
        body: { 'en-US': convertRteToRichText(row.bodytext) },
        publishDate: { 'en-US': new Date(row.datetime * 1000).toISOString() },
        slug: { 'en-US': row.path_segment }
      }
    });
    await entry.publish();
    console.log(`Migrated: ${row.title}`);
  }
}

convertRteToRichText 函数是事情变得混乱的地方。TYPO3 的 RTE 输出是 HTML(通常带有自定义标签如 <link> 用于内部链接)。将其转换为结构化富文本格式因 CMS 而异——Contentful 使用自己的富文本 JSON,Sanity 使用 Portable Text 等等。

方法 2:TYPO3 无头扩展作为桥接

在你现有的 TYPO3 实例上安装 EXT:headless 扩展。这将 TYPO3 变成 JSON API,你可以从迁移脚本消费它,甚至在构建新前端时暂时使用它作为无头后端。

这种方法有个不错的优点:你可以先针对 TYPO3 的无头 API 运行新前端,然后稍后将后端切换到适当的无头 CMS。它将迁移分为两个阶段。

方法 3:手动重建

对于较小的网站(100 页以下),有时在新 CMS 中手动重建内容更快。特别是如果你也在重组和重写内容——你可能应该这样做。

前端架构决策

使用无头 CMS,你需要一个单独的前端。这是真正性能收益发生的地方。

Next.js

最受欢迎的选择。服务器端渲染、静态生成、增量静态重新生成——Next.js 处理你可能需要的所有渲染策略。App Router(自 Next.js 13.4 起稳定)与 React Server Components 特别适合内容丰富的网站。我们通过我们的 Next.js 开发实践做很多这样的工作。

Astro

对于不需要太多交互性的内容丰富的网站,Astro 非常出色。默认情况下不发送 JavaScript,并通过其 Islands Architecture 支持部分水合。我们看到 Astro 构建一致地在 Lighthouse 分数中达到 95+,这与典型 TYPO3 前端性能相比是戏剧性的改进。如果这让你感兴趣,请查看我们的 Astro 开发服务

Nuxt

如果你的团队更喜欢 Vue 而不是 React,Nuxt 3 是 Next.js 的等价物。坚实的选择,很好的 DX,好的生态系统。

框架 最适合 JS 发送 学习曲线 CMS 集成
Next.js 动态应用、电子商务、仪表板 中-高 中等 优秀
Astro 内容网站、博客、营销 最小 优秀
Nuxt 3 Vue 团队、内容 + 应用 中等 中等 很好
SvelteKit 小团队想要简洁 低-中等 增长中

处理 TYPO3 特定功能

一些 TYPO3 功能在无头世界中没有直接等价物。以下是如何处理常见功能。

工作区和版本控制

TYPO3 的工作区系统让编辑在发布前在多个页面上暂存更改。大多数无头 CMS 平台提供环境或发布调度,部分复制这个功能。Contentful 有环境和定时发布。Sanity 最近推出了发布功能。开箱即用时,没有一个与 TYPO3 工作区一样复杂,所以如果你的编辑严重依赖工作区,计划工作流调整。

后端用户权限

TYPO3 的权限系统极其细粒度——页面级、内容元素级、字段级访问控制。无头 CMS 平台在这里差异很大。Contentful 的角色系统不错但不够细粒度。Sanity 的更灵活但需要自定义配置。Strapi 的基于角色的访问很好。在承诺前审计你当前的权限矩阵并验证目标 CMS 能否处理它。

表单处理

TYPO3 的表单框架(EXT:form)从 YAML 配置生成表单。在无头设置中,你需要一个表单服务。选项包括 Formspree、Basin 或使用无服务器函数构建你自己的。如果你使用 Next.js,Server Actions 使表单处理简单明了。

多语言和本地化

这很关键,通常被低估。TYPO3 的翻译处理——带有其语言覆盖概念、连接/自由模式和回退链——很复杂。在选择 CMS 前映射你的确切翻译要求。Storyblok 和 Contentful 处理区域设置管理很好。Sanity 对于复杂的多语言场景需要更多自定义设置。

迁移过程中保留 SEO

这部分可能是最重要的。一次失败的迁移可能会摧毁你的有机流量。

URL 映射

从你的 TYPO3 网站导出每个 URL。每一个。使用爬虫如 Screaming Frog 或 wget --spider 构建一个完整的 URL 列表。然后创建一个重定向映射:

/old-typo3-path/page.html → /new-clean-path
/index.php?id=42 → /about-us
/fileadmin/documents/report.pdf → /assets/report.pdf

为每个改变的 URL 实现 301 重定向。在 Next.js 中,这进入 next.config.js

// next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/old-path/:slug*',
        destination: '/new-path/:slug*',
        permanent: true,
      },
      // ... 数百个更多,理想情况下从 JSON 文件加载
    ];
  },
};

对于大型重定向列表(500+),考虑在边缘处理重定向(Vercel Edge Middleware、Cloudflare Workers 或 nginx)而不是在应用配置中。

元数据迁移

TYPO3 在页面表中存储 SEO 元数据(seo_title、description、og_image 等)以及可能在扩展如 EXT:cs_seo 或 EXT:seo_basics 中。提取所有这些并将其迁移到你的无头 CMS 内容模型。不要忘记:

  • 页面标题和元描述
  • Open Graph 和 Twitter Card 数据
  • 规范 URL
  • 多语言网站的 hreflang 标签
  • 结构化数据 / JSON-LD 模式
  • XML 站点地图生成

监控

在迁移前为新域/子域在 Google Search Console 中设置。上线后,前两周每天监控覆盖范围报告。查看爬虫错误、丢失的页面和索引问题。有一个回滚计划。

测试和上线策略

我建议分阶段方法而不是一次性切换。

第 1 阶段:并行运行(2-4 周)

在暂存域上运行新的无头网站。比较与 TYPO3 网站的内容奇偶性。让编辑测试内容工作流。使用 Percy 或 Playwright 等工具运行自动化视觉回归测试。

第 2 阶段:软启动

使用特性标志或 CDN 级别的 A/B 测试将一小部分流量路由到新网站。监控 Core Web Vitals、错误率和用户行为。

第 3 阶段:完全切换

切换 DNS 或反向代理配置。激活所有重定向。积极监控 48 小时。保持 TYPO3 实例运行(只读)至少 30 天作为参考。

第 4 阶段:停用

一旦你确信迁移稳定,关闭 TYPO3 基础设施。存档数据库和 fileadmin 目录。当有人询问旧内容时,你会感谢自己。

真实世界迁移时间表和成本

让我们坦诚地说这花费多少。我见过太多团队低估迁移项目。

项目大小 页面 时间表 估计成本
50-200 6-10 周 $15,000-$35,000
200-1,000 12-20 周 $40,000-$90,000
1,000-5,000 20-36 周 $80,000-$200,000
企业 5,000+ 6-12 月 $150,000-$500,000+

这些数字包括内容建模、迁移脚本、前端开发、测试和启动支持。它们不包括 CMS 许可成本,这因平台而异。

最大的成本驱动因素是:

  1. 内容类型数量和复杂性 —— 不是原始页面计数
  2. 需要构建等价功能的自定义 TYPO3 扩展
  3. 多语言设置复杂性
  4. 集成要求(搜索、电子商务、身份验证)
  5. 编辑培训和变更管理

如果你想讨论针对你具体情况的迁移可能看起来如何,联系我们或查看我们的定价页面以了解参与模型。

常见问题

我能否使用 TYPO3 作为无头 CMS 而不是迁移到新的? 是的,EXT:headless 扩展(以前的"headless")将 TYPO3 变成 JSON API。这可以是一个好的中间步骤。然而,你仍然在维护一个 TYPO3 后端及其所有操作开销。作为桥接策略它有意义,但通常不是长期答案,如果你的目标是减少 TYPO3 依赖。

典型的 TYPO3 到无头 CMS 迁移需要多长时间? 对于中等大小的网站(200-1,000 页),预期从启动到上线需要 3-5 个月。内容建模和迁移脚本阶段通常比团队预期花费更长时间。前端开发通常可以在内容模型定义后并行运行。具有多种语言和复杂集成的企业迁移可能需要 6-12 个月。

我会在迁移过程中失去 SEO 排名吗? 如果你正确进行,你不应该。关键因素是:为所有改变的 URL 实现正确的 301 重定向、迁移所有元数据、维持网站结构和内部链接,以及向 Google 提交更新的站点地图。迁移后排名临时下降 2-4 周是正常的,通常会恢复。永久性损失通常表示错过的重定向或丢失的内容。

哪个无头 CMS 最适合替换 TYPO3? 这取决于你的优先事项。对于 TYPO3 编辑,Storyblok 通常是最平稳的过渡,因为其可视化编辑功能。Contentful 是最安全的企业选择,具有最成熟的生态系统。Sanity 提供最多的开发者灵活性。Strapi 是你需要开源和自托管时的最佳选项。没有单一最佳答案——它取决于你的团队、预算和要求。

迁移后我的 TYPO3 扩展会发生什么? 每个扩展都需要单独评估。常见扩展如 EXT:news、EXT:cal 和 EXT:powermail 需要新堆栈中的等价功能。新闻/博客功能很容易用任何无头 CMS 复制。日历和事件功能可能需要第三方服务。表单需要新解决方案(表单生成器、无服务器函数或像 Formspree 这样的服务)。自定义扩展需要最多分析。

我如何在迁移过程中处理 TYPO3 的 fileadmin 资产? 你需要将所有资产(图像、PDF、视频)迁移到你的新 CMS 的资产管理系统或单独的 DAM/CDN。编写一个从 fileadmin 下载、通过其 API 上传到新平台并将旧文件引用映射到新资产 ID 的脚本。不要忘记处理已处理/调整大小的图像——大多数无头 CMS 平台自动处理图像转换,所以你通常只需要迁移原始文件。

我能否增量迁移或必须一次性完成? 增量迁移是可能的,对大型网站有时是可取的。你可以使用反向代理将特定 URL 路径路由到新的无头前端,同时保持其他路径在 TYPO3 上。这让你逐段迁移。权衡是同时管理两个系统的增加复杂性,并维持两个系统间的一致导航和设计。

我应该怎样对待抵制变化的 TYPO3 后端用户? 变更管理真的是一半的战斗。尽早让编辑参与——在内容建模阶段向他们展示新 CMS,而不是在一切都构建好后。选择一个编辑体验好的 CMS(Storyblok 和 Contentful 往往获得最佳编辑反馈)。创建特定于你设置的文档和培训材料。诚实地说明什么在改变以及为什么——当编辑看到改进的预览体验和更快的发布工作流时,他们通常会同意。