3. 静态资源迁移:HTML结构迁移、CSS样式迁移、JavaScript脚本迁移、图片与字体文件处理

静态资源迁移,说白了就是把旧项目里的「皮肉」搬到新环境里。很多人觉得这步就是复制粘贴,结果上线后页面崩得亲妈都不认识。我见过最离谱的一次,团队花了两周迁移,最后发现所有图片路径都写死了绝对路径,部署到子目录下全变404。

这一章,咱们把静态资源拆成四块来讲:HTML、CSS、JavaScript、图片与字体。每块都有坑,每块也都有套路。

核心原则:迁移不是搬运,是适配。新环境可能有不同的域名、不同的目录结构、不同的协议(HTTP→HTTPS),所有资源引用都必须跟着变。

3.1 HTML结构迁移

HTML迁移看起来最简单,但最容易出问题。我习惯先把页面结构拆成三部分:骨架、内容、引用。

  • 骨架:DOCTYPE、html、head、body 这些标签,基本不用动。
  • 内容:文本、表格、列表等,注意编码问题。旧项目可能是 GBK,新环境统一 UTF-8,中文乱码就来了。
  • 引用:CSS 的 link、JS 的 script、图片的 img、字体的 link 或 @font-face。这些是迁移的重灾区。

举个例子,旧项目里可能有这样的引用:

<link rel="stylesheet" href="/css/style.css">
<script src="/js/app.js"></script>
<img src="/images/logo.png" alt="Logo">

如果新环境部署在子路径 /portal/ 下,这些绝对路径就全废了。要么改成相对路径,要么用 <base> 标签统一指定基准 URL。

我的习惯:在 head 里加一行 <base href="/portal/">,所有相对路径都基于这个基准解析。但要注意,<base> 会影响页面内所有相对链接,包括锚点,用之前一定要测试。

3.2 CSS样式迁移

CSS 迁移的坑,我踩过不少。最典型的有三个:

  1. 路径问题:CSS 里引用的图片、字体,比如 background-image: url('../images/bg.png'),路径是相对于 CSS 文件本身的。如果 CSS 文件位置变了,路径就得跟着改。
  2. 兼容性问题:旧项目可能用了只有 IE 才支持的写法,比如 filter 属性。新环境如果是现代浏览器,这些代码可以直接删掉。
  3. 优先级冲突:多个 CSS 文件合并后,选择器优先级可能发生变化。我之前遇到过,迁移后某个按钮颜色变了,查了半天发现是两个文件里都有 .btn 定义,顺序变了导致覆盖关系变了。

怎么解决?我建议分三步走:

  • 第一步:用工具(比如 PurgeCSS)清理无用样式,减少迁移量。
  • 第二步:把所有 url() 引用提取出来,统一替换路径。可以用正则,也可以用 Webpack 的 css-loader 自动处理。
  • 第三步:在浏览器里逐页对比新旧样式,重点关注字体、颜色、间距、布局。

我曾经踩过的坑:迁移一个老项目时,CSS 里用了 @import url('http://old-domain.com/css/common.css')。新环境是 HTTPS,浏览器直接阻止了混合内容加载。所有 @import 必须改成相对路径或同协议路径。

3.3 JavaScript脚本迁移

JavaScript 迁移,说白了就是处理三件事:依赖、路径、兼容性。

问题类型 典型表现 解决方案
依赖缺失 控制台报错 Uncaught ReferenceError: xxx is not defined 检查所有 script 标签顺序,确保依赖库先加载
路径错误 AJAX 请求 404,或图片/文件加载失败 全局搜索硬编码的 URL,替换为动态路径或配置变量
API 兼容性 旧 API 在新浏览器中被废弃(如 document.all) 用 polyfill 或重写为现代 API
跨域问题 XMLHttpRequest 被 CORS 策略阻止 后端配置 CORS 头,或使用 JSONP(已不推荐)

我个人习惯在迁移前先做一次「依赖审计」。打开旧项目的页面,在控制台里看 Network 面板,把所有加载的 JS 文件列出来,搞清楚加载顺序和依赖关系。然后在新环境里按同样的顺序引入。

如果项目用了模块化(比如 RequireJS、CommonJS),迁移时要注意模块路径。举个例子:

// 旧项目路径
define(['lib/jquery', 'app/utils'], function($, utils) { ... });

// 新环境路径可能变了
define(['/portal/lib/jquery', '/portal/app/utils'], function($, utils) { ... });

这种时候,我建议用路径映射(paths config)统一管理,而不是一个个改。

一个小技巧:在全局定义一个 window.BASE_URL = '/portal/',所有动态生成的 URL 都拼接这个变量。以后换路径,改这一个地方就行。

3.4 图片与字体文件处理

图片和字体,说白了就是「静态资源」里的重头戏。它们体积大、数量多、路径散,迁移起来最烦人。

图片处理

图片迁移我分四步走:

  1. 收集:用爬虫或手动扫描,找出所有图片引用。包括 HTML 里的 <img>、CSS 里的 background-image、JS 里动态创建的 new Image()。
  2. 复制:把图片文件按原目录结构复制到新环境。注意保持目录层级一致,否则路径全得改。
  3. 优化:迁移过程中顺便做一次压缩。我常用 imagemin 批量处理,能省 30%-50% 的体积。
  4. 验证:用工具(比如 broken-link-checker)扫描所有图片链接,确保没有 404。

注意:有些图片是用户上传的,存储在服务器本地或云存储上。迁移时不能只复制文件,还要更新数据库里的路径字段。我曾经漏掉这一步,结果用户头像全挂了,被投诉了一整天。

字体处理

字体迁移相对简单,但有个坑:字体文件通常有版权限制。迁移前先确认字体是否允许在目标域名下使用。

字体引用的常见方式有两种:

  • @font-face:在 CSS 里定义,引用 .woff、.woff2、.ttf 等文件。
  • Google Fonts / 第三方 CDN:通过 <link> 引入外部字体。

如果是自托管字体,迁移时注意两点:

  • 字体文件路径要更新,和图片一样处理。
  • 不同浏览器需要的字体格式不同(WOFF2、WOFF、TTF、EOT),确保所有格式都复制过去了。

如果是第三方 CDN 字体,迁移时建议改成自托管。为什么?因为第三方 CDN 可能被墙、可能慢、可能突然改版。我见过一个项目,迁移后 Google Fonts 加载失败,页面字体全变成默认宋体,设计稿直接废了。

我的建议:把字体文件下载到本地,用 @font-face 引用。虽然多了几百 KB 的体积,但稳定性和可控性高得多。

3.5 知识体系总览

下面这张图,把静态资源迁移的核心流程和关键节点串起来了。你可以把它当作迁移时的检查清单。

静态资源迁移知识体系 静态资源迁移核心流程 静态资源迁移 HTML 结构迁移 CSS 样式迁移 JavaScript 迁移 图片与字体处理 骨架 内容 引用路径 路径替换 兼容性 优先级冲突 依赖审计 路径映射 跨域处理 收集复制 压缩优化 版权验证 迁移后必做验证 1. 所有页面无 404 资源 2. 样式与旧环境一致 3. 交互功能正常 4. 字体加载正确 5. 跨域请求正常 6. 性能无明显下降

嗯,这张图基本把这一章的内容都串起来了。你迁移的时候,可以对着它一项一项检查,不容易漏。

3.6 迁移后的验证清单

最后,我整理了一份验证清单。每次迁移完,我都会逐条过一遍:

  • HTML:所有页面能正常渲染,没有乱码,没有标签未闭合。
  • CSS:样式与旧环境一致,没有丢失的样式,没有意外的覆盖。
  • JavaScript:控制台无报错,所有交互功能正常,AJAX 请求返回正确数据。
  • 图片:所有图片能正常显示,没有 404,没有跨域错误。
  • 字体:字体加载正确,没有 FOIT(Flash of Invisible Text)或 FOUT(Flash of Unstyled Text)。
  • 性能:资源加载速度可接受,没有不必要的重定向。

一个小建议:用浏览器的开发者工具,在 Network 面板里过滤 404 和 500,能快速定位所有失败的资源请求。我每次迁移完都会跑一遍这个检查,省时省力。