必须用文件系统API主动校验img src路径有效性,而非依赖浏览器静默加载;需解析相对路径为绝对路径后检查存在性与可读性,远程URL和data:协议应跳过,动态拼接src需逻辑排除。

检查 HTML 中 <img> 标签的 src 文件是否存在
直接用浏览器打开 HTML 无法得知图片是否真能加载——404 错误可能被静默吞掉,或只在控制台显示。必须在构建时或本地校验阶段主动探测文件路径有效性。
核心思路是:提取所有 <img src="..."> 的 src 值,转为相对于 HTML 文件或项目根目录的绝对路径,再用文件系统 API 检查该路径是否存在(且可读)。
- 注意
src可能是相对路径(如"images/logo.png")、绝对路径("/assets/icon.svg")、协议完整 URL("https://cdn.example.com/photo.jpg"),只有前两类可本地检查;协议 URL 需单独发起 HEAD 请求,但超时和跨域限制多,不建议默认启用 - 若 HTML 和资源不在同一目录下(比如 HTML 在
dist/,图片在src/assets/),需明确指定“基准路径”(base directory),否则路径解析会出错 - Node.js 环境推荐用
path.resolve()+fs.existsSync()(同步)或fs.promises.access()(异步更严谨,可检测读权限)
用 Node.js 快速写一个 CLI 工具检查图片路径
不需要引入重型构建工具,一个 20 行左右的脚本就能覆盖大部分静态站点需求。
const fs = require('fs').promises;
const path = require('path');
const { JSDOM } = require('jsdom'); // npm install jsdom
<p>async function checkImageSources(htmlPath, baseDir = path.dirname(htmlPath)) {
const html = await fs.readFile(htmlPath, 'utf8');
const dom = new JSDOM(html);
const imgs = dom.window.document.querySelectorAll('img[src]');</p><p>for (const img of imgs) {
const src = img.src;
if (/^https?:\/\//.test(src)) continue; // 跳过远程 URL
const absPath = path.resolve(baseDir, src);
try {
await fs.access(absPath, fs.constants.R_OK);
} catch {
console.warn(<code><code>${htmlPath}</code>: missing image <code>${src}</code> → <code>${absPath}</code></code>);
}
}
}</p>调用示例:node check-imgs.js ./dist/index.html ./dist。关键点:
立即学习“前端免费学习笔记(深入)”;
-
JSDOM解析比正则可靠,能处理属性引号、空格、注释干扰 -
fs.access(..., fs.constants.R_OK)比existsSync更准——它同时验证存在性和可读性,避免因权限问题导致后续构建失败 - 务必传入
baseDir,否则path.resolve()会以当前工作目录为起点,CI 环境容易误判
Webpack 或 Vite 构建中集成图片路径检查
构建时检查比手动跑脚本更可靠,但要注意时机——必须在 HTML 插件(如 html-webpack-plugin 或 vite-plugin-html)生成最终 HTML 后介入,否则看到的是模板路径而非实际输出路径。
- Webpack:在
compilation.hooks.htmlWebpackPluginAfterHtmlProcessing钩子中读取data.html字符串,解析并检查;注意此时资源已 emit,baseDir应设为compilation.outputOptions.path - Vite:用
transformIndexHtml钩子,但该钩子接收的是字符串而非 DOM,建议用parse5或cheerio解析,再遍历img标签;路径基准设为config.root或config.build.outDir,取决于你检查的是源 HTML 还是构建后 HTML - 别在开发服务器中间件里做这事——每次刷新都检查磁盘 I/O,明显拖慢热更新
常见误报与绕过场景
不是所有“找不到”都该报错。以下情况需逻辑排除,否则 CI 动不动就挂:
- 动态拼接的
src(如<img :src="userAvatar">或<img src="${avatarUrl}">)——静态分析无法识别,应跳过或加注释标记<!-- skip-check: dynamic-src --> - SVG 内联写法(
<img src="data:image/svg+xml;base64,...">)——无需文件检查,正则或 DOM 查询时可过滤掉data:开头的src - 构建时才生成的图片(如通过
vite-plugin-svg-icons注入的图标)——这些路径在源码中不存在,但构建后会被重写,检查应针对dist目录下的最终 HTML,而非源 HTML
路径解析和权限判断本身很稳定,真正复杂的是语义理解:哪些该查、哪些该放行、在哪一环查。漏掉动态场景会误报,过早检查构建前资源会误杀。



















