导读:本期聚焦于Canve创作的《Webpack 中 stats.builtAt 显示构建完成的时间戳应该怎么理解?》,敬请观看详情。统计 Webpack 构建耗时的时候,stats.builtAt 经常被当成格式化的日期直接展示,结果打印出来却是一大串毫秒数。这个字段其实是 compilation 结束阶段记录的 Unix 时间戳,单位是毫秒,需要结合 Date 对象转换成本地可读时间。它默认不一定出现在 stats JSON 中,要在 stats 配置里显式开启 builtAt,或者通过 Node API 的 stats.toJson 选项提取。除了展示构建完成时间,builtAt 还能和 stats.time 配合计算单次构建的起止范围,适合接入 CI 日志、构建统计面板和性能回归监控。理解它的取值时机和配置方式,可以避免把回调时间或当前时间当成构建结束时间,也能让构建日志更加准确。

Webpack 的 stats 对象里有一个字段叫 builtAt,名字看起来像日期,实际拿到的却是一串数字。这串数字是 Unix 时间戳,单位是毫秒,表示一次 compilation 构建完成的时间点。它的主要用途不是直接给用户看,而是给程序做日志记录、耗时统计和构建状态追踪。

Webpack 中 stats.builtAt 显示构建完成的时间戳应该怎么理解?

stats.builtAt 在 Webpack stats 体系里的位置与取值来源

Webpack 在每次构建结束后会生成一个 stats 对象,这个对象可以序列化成 JSON,也可以格式化成终端字符串。stats 数据里包含模块、资源、错误、警告、耗时等多种信息,builtAt 属于时间类字段。它记录的不是字符串形式的日期,而是从 ECMAScript 纪元开始经过的毫秒数,也就是常见的 Unix timestamp 毫秒格式。

从 Webpack 内部编译流程看,builtAt 对应 compilation 结束阶段记录的时间。它和 compiler.hooks.done 回调触发的时间非常接近,但不完全等同。因为 stats 对象的生成、序列化也会消耗少量时间,所以如果在回调里用 Date.now() 代替,得到的结果会略微偏晚。这个差异在普通项目里可能只有几毫秒,但在构建统计面板或 CI 日志里,如果要求时间边界清晰,还是应该以 builtAt 为准。

默认情况下,Webpack 的 normal stats preset 不一定输出 builtAt 字段。如果只是执行 webpack 命令然后查看控制台输出,很可能看不到它。需要使用 verbose 级别的 preset,或者在 stats 配置中显式开启 builtAt,才能保证它在 JSON 或字符串输出中出现。

在 Webpack 配置中开启 builtAt 的几种方式

最常用的做法是在 webpack.config.js 中设置 stats.builtAt。Webpack 的 stats 配置既可以是字符串 preset,也可以是对象。当使用对象形式时,可以精确控制想要输出的字段。下面是一个开启 builtAt 和 assets 的最小配置:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  stats: {
    builtAt: true,
    assets: true
  }
};

如果你通过 Node API 调用 Webpack,不修改全局配置也可以直接获取这个字段。在 stats.toJson() 方法中传入 builtAt: true,就能从结果对象里读取构建完成时间戳。这种方式很适合接入自动构建脚本,不需要污染 Webpack 主配置。

const webpack = require('webpack');
const config = require('./webpack.config.js');

const compiler = webpack(config);

function handleResult(err, stats) {
  if (err) {
    console.error(err);
    return;
  }
  const info = stats.toJson({ all: false, builtAt: true, time: true });
  console.log('builtAt:', info.builtAt);
  console.log('time:', info.time + 'ms');
}

compiler.run(handleResult);

也可以在自定义插件里读取,例如在 compiler.hooks.done 回调中接收 stats 参数,然后调用 toJson 提取。这样做的好处是构建一结束就能立即处理,适合把结果写入日志文件或发送到监控接口。

class BuildTimePlugin {
  apply(compiler) {
    compiler.hooks.done.tap('BuildTimePlugin', function (stats) {
      const info = stats.toJson({ all: false, builtAt: true, time: true });
      console.log('build completed at', info.builtAt);
      console.log('build duration', info.time + 'ms');
    });
  }
}

module.exports = BuildTimePlugin;

把 builtAt 转换成本地可读时间并计算构建耗时

builtAt 直接输出时是一串数字,例如 1743420000000。要让它对开发者友好,需要交给 JavaScript 的 Date 对象处理。new Date(builtAt) 会创建一个日期对象,然后可以调用 toISOString() 得到标准 UTC 时间,也可以调用 toLocaleString() 得到本地时区的可读格式。

const builtAt = 1743420000000;
const time = new Date(builtAt);

console.log(time.toISOString());
console.log(time.toLocaleString('zh-CN', { hour12: false }));

如果需要在 CI 日志里同时记录构建开始时间和结束时间,可以结合 stats.time 字段。Webpack 的 stats.time 表示本次构建消耗的总毫秒数,用 builtAt - time 就能近似得到构建开始时刻。这个方法虽然不是精确到纳秒,但对于日志展示、构建趋势分析已经足够稳定。

function logBuildRange(info) {
  const endTime = new Date(info.builtAt);
  const startTime = new Date(info.builtAt - info.time);

  console.log('start:', startTime.toLocaleString());
  console.log('end:', endTime.toLocaleString());
  console.log('duration:', info.time + 'ms');
}

需要特别注意的是,builtAt 是构建完成时刻,不是当前时间,也不是 stats 输出时刻。多阶段构建、watch 模式、缓存命中时,这个字段的含义仍然不变。只要一次 compilation 结束,它就会被记录一次。因此在 watch 模式下,每次重新构建都会产生新的 builtAt 值。

builtAt 与 Date.now、hooks.done 的区别及常见误区

一个常见的误用是在构建回调里直接用 Date.now() 记录结束时间,然后把它和 builtAt 混在一起比较。实际上 Date.now() 是回调执行时间,统计的是“构建完成之后又执行了多少逻辑”,而 builtAt 是 compilation 完成时刻。前者会包含 stats 生成、回调调度等开销,后者更接近真实构建结束点。

另一个常见问题是时区。很多开发者拿到毫秒时间戳后直接拼到日志里,结果排查问题时还需要手动换算。正确做法是统一使用 ISO 字符串或带时区标记的格式。例如 time.toISOString() 输出的是 UTC 时间,可读性和跨地域协作都更好。如果必须展示本地时间,也要使用 toLocaleString() 而不是手动拼接年月日,因为手工格式化容易在不同 Node 版本或操作系统上出现不一致。

下面通过一个表格对比几种常见的时间来源,帮助区分它们的用途:

数据来源含义单位适用场景
stats.builtAtcompilation 完成时间点毫秒时间戳记录构建结束时刻
stats.time本次构建总耗时毫秒性能统计与阈值告警
Date.now() in done回调执行时刻毫秒时间戳粗略统计,包含额外开销
compilation.endTimecompilation 结束时间毫秒时间戳需要直接访问 compilation 对象

理解了这些差异之后,就可以把 builtAt 放在正确的位置上。比如在构建完成插件里写入 JSON 日志时,建议同时记录 builtAt 和 stats.time,这样后续无论是做性能回归分析,还是排查某次发布是否在预期时间完成,都有清晰的数据依据。不要只记录一个可读日期,因为程序化分析需要的是稳定的时间戳,而不是给人看的字符串。

总体来说,stats.builtAt 是 Webpack 提供给开发者定位构建结束时刻的重要字段。它默认不开启、单位是毫秒、值是一个数字,这些特性决定了它更适合被程序消费。把配置开好、把转换写对、把时间来源分清楚,就能避免大部分构建日志里的时间错乱问题。

Webpack stats.builtAt构建完成时间戳webpack 配置修改时间:2026-10-07 01:33:55

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/1007/66671.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。