☰
Modernizr 4.x 实战指南:HTML5/CSS3 特性检测原理、异步监听 API 与自定义构建
2026/9/30 2:12:55 网站建设 项目流程

【免费下载链接】Modernizr

Modernizr is a JavaScript library that detects HTML5 and CSS3 features in the user’s browser.

项目地址:https://gitcode.com/gh_mirrors/mo/Modernizr
点击查看免费下载

Modernizr 是一个运行在浏览器端的 JavaScript 特性检测库,能够在当前用户代理(UA)中探测原生 CSS3 与 HTML5 特性的支持情况,并以"全局Modernizr对象属性 +<html>元素类名"两种方式暴露检测结果,从而让开发者以颗粒度极细的控制权对页面进行渐进增强(progressive enhancement)。本文以仓库中的 README 文档(卡纳达语版 README.ka.md 与英文原版 README.md 均指向同一份核心内容)为主体,结合仓库源码深入讲解 v4 破坏性变更、异步事件监听 API、构建工具链与测试流程,读完即可独立完成从获取仓库、自定义构建到监听异步检测结果的完整实践。

Modernizr 是什么:双通道输出检测结果

Modernizr 的核心职责非常聚焦:测试当前 UA(浏览器环境)中可用的原生 CSS3 和 HTML5 特性,然后把结果以两种方式交付给开发者:

  1. 全局Modernizr对象的属性:例如Modernizr.canvas、Modernizr.flexbox,值为true/false;
  2. <html>元素上的类名:例如支持时添加canvas、flexbox,不支持时添加no-canvas、no-flexbox。

有了这两类输出,你就可以基于检测结果对页面做渐进增强:在不支持的浏览器上提供基础体验,在支持的浏览器上叠加高级能力,而不是依赖 UA 字符串猜测(UA sniffing)。

从源码层面看,这一机制的底层实现位于 src/addTest.js 的addTest()函数:任何一次特性检测的结果都会被写入Modernizr对象(Modernizr[feature] = test),同时通过setClasses([(!!test && test !== false ? '' : 'no-') + featureNameSplit.join('-')])在<html>上打上对应的类名。检测项名称会被统一转为小写,例如调用addTest('itsTuesday', ...)后访问的是Modernizr.itstuesday而非Modernizr.itsTuesday;名称中带.的检测(如Modernizr.input.list)还会被拆分成两级嵌套属性。

v4 破坏性变更清单

v4 相对旧版本有一批需要开发者注意的破坏性变更,迁移时建议逐条核对:

运行环境要求

  • Node 版本支持收紧:放弃对 Node <= 10 的支持,请至少升级到 12(当前仓库 package.json 的engines字段声明为node >= 16,实际运行请以仓库声明为准)。

测试重命名

  • class重命名为es6class,与其余 es 系列测试(es5、es6、es7、es8 等)的命名保持一致。

测试迁移到子目录

v4 把大量顶层特性检测文件整理进按主题划分的子目录,迁移清单如下:

原位置新子目录
cookies、indexeddb、indexedblob、quota-management-api、userdatastorage
audioaudio
batterybattery
canvas、canvastextcanvas
customevent、eventlistener、forcetouch、hashchange、pointerevents、proximityevent
exiforientationimg
capture、fileinput、fileinputdirectory、formatattribute、input、inputnumber-l10n、inputsearchevent、inputtypes、placeholder、requestautocomplete、validationinput
svgsvg
webglwebgl

这份目录结构在仓库的 feature-detects 目录中可以直接印证——例如storage/cookies.js、input/capture.js、canvas/canvas.js等文件均按上述子目录归位。同时 lib/config-all.json 中的feature-detects数组也统一使用了目录/检测名的写法。

被移除的测试

v4 移除了以下重复或过时的检测:

  • touchevents:已被移除(详见相关讨论);
  • unicode:已被移除;
  • templatestrings:与 es6 检测stringtemplate重复;
  • contains:与 es6 检测es6string重复;
  • datalistelem:与Modernizr.input.list重复。

迁移时如果旧代码里依赖了上述检测名,需要改用对应的替代检测。

异步事件监听 API:Modernizr.on

为什么需要异步监听

并非所有特性检测都是同步完成的——部分检测需要等待资源加载、回调或用户交互后才能出结果。过去,开发者只能通过轮询Modernizr对象属性或监听<html>类名变化来感知异步测试是否完成,既笨拙又容易出错。v4 引入的Modernizr.onAPI 正是为了解决"异步测试何时完成"这一问题:只有异步测试才会触发事件,同步测试应当同步处理以换取速度和一致性。

基本用法

监听一个测试并传入回调:

// 监听一个测试,传入回调 Modernizr.on("testname", function (result) { if (result) { console.log("The test passed!"); } else { console.log("The test failed!"); } });

关键约定:

  • 回调保证只调用一次(每次调用on注册的回调都只触发一次);
  • 回调参数result为布尔值:true表示支持,false表示不支持;
  • 目前不对外暴露trigger方法;如果你想完全掌控异步测试的触发时机,应使用src/addTest特性——任何通过addTest注册的测试都会自动暴露并触发on功能。

源码级原理:on 与 _trigger 的实现

从 src/addTest.js 可以看到这套事件机制的全部实现:

  • ModernizrProto.on(feature, cb):首次监听某个特性时在ModernizrProto._l(内部监听器表)上创建数组并推入回调;如果该测试已经解析完成(Modernizr.hasOwnProperty(feature)为真),则在下一个 tick(setTimeout(..., 0))立即调用Modernizr._trigger(feature, Modernizr[feature])补发结果,保证"先测完、后监听"也能收到回调;
  • ModernizrProto._trigger(feature, res):取出该特性的全部回调,在下一个 tick 逐个调用并传入结果,随后delete this._l[feature]清空监听器表——这正是"每个on注册的回调只会被调用一次"的保证来源。

值得一提的是addTest()内部在写入结果、设置类名之后会调用Modernizr._trigger(feature, test),因此你自己通过addTest定义的自定义检测同样可以无缝接入on事件体系。此外,用addTest注册检测时如果试图覆盖一个已存在的测试,函数会直接返回而不覆盖(防止与官方检测冲突)。

快速开始:获取仓库并安装依赖

在本地搭建开发环境只需两步:

# 克隆或下载仓库 git clone https://gitcode.com/gh_mirrors/mo/Modernizr.git # 安装项目依赖 npm install

安装完成后即可进入下一节的构建环节。

构建 Modernizr:两种方式

方式一:通过 JavaScript(npm 包编程式调用)

Modernizr 可以经 npm 以编程方式使用:

var modernizr = require("modernizr");

其中暴露了一个build方法用于生成自定义的 Modernizr 构建(只包含你需要的检测项,体积更小):

var modernizr = require("modernizr"); modernizr.build({}, function (result) { console.log(result); // the build });

参数说明:

  • 第一个参数:JSON 配置对象,用于声明要包含的 options 与 feature-detects,所有可用配置项参见 lib/config-all.json;
  • 第二个参数:任务完成后的回调函数,其参数result即为生成的构建产物字符串。

配置对象的整体结构(取自仓库实际配置)如下:

{ "classPrefix": "", "enableClasses": true, "enableJSClass": true, "scriptGlobalName": "window", "usePrefixes": true, "minify": false, "options": [ "addTest", "atRule", "domPrefixes", "hasEvent", "html5shiv", "html5printshiv", "load", "mq", "prefixed", "prefixes", "prefixedCSS", "setClasses", "testAllProps", "testProp", "testStyles" ], "feature-detects": [ "canvas/canvas", "css/flexbox", "storage/localstorage" ] }

其中:

  • classPrefix:类名前缀,为空字符串时不加前缀;
  • enableClasses:是否在<html>上写入特性类名;
  • enableJSClass:是否在无 JS 时保留no-js类;
  • scriptGlobalName:Modernizr挂载到哪个全局对象(默认window);
  • usePrefixes:检测时是否尝试厂商前缀;
  • minify:是否压缩输出;
  • options:需要引入的基础能力模块(对应 src 目录下的模块文件);
  • feature-detects:需要包含的特性检测列表,路径相对于 feature-detects 目录。

从构建链路看,src/generate.js 会按config.options与config['feature-detects']拼装出一个 require.js 构建脚本:setClasses选项被特殊处理(会额外引入setClasses与classes模块);html5printshiv与html5shiv互斥(同时出现时只保留前者);每个检测路径若未以test/开头会被自动补齐前缀。最终构建体通过scriptGlobalObject.Modernizr = Modernizr暴露到全局。

方式二:命令行接口(CLI)

仓库同时提供了命令行构建工具,查看所有可用选项:

./bin/modernizr

CLI 入口 bin/modernizr(Windows 对应 bin/modernizr.bat)支持的参数如下(与源码中的 yargs 定义一致):

短参数长参数说明
-h--help打印帮助信息
-V--version打印版本号并退出
-f--features逗号分隔的特性检测列表
-o--options逗号分隔的可扩展选项列表
-c--configJSON 配置文件路径(示例参见 lib/config-all.json)
-d--dest构建产物输出路径,默认./modernizr.js
-m--metadata特性检测元数据输出路径,默认./metadata.json
-u--uglify压缩/混淆输出
-s--scriptGlobalNameModernizr挂载的全局变量名,默认window
-q--quiet静默所有输出

典型用法组合示例:

# 基于配置文件构建 ./bin/modernizr -c my-config.json -d ./dist # 直接内联指定特性与选项(压缩输出) ./bin/modernizr -f css/flexbox,storage/localstorage -o setClasses -u

使用-f/-o时,CLI 会读取Modernizr.metadata()与Modernizr.options()(实现见 lib/options.js,其通过扫描 src 目录中 JSDoc 注释的@optionName/@optionProp标签汇总选项)把属性名映射回对应的 AMD 模块路径;若遇到未知属性名会抛出invalid key value name错误。

如果想基于 lib/config-all.json 一次性生成全部检测项的完整构建,可直接运行 npm 脚本:

npm start // 输出到 ./dist/modernizr-build.js

该命令等价于执行gulp default(见 package.json 的 scripts 与 gulpfile.babel.js),任务链为clean → eslint → generate,最终由generate任务调用modernizr.build(config-all, ...)将产物写入dist/modernizr-build.js。

测试 Modernizr:命令行与浏览器两种跑法

方式一:命令行无头测试

使用 mocha-headless-chrome 在控制台执行全部测试:

npm test

npm test对应gulp test,其任务链为clean → eslint → generate → pug → mocha:node → mocha:browser(见 gulpfile.babel.js),即先做 ESLint 检查、生成构建、编译 Pug 测试模板,再依次运行 Node 端测试与浏览器端无头测试(通过mocha-headless-chrome分别加载test/integration.html与test/unit.html)。

方式二:在浏览器中手动测试

你也可以用下面的命令启动本地静态服务,然后在任意浏览器中打开测试页:

npm run serve-gh-pages

serve-gh-pages对应gulp serve:gh-pages,任务链为clean → generate → pug → copy:gh-pages,随后用 gulp-connect 以gh-pages/为根目录启动服务(默认端口 8080)。然后导航到以下两个 URL:

http://localhost:8080/test/unit.html http://localhost:8080/test/integration.html
  • unit.html:单元测试页,逐个验证 src 下各模块(addTest、mq、prefixed、testStyles等)的行为,对应测试源码位于 test/browser/src;
  • integration.html:集成测试页,验证真实浏览器环境下各特性检测的产出,对应测试源码位于 test/browser/integration(包含bools.js、classes.js、global.js、prefixed.js等用例)。

如何阅读特性检测源码:以 canvas 为例

理解 Modernizr 的工作方式,最直观的入口是阅读 feature-detects 目录下的检测文件。以 feature-detects/canvas/canvas.js 为例,每个检测文件都遵循统一的"元数据注释 + AMD 定义"结构:

/*! { "name": "Canvas", "property": "canvas", "caniuse": "canvas", "tags": ["canvas", "graphics"], "polyfills": ["excanvas", "slcanvas"] } !*/ define(['Modernizr', 'createElement'], function(Modernizr, createElement) { // 在 S60 和 BB Storm 上 getContext 存在但总是返回 undefined, // 因此必须实际调用 getContext() 来验证 Modernizr.addTest('canvas', function() { var elem = createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }); });

要点:

  • 头部 JSON 注释声明了检测的name、property(挂到Modernizr上的属性名)、caniuse对应条目、tags分类与可选polyfills兜底方案;
  • 检测逻辑通过Modernizr.addTest('canvas', fn)注册,fn返回布尔值;
  • 该检测揭示了特性检测的一个经典陷阱:即使getContext存在,某些设备上仍可能返回undefined,所以必须实际调用一次getContext('2d')来真实验证,而不是只检查属性存在性。

这一"元数据 + addTest"的模式遍布整个 feature-detects 目录(从css/flexbox到webrtc/peerconnection),既可作为自定义检测的模板,也是理解 Modernizr 架构的最佳范例。

结语

Modernizr 的整个使用闭环可以概括为:从 lib/config-all.json 选择特性与选项 → 通过modernizr.build()编程接口或./bin/modernizr命令行生成最小化自定义构建 → 在页面中借助Modernizr对象属性与<html>类名做渐进增强 → 对异步检测使用Modernizr.on订阅完成事件。本仓库的 src、feature-detects、lib 与 test 目录共同构成了理解上述每一环节的完整源码证据链,值得按需深入阅读。

【免费下载链接】Modernizr

Modernizr is a JavaScript library that detects HTML5 and CSS3 features in the user’s browser.

项目地址:https://gitcode.com/gh_mirrors/mo/Modernizr
点击查看免费下载
上一篇:歌词滚动姬:终极免费LRC歌词制作工具完整指南 🎵
下一篇:终极免费方案:3分钟解决浏览器图片格式转换难题

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询