JavaScript的模块加载可能有害


发布者 ourjs  发布时间 1392643239000
关键字 心得体会 
OurJS注:就像原文评论所指出,作者批评的是在前端领域过度使用异步模块加载方式。通常的Web应用会对JavaScript文件进行合并,压缩(Minify)以减小连接数,和文件体积,以更好的利用缓存,提升用户体验。原先的JS源文件最终会变化一个或两个上线。这跟后端(NodeJS)分散的代码组织方式会有所不同。

简介

我最近倾向一个观点:JavaScript的模块加载是非常不好的,我认为从总体上来说,这不是一个好主意。其实也有适合他们应用的场合,最后我会提到。

现在,估计我是这里的少数派。除了CommonJS和AMD模块加载方式, (参见:JavaScript模块化编程:AMD规范及require.js用法),其他加载系统像RequireJS或者(说实话我非常吃惊)Google Module Server,Node浓重的文化正在影响着Javascript世界,你很难去说JavaScript模块加载的不好。纯脚本太老了,太傻了,太不方便了。每个人都知道,所以他们不会指责自己喜欢的东西,对吗?

我准备走出这个群体,并说:“JavaScript模块加载可能有害”,下面希望我能说服你认同我。

危害#1:混乱的调试

模块加载机制在一些明显和微妙的地方调试困难。

压缩,转换还有其他的预处理都支持模块加载(有些其实并不是必须,仅是为了保持一致),从原文件加载模块通常都是由浏览器来完成的。所以当你调试代码时经浏览器加载的代码经常会与实际代码不匹配。Source Maps可以解决这个问题,但在高度其它浏览器时还是会有问题。(注*Source Maps为一种新的调度方法)

通常,在源代码没有改变或者source maps正常工作时,模块加载所产生的动态标签会产生一些问题。调试器可能无法区别在页面加载时装载的脚本,例如,如果不写成内联的script标签,你设置的断点可能消失。

其实很难评价模块加载所带来的便利和他们所引起的问题,总的来说他们应该帮助你组织结构和保持简单,而不是增加工作量。

危害#2:模块加载顺序

也许模块加载的最常见和折磨人的瓿就是脚本的加载顺序。跟在你的页面按顺序加载SCRIPT标签相比,理解模块何时被执行是非常折腾的人的。

通常最先加载的模块会被执行,但内部模块依赖决定了他需要等依辣的模块加载完了才执行。

这有一个明显的优点,可以帮助我们定义并理解依辣关系,这些引用可以通过require()调用清晰地表达出来,是非常令人钦佩的。

然后,实际情况里,我们的项目通常没有如此复杂的内部模块依赖。

危害#3:工作并发症

显而易见,使用模块加载系统代替简单的脚本工作起来非常困难。

因为整合这个众所周知的困难,很多第三方库并不使用相似的模块加载系统。多个系统会让他的工作更加复杂。这些库的作者不得不添加将模块添加额外的封装,以便不同的模块加载系统去调用,不管用户是不是采用。

当你带一位新的程序员到一个项目中,或者一个程序员找到一个有用库,但这个库使用模块加载(如RequireJS)组织,这就给他带来了一些障碍,其实他只想添加一个简单的script。这值得吗?我担心这样会导致我们的系统碎片化。

结论

最后还是要看这种加载方式所带来的便利性和成本的对比,如果加载方式带来的便利性大于支出,说它有害是没有道理的。比如你有一个非常庞大的代码库,如果一开始就加载所有内容会影响性能,用户体验时,你可以采用。