blog icon indicating copy to clipboard operation
blog copied to clipboard

个人技术博客,博文写在 Issues 里。

Results 121 blog issues
Sort by recently updated
recently updated
newest added

作为公司里唯一的前端,代码组织方式一直是我在考虑的事情,而文章的标题就是我一步步实践过来的路程。 最开始的时候,我毫无例外的使用最普遍的 `` 方式加载代码,我做的网页看起来就像这样: ``` html ``` 就像大多数人做的那样,整个网站都用到的 style 与 script 放在最上面,某些页面之间公用的文件次之,最后是单个页面用到的文件。 后来我发现,这样做会有一些问题: - 文件的依赖关系**非常混乱**,为了用到一个 js,你可能需要预先加载另外一些 js ——另外一些 js 又依赖其它 js,用不了多久 `` 标签就失控了。 - 全局变量太多(jQuery、$、angular 等等) - 如果要开发网站用得到的公用文件(最初形态的“模块”),为了避免污染全局变量,所以要纳入到同一个全局变量(或者成为“命名空间”)里如 `window.MyApp.module1`,但时间长了就不知道这个命名空间里有些什么模块、这里面的模块相互之间是怎么依赖的了 -...

RequireJS
AngularJS
划词翻译
Vue.js

在接触 AngularJS 之前,我已经深入了解并使用了 RequireJS。我非常喜欢 AMD 的加载方式,因为它做到了模块化与按需加载,促进了代码之间的松耦合。 在接触到 AngularJS 之后,我就开始寻求一种方式——一种将 AngularJS 与 RequireJS 结合起来的方式,使 AngularJS 能借助 RequireJS 做到模块化和按需加载。经过一段时间的努力之后,我成功做到了这一点,并将成果发布到 [lmk123/angularjs-requirejs-rjs-md5](https://github.com/lmk123/angularjs-requirejs-rjs-md5) 。 顾名思义,在此基础上,我还做到了文件合并与 md5 签名,这样就可以将文件安全的放在 CDN 上。 但是还有一点没有做到——给文件路径加上 CDN 的前缀。 按照我那个项目的结构,只有 app/index.html 是不能缓存的,而其它文件:脚本、样式、模板都可以放在...

RequireJS
AngularJS

首先我得承认,我脑洞很大。- - 在 #8 中,我指出 AngularJS 有一个不好的地方:默认情况下,所有控制器、指令、服务都需要先加载才完毕能启动应用。 但这次我走了另一个极端:所有控制器、指令、服务、甚至样式都做到按需加载。(项目在[这里](https://github.com/lmk123/angularjs-all-lazyload)) 我承认我不顾后果的就开始做了,我也知道,这必然会让 HTTP 请求数(疯狂的)攀升。 所以我也没指望谁真的把那个项目用到生产环境里去= = 尽管如此,我仍然觉得这样做是有意义的,至少起了一个抛砖引玉的作用:在两个极端里,我们应该如何找到一个最佳的平衡点呢? 第一个极端是将所有文件都打包成 “all.js” 与 “all.css” ,但是任何一个小改动都会破坏用户的缓存,让用户重新下载这两个大文件。 第二个极端(即我的项目)是将所有文件都做成按需加载的。好处是对小文件的修改不会破坏其他文件的缓存,坏处是用户_每个路由的第一次访问_都要加载两三个甚至更多文件,延迟感比较明显。 为什么我还是觉得我的极端比较合理 = = 为了缓解 HTTP 请求数,我们可以将并不是公用的指令和服务直接写在控制器里,但即使如此,第一次访问一个路由时仍然需要加载三个文件:控制器,模板及样式。 实际上,这个模式就跟传统网站类似。当从一个页面点到另一个页面的时候,也是需要加载这三个文件的,此时模板一般会直接写在 html 里,而且 html...

RequireJS
AngularJS

自从决定将公司的网站改用AMD的方式开发之后,积攒了不少 [RequireJS](https://github.com/jrburke/requirejs) 的使用心得,于是在博客里简单的描述一下。 ## 为什么使用RequireJS 在为公司开发网站时,一开始的页面结构是很简单的: ``` html ``` 后来,公司要求在页面上加一个图表。自己做不来,只好找一个插件,于是页面变成了这样子: ``` html ``` 再后来,公司觉得浏览器的`alert()`与`confirm()`样式太丑了,所以我又写了一个公共组件;组件依赖jQuery,并且在每一个网页里都可能用到,于是页面结构成了这样子: ``` html ``` 那么问题来了。 1. js 文件之间的依赖关系太杂乱。一些插件依赖 jQuery,但一些插件又依赖另一个插件--所以最终,我需要小心翼翼的按照正确的顺序依次列出那些script标签,这肯定是不利于日后维护的。 2. 命名空间混乱。为了避免全局变量污染,一些插件会将自己的接口挂载在 jQuery 这个变量上,但这样仍然会污染 jQuery 的命名空间。日后我调试一段代码,发现一个不属于 jQuery 的方法--那这个方法到底是在哪个...

RequireJS

最近我在项目里用到了 [David](https://david-dm.org),它能分析你的项目的第三方依赖是否都是最新版,正好最近 [Babel](https://babeljs.io) 发布了 6.0 版,David 就帮我监测到了,真的非常方便。 我是一个很喜欢追求“最新版”的人,APP、代码、操作系统等都希望用上最新的,因为我认为,最新的总是最好的,会提供新功能、修复 bug 等。这次 Babel 从 5.0 升级到 6.0,最大的改动就是将以往集成的一堆插件全部分开成了一个个小的模块了,使用者需要自行制定要用到哪些插件。 那么问题来了:我已经全局安装了 babel v5.x,如果我升级了 babel ,那么其他依赖 babel 的项目我也要重新配置一遍;但我(和其他大多数人,应该也包括你)认为,别说是项目了,现在连代码都提倡“模块化”——每个代码文件都应该是独立的整体,可是我现在连项目之间都相互“依赖”了;想想看,若你参与两个项目的开发,一个需要全局安装 Babel 5.x,另一个是新项目,用的是 Babel 6.x,那你怎么办,开两个虚拟机吗? 这让我反思出一个道理——我们不应该使用 `npm install -g`。...

NPM
Node.js

先来说说我对“_组件_”的定义。 前端开发过程中,可能会用到一些第三方插件,比如 [jBox](https://github.com/StephanWagner/jBox) 或者 [asDatepicker](https://github.com/amazingSurge/jquery-asDatepicker):这些插件会附带一个 css 文件用来定义样式。于是我们在使用这些插件的时候,页面看上去是这样的: ``` html ``` 这里有一个小问题:既然需要加载 jBox.js 的时候总是需要加载 jBox.css 的,那为什么不将 jBox.css 写进 jBox.js 呢?这样可以减少一次 HTTP 请求。 但是总所周知,在 js 里的长文本是很难维护的,所以最好的解决方案是:开发时分成多个文件,但在生产环境时合并成一个文件;相关的文件最好放在一处,比如说放在同一个文件夹下——这就是我所认为的“_组件_”的定义。 [require.js](https://github.com/jrburke/requirejs) 配合 [text插件](https://github.com/requirejs/text)与 [r.js 文件组合工具](https://github.com/jrburke/r.js)就可以实现上面的需求了,只是 r.js...

RequireJS

这两天陆续学习了下 [gulp](https://github.com/gulpjs/gulp) 与 [f.i.s](https://github.com/fex-team/fis)。学习 gulp 纯粹是好奇它为什么会比 [grunt](https://github.com/gruntjs/grunt) 流行(我的结论在 #3),而学习 fis 则是为了解决一个_“前端工程”_问题。 我基于一些原因(见 #2),在公司项目里使用了 RequireJS,但我仍需要解决它的增量更新问题。单靠 RequireJS 提供的 `urlArgs` 是远远不够的,最好的办法应该是[这篇文章](https://github.com/fouber/blog/issues/6)里所说的那样,给每个静态文件的文件名加上 md5。 在我思考要不要脱离 fis、自己来实现的时候,我在网上搜到了一个 gulp 插件:[gulp-rev-all](https://github.com/smysnk/gulp-rev-all)。比起 fis 那种通过更新 RequireJS 中的 `paths` 设置,这个插件做的事情更符合我的意愿。它能把下面的代码: ```...

RequireJS

我在 #2 里曾提到过:[Require.js](https://github.com/jrburke/requirejs) 不是最终解决方案。 为什么这样说呢?想一下这样的场景: 我有很多模块,某一天我更新了其中的 `a.js`。为了让用户的浏览器不去读缓存,比较 low 的做法是在网页里引用这个脚本的时候,手动带上版本号或时间戳,例如: ``` html ``` 但是,模块是由 require.js 来加载的,不需要(也不能)由我们手动添加 script 标签。好在 require.js 提供了一个配置属性 [urlArgs](http://requirejs.org/docs/api.html#config-urlArgs),但问题在于:这个设置是全局的,所有被加载的模块都会带上这个 `urlArgs`。 这意味着它没有_增量更新_的能力:我修改了一个模块,然后更新了这个设置,那么其它所有未修改的模块文件也会被用户的浏览器重新下载一遍。 其实不仅是 require.js ,其它所有在页面上被引用的静态文件都有同样的问题。只是,一些后端语言已经考虑到了这个问题,例如公司项目使用的 [Spring 框架](http://spring.io/),会自动根据页面上引用的静态文件的内容生成一个 md5 字符串,写在文件名里(见 http://spring.io/blog/2014/07/24/spring-framework-4-1-handling-static-web-resources)。...

RequireJS

毕业之后,我去的第一家公司使用的前端构建工具是 [Ant](http://ant.apache.org/),使用时需要配置 `build.xml` 和 `ant.properties` 文件,构建流程一点也不直观,而且修改时还需要在两个文件之间来回看;后来来到现在这家公司,正好是 [Grunt](https://github.com/gruntjs/grunt) 正火的时候。它最吸引我的地方就在于它使用的是 node.js,对前端来说多么友好啊。 再后来,[gulp](https://github.com/gulpjs/gulp) 横空出世。简单的了解之后,我认为它与 grunt 是同样的工具,不值得再花时间。直到今天,我在网上看到 [gulp 4.0](https://github.com/gulpjs/gulp/tree/4.0) 就要发布的消息,于是在 github 上查看了下它的项目主页,发现标星数(11366)居然比 grunt(9050) 多。 我意识到,gulp 后来居上,一定是有更吸引人的地方,所以我稍微研究了下。 gulp 给我的第一印象就是:简单。它的文档居然只有一个页面,要不了多长时间就看完了。读完之后,我发现它是一个“流”构建工具,这正是它与 grunt 最大的区别(虽然我觉得这无非就是减少了构建时间,但这其实无关紧要)。 之后我就开始 Hello World 了。我一直都喜欢追求最新版本,所以使用了暂未发布的...

这一切都要从我正在开发的[非官方的『一个』移动客户端](https://github.com/lmk123/app-another-one)开始说起。 出于对[官方的『一个』移动客户端](https://itunes.apple.com/cn/app/yi-ge/id539190656?mt=8)的不满,我萌生了自己开发一个 APP 的想法。在使用 Bootstrap + ui-bootstrap 开发出[第一版](https://github.com/lmk123/app-another-one/releases/tag/v1.0.0)后,我有点不满意:程序看上去更像一个手机网站,而不是应用程序。 让网站看起来像原生应用程序,指的当然是各种动画效果:滑动、滚动到页面边缘时回弹等等。为此我找到了三种 UI 框架来完成这些事情: - [Ionic Framework](http://ionicframework.com/) - [Onsen UI](http://onsen.io/) - [Framework 7](http://www.idangero.us/framework7/) Framework 7 没有与 angularjs 集成,所以我暂时没有考虑使用它。社区里 Star 最多的是 Ionic Framework(并且将另外两个项目远远的甩在身后),所以我首先深入学习了它并用它重写了[第二版](https://github.com/lmk123/app-another-one/releases/tag/v2.0.0)。这一版并没有写完,因为在使用 Ionic...

PhoneGap
AngularJS