在浏览器中轻松实现CommonJS的require
- 只需1kb,无需构建
这个神奇的小项目提供了一个在浏览器环境下运行的、功能完备且几乎实用的CommonJS/Node.jsrequire
模块加载器,大小竟然不到1000字节。
功能亮点
- 同步的
require
模块加载 - 支持
exports
和module.exports
对象 - 能在Chrome、Opera 15+、Firefox 36+以及Safari(IE待测试)中正常进行调试
- 兼容npm,通过搜索
node_modules
目录查找模块(见限制) - 处理循环依赖
- 直接运行,无需构建你的JavaScript代码
- 尽管小巧,但API却相当丰富!
示例应用
使用方法
在你的模块中,你可以像在Node环境中一样使用require
函数、exports
对象和module.exports
对象。启动该要求系统有两种方式:
HTML中的data-main
属性
<script src="require1k.min.js" data-main="./index"></script>
在页面加载时,require1k
会寻找第一个带有data-main
属性的<script>
标签,然后根据HTML文件的位置异步加载并执行指定的模块。
全局R
函数
<script>
R(function (require, module, exports) {
var index = require("./index");
exports.hello = "World!";
}, function (err, exports) {
if (err) {
console.error(err.statusText);
return;
}
console.log(exports.hello)
});
</script>
R
函数接受一个函数或模块ID以及可选的回调函数。如果提供了函数,它将加载所有依赖并执行。如果有错误,回调函数会接收到失败的XMLHttpRequest对象作为第一个参数。此外,它还会获取到函数的exports
对象,这可能非常有用。
或者,你也可以提供一个模块ID和一个可选的回调函数来直接获取模块的导出对象。
限制条件
- 不读取
package.json
文件,因此忽略"main"
属性。包内的模块需要通过完整路径请求,例如:var _ = require("underscore/underscore");
- 交叉包依赖通过逐级上溯URL路径找到,导致:
- 加载交叉包依赖较慢,因为请求是顺序进行的
- 控制台会出现404错误信息
- 未找到的交叉包依赖会导致栈溢出并停止脚本执行
- 如果数据已经可用,回调函数会被同步调用,释放Zalgo
- 不支持加载
.json
文件
创新之处
简而言之,这是一个有趣的黑客实验。
更深入一点说呢?
使用<script>
标签管理你的“复杂”Web应用程序的依赖关系会使得维护变得一团糟。然而现在许多人仍在这样做,甚至许多当前发布的文章仍然建议这种方法。人们正在编写大型且复杂的应用,然后浪费时间手动管理依赖关系!这是完全没有必要的。
包管理确保你有一个系统来添加和更新项目中的库。这意味着你可以轻松检查你的库是否过期,并清楚地看到你的项目依赖于哪些库。而且,当你用一个(或多个)<script>
标签加载库时,所有库都是全局的。当你编写需要额外库的JavaScript时,你必须回到完全不同的文件中去添加依赖。这简直是胡闹。
你的应用的每个部分依赖什么应该是明确的。不应该需要编辑不相关的文件以依赖第三方模块。
如果你今天正在编写任何具有一定规模的Web应用,那么正确管理依赖是非常重要的。
这就是我推荐的方法:
- 使用npm管理客户端的依赖
- 使用Browserify或Webpack打包你的应用
仅此而已。
(是的,我也注意到将require1k嵌入页面上的讽刺性。但这只是一个玩笑,有点儿。)
致谢
这个项目主要受到了Mr的启发,这是一个CommonJS模块加载器和配套打包工具,当然,它不是1kb。
感谢Tom Robinson编写了最初的版本,感谢Kris Kowal教给我很多东西。
许可证
该项目采用BSD许可证。
对于那些追求轻量级、无构建过程以及想要在浏览器环境使用CommonJS的开发者来说,这个项目无疑是一个福音。即使在资源有限的情况下,require1k也能提供强大的模块化解决方案。所以,快来尝试一下,看看它能为你的项目带来怎样的改变吧!