你尚未登录,仅允许查看本站部分内容。请登录使用邀请码注册
糖饼

再谈 SeaJS 与 RequireJS 的差异 14个回复 专栏 @ Javascript

糖饼 发布于 3 年前

“历史不是过去,历史正在上演。随着 W3C 等规范、以及浏览器的飞速发展,前端的模块化开发会逐步成为基础设施。一切终究都会成为历史,未来会更好。”——引用玉伯原文最后一段话,我个人也非常赞同。既然谈到了“未来”,我个人认为:前端 js 模块如果继续发展,其模块格式很可能会成为未来 WEB 一种标准规范,产生多种实现方式。就好比 JSON 格式一样,最终成为标准、被浏览器原生实现。

谁更有能成为未来的异步模块标准?SeaJS 遵循 CMD 规范,RequireJS 遵循 AMD 规范,先从这两种不同的格式说起。

CMD

CMD 模块依赖声明方式:

define(function (require) {
    var a = require('./a');
    var b = require('./b');
    // more code ..
})

CMD 依赖是就近声明,通过内部require方法进行声明。但是因为是异步模块,加载器需要提前加载这些模块,所以模块真正使用前需要提取模块里面所有的依赖。无论是加载器即时提取,还是通过自动化工具预先提取,CMD 的这种依赖声明格式只能通过静态分析方式实现,这也正是 CMD 的弊端所在。

CMD 规范的弊端

  1. 不能直接压缩:require是局部变量,意味着不能直接的通过压缩工具进行压缩,若require这个变量被替换,加载器与自动化工具将无法获取模块的依赖。
  2. 模块书写有额外约定:路径参数不能进行字符串运算,不能使用变量代替,否则加载器与自动化工具无法正确提取路径。

规范之外的约定意味着更多的文档说明,除非它们也是规范中的一部分。

注:SeaJS 静态分析实现是把模块包toString()后使用正则提取require部分得到依赖的模块路径。

AMD

AMD 模块依赖声明方式:

define(['./a', './b'], function (a, b) {
    // more code ..
})

AMD 的依赖是提前声明。这种优势的好处就是依赖无需通过静态分析,无论是加载器还是自动化工具都可以很直接的获取到依赖,规范的定义可以更简单,意味着可能产生更强大的实现,这对加载器与自动化分析工具都是有利的。

AMD 规范的弊端

  1. 依赖提前声明在代码书写上不是那么友好
  2. 模块内部与 NodeJS 的 Modules 有一定的差异

关于第二点的问题需要特别说明下。其实无论是 CMD 还是 AMD 的异步模块,都无法与同步模块规范保持一致(NodeJS 的 Modules),只有谁比谁更像同步模块而已。AMD 要转换为同步模块,除了去掉define函数的包裹外,需要在头部使用require把依赖声明好,而 CMD 只需要去掉define函数的包裹即可。

总结

规范 生态 书写 易于实现 NodeJS模块相似性
AMD ☆☆☆☆☆ ☆☆☆ ☆☆☆☆☆ ☆☆☆
CMD ☆☆ ☆☆☆☆☆ ☆☆☆ ☆☆☆☆☆

从规范上来说,AMD 更加简单且严谨,适用性更广,而在 RequireJS 强力的推动下,在国外几乎成了事实上的异步模块标准,各大类库也相继支持 AMD 规范。

但从 SeaJS 与 CMD 来说,也做了很多不错东西:1、相对自然的依赖声明风格 2、小而美的内部实现 3、贴心的外围功能设计 4、更好的中文社区支持

如果有可能,我希望看到 SeaJS 也支持 AMD,与前端社区大环境保持一致最终幸福的是广大开发者。

  • 一丝

    顶!

    #1
  • 前端农民工

    @糖饼

    接着你的文章又写了一篇, http://div.io/topic/439

    #2
  • kazaff

    我记得SeaJS在错误处理上采用的是抑制风格,这是我非常不能接受的~而且博主提到的“生态”我觉得很重要,requireJS的生态圈很好,我很喜欢!

    #3
  • knightwu

    requirejs 也已经支持CMD的方式了

    #4
  • 黄芙蓉

    学习了,赞楼主share!!

    #5
  • 黄芙蓉

    加深了我对requirejs和seajs的认识~~

    #6
  • dotnil

    CMD 写法,压缩前补上 define 的其他参数,就可以随便压缩了,SeaJS 推荐这样的做法。

    define('foo', ['bar'], function(require, exports, module) {
      // 这样就不会用正则去分析依赖哪些模块了
      // 也就不需要保证 require 函数名不变
    })
    
    #7
  • showzyl

    seajs要是依赖和require一样就真的完美了。

    #8
  • dotnil

    我倒不觉得,其实 SeaJS 这种处理方式,很适合用来包装 CommonJS 的模块,我在最近一个项目里采用与 Node.js 一样的模块写法,在前端动态封装 SeaJS 所需的外部包装 define(id, deps, function(require, exports, module) {}),实际效果非常不错,能够做到前后端真正无缝的代码共享。

    #9
  • petitspois

    都在添坑啊!只是添的东西不一样。

    #10
  • fansekey

    @petitspois 掌握了生命的精髓

    #11
  • 小天同学

    top to top

    #12
  • hahadekuai

    这要是成为浏览器的标准,想不到会有多糟糕的未来

    #13
  • 糖饼

    文章已经过时了,标准果然是日新月异( •̣̣̣̣̣̥́௰•̣̣̣̣̣̥̀ )

    #14
登录后回复,如无账号,请使用邀请码注册