blog
blog copied to clipboard
在 AngularJS 中按需加载控制器、指令、服务与样式
首先我得承认,我脑洞很大。- -
在 #8 中,我指出 AngularJS 有一个不好的地方:默认情况下,所有控制器、指令、服务都需要先加载才完毕能启动应用。
但这次我走了另一个极端:所有控制器、指令、服务、甚至样式都做到按需加载。(项目在这里)
我承认我不顾后果的就开始做了,我也知道,这必然会让 HTTP 请求数(疯狂的)攀升。
所以我也没指望谁真的把那个项目用到生产环境里去= =
尽管如此,我仍然觉得这样做是有意义的,至少起了一个抛砖引玉的作用:在两个极端里,我们应该如何找到一个最佳的平衡点呢?
第一个极端是将所有文件都打包成 “all.js” 与 “all.css” ,但是任何一个小改动都会破坏用户的缓存,让用户重新下载这两个大文件。
第二个极端(即我的项目)是将所有文件都做成按需加载的。好处是对小文件的修改不会破坏其他文件的缓存,坏处是用户_每个路由的第一次访问_都要加载两三个甚至更多文件,延迟感比较明显。
为什么我还是觉得我的极端比较合理 = =
为了缓解 HTTP 请求数,我们可以将并不是公用的指令和服务直接写在控制器里,但即使如此,第一次访问一个路由时仍然需要加载三个文件:控制器,模板及样式。
实际上,这个模式就跟传统网站类似。当从一个页面点到另一个页面的时候,也是需要加载这三个文件的,此时模板一般会直接写在 html 里,而且 html 的缓存时间不敢设太长;使用 AngularJS 做到完全的按需加载后,就可以放心的给模板设置长一点的缓存时间了,毕竟模板里面不会引用脚本与样式。
欢迎大家讨论一下到底怎么做比较好 = =
哈哈, 和我的想法很像, 可以看看我的项目 http://github.com/Treri/angular-require 我的想法是, 只把路由信息在页面加载的时候加载进来, 等到进入到具体的路由时, 再去加载相应的文件, 当然这包括每个路由特定的 controller service style resolve等等. 可以看我的项目源码
这个小项目, 我已经在公司的项目中使用了. 感觉还不错. 只是如果页面比较多的时候, 路由定义文件就会比较大.
我还用了一个小技巧, 最后压缩的时候, 我使用https://github.com/Treri/grunt-inline-css 这个小插件, 把每个controller对应的css文件, 注入到每个文件的前面, 这样又能减少一个http请求了.
同时使用https://github.com/Treri/grunt-amd-id 这个小插件, 把每个文件的module id写入到文件中, 这样的话,就能把那些所有页面都需要的东西, 通过一个文件加载进来.
现在的项目, 所有的vendor文件通过一个文件加载进来. 自己项目的文件, 就通过上面几个小插件的结合, 共用的文件, 压缩合并到一起. 各个controller对应的, 就在路由中, 使用angular-require插件加载进来.
@Treri
只是如果页面比较多的时候, 路由定义文件就会比较大.
这比一口气把所有文件加载进来好 :) 还有,我发现这个项目甚至可以按需加载 ui-router 的状态(state) = =
把每个controller对应的css文件, 注入到每个文件的前面 把那些所有页面都需要的东西, 通过一个文件加载进来.
我也写过一个类似的小工具。我在想其实对 css 的依赖可以写在 controller.js 里而不是路由里,然后使用类似的工具将它并到 controller.js 文件里就可以了.
所有的vendor文件通过一个文件加载进来.
这个想法很好!
全部按需加载肯定是有问题的,而且大部分情况下可能还不如所有文件打包。
一般来说使用了MVVM框架以后,业务脚本的代码量都会大大减少。Angular我不熟悉,看了你们的讨论貌似好像按需加载还是按照路由来的?如果我有10个页面,每个对应的业务脚本压缩后只有1~2KB,那这种按需加载意义也不大。
我个人非常赞同这篇文章的做法,PC端大型单页式商业内容管理系统的JS模块化构建探索,有两段我觉得非常好:
从经验值来看,单个资源的大小尽量控制在未Gzip前500KB以内,过大的文件会成为瓶颈,除非你可以很好地规划一个HTTP请求段,使得一个大文件加载的用时内浏览器会利用另一个TCP链接加载多个小文件。
并不是所有的文件都需要合并在一起,也不是所有资源都可以按需加载,对于请求数量的控制并不仅仅体现在系统启动时,也贯穿整个系统的使用流程,来提供用户一致的性能体验。
@simongfxu
如果我有10个页面,每个对应的业务脚本压缩后只有1~2KB,那这种按需加载意义也不大。
在这种场景下,当然就不需要按需加载了,但是就如你推荐的那篇文章所说的:
相当多的站点会将所有的JavaScript合并为一个文件,这也是最简单粗暴有效的方案。但是对于大型的单页系统而言,所有JavaScript合并后生成的文件会非常之巨大,其体积在浏览器单线程的下载模式下已经成为系统的性能瓶颈。
你推荐的这篇文章真的很好,它其实就是在_全部合并_或_全部按需加载_之间寻找一个平衡点!