{"action":"created","issue":{"url":"https://api.github.com/repos/seajs/seajs/issues/971","labels_url":"https://api.github.com/repos/seajs/seajs/issues/971/labels{/name}","comments_url":"https://api.github.com/repos/seajs/seajs/issues/971/comments","events_url":"https://api.github.com/repos/seajs/seajs/issues/971/events","html_url":"https://github.com/seajs/seajs/issues/971","id":20227230,"number":971,"title":"如何改造现有文件为 CMD 模块","user":{"login":"afc163","id":507615,"avatar_url":"https://avatars.githubusercontent.com/u/507615?v=3","gravatar_id":"","url":"https://api.github.com/users/afc163","html_url":"https://github.com/afc163","followers_url":"https://api.github.com/users/afc163/followers","following_url":"https://api.github.com/users/afc163/following{/other_user}","gists_url":"https://api.github.com/users/afc163/gists{/gist_id}","starred_url":"https://api.github.com/users/afc163/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/afc163/subscriptions","organizations_url":"https://api.github.com/users/afc163/orgs","repos_url":"https://api.github.com/users/afc163/repos","events_url":"https://api.github.com/users/afc163/events{/privacy}","received_events_url":"https://api.github.com/users/afc163/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/seajs/seajs/labels/documentation","name":"documentation","color":"444444"}],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/seajs/seajs/milestones/13","labels_url":"https://api.github.com/repos/seajs/seajs/milestones/13/labels","id":413198,"number":13,"title":"2.2.0","description":"","creator":{"login":"lifesinger","id":97227,"avatar_url":"https://avatars.githubusercontent.com/u/97227?v=3","gravatar_id":"","url":"https://api.github.com/users/lifesinger","html_url":"https://github.com/lifesinger","followers_url":"https://api.github.com/users/lifesinger/followers","following_url":"https://api.github.com/users/lifesinger/following{/other_user}","gists_url":"https://api.github.com/users/lifesinger/gists{/gist_id}","starred_url":"https://api.github.com/users/lifesinger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lifesinger/subscriptions","organizations_url":"https://api.github.com/users/lifesinger/orgs","repos_url":"https://api.github.com/users/lifesinger/repos","events_url":"https://api.github.com/users/lifesinger/events{/privacy}","received_events_url":"https://api.github.com/users/lifesinger/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":14,"state":"closed","created_at":"2013-08-28T00:51:28Z","updated_at":"2014-08-25T10:39:35Z","due_on":"2013-09-30T07:00:00Z","closed_at":"2014-03-06T11:09:02Z"},"comments":62,"created_at":"2013-09-29T10:49:00Z","updated_at":"2015-01-21T12:22:49Z","closed_at":"2013-09-30T02:56:29Z","body":"# 如何改造现有文件为 CMD 模块\r\n\r\n经过一段考察，我们终于要在项目中引入模块机制和 Sea.js 了，那么如何将现有的文件改造成 CMD 模块就成了重要的问题。下面针对一些典型场景来说明包装的方式。\r\n\r\n首先还是请大家详细了解下 [CMD 模块定义规范](https://github.com/seajs/seajs/issues/242)，只要洞悉事物的定义和本质，一切问题可迎刃而解。\r\n\r\n## 改造主流模块\r\n\r\n这里指的是 jQuery、Moment、Backbone、underscore 等业界主流模块，这些模块一般都有对 AMD 和 CommonJS 的支持代码，例如 jQuery 源文件的最后几行：\r\n\r\n```js\r\nif ( typeof module === \"object\" && module && typeof module.exports === \"object\" ) {\r\n\tmodule.exports = jQuery;\r\n} else {\r\n\twindow.jQuery = window.$ = jQuery;\r\n\r\n\tif ( typeof define === \"function\" && define.amd ) {\r\n\t\tdefine( \"jquery\", [], function () { return jQuery; } );\r\n\t}\r\n}\r\n```\r\n\r\n还有 Backbone 里：\r\n\r\n```js\r\nvar Backbone;\r\nif (typeof exports !== 'undefined') {\r\n  Backbone = exports;\r\n} else {\r\n  Backbone = root.Backbone = {};\r\n}\r\n```\r\n\r\n对于有这些兼容代码的，只需要去掉 define.amd 的支持，或是直接包装上 `define` 就可以了。\r\n\r\n```js\r\ndefine(function(require, exports, module) {\r\n  // code here ...\r\n});\r\n```\r\n\r\n如果没有模块化的兼容代码，有时候需要手动引入依赖，以及暴露对应的接口。\r\n\r\n```js\r\ndefine(function(require, exports, module) {\r\n  var $ = require('$');\r\n  // code here ...\r\n  module.exports = Placeholders;\r\n});\r\n```\r\n\r\n可以参考 [cmdjs/gallery](https://github.com/cmdjs/gallery) 里的 [Gruntfile](https://github.com/cmdjs/gallery/blob/master/moment/Gruntfile.js) 对这些主流模块的代码替换方式。\r\n\r\n## 现有的 JS 文件\r\n\r\n对于一些现有的普通 JS 文件，相对简单的多，参考 CMD 的[书写规范](https://github.com/seajs/seajs/issues/242)，把那些暴露到全局命名空间的接口用 CMD 的方式进行改造就可以了。\r\n\r\n比如现有文件 `util.js` 。\r\n\r\n```js\r\nwindow.util = window.util || {};\r\nutil.addClass = function() {\r\n  window.css();\r\n};\r\nutil.queryString = function() {};\r\n```\r\n\r\n改为：\r\n\r\n```js\r\ndefine(function(require, exports, module) {\r\n  // 引入依赖\r\n  var css = require('css');\r\n  \r\n  util.addClass = function() {\r\n    css();\r\n  };\r\n  util.queryString = function() {};\r\n  \r\n  // 暴露对应接口\r\n  module.exports = util;\r\n});\r\n```\r\n\r\n这里不啰嗦，就是基本的 CMD 书写规范。实际的改造过程中，情况可以比上面的例子要复杂一些，具体情况具体解决就行。\r\n\r\n## 改造 jQuery 插件\r\n\r\n这也是一个经常遇到的问题，我们推荐以下的包装方式：\r\n\r\n```js\r\n// jquery-plugin-abc\r\ndefine(function(require, exports, module) {\r\n  var $ = require('$');\r\n  // 插件的代码\r\n  $.fn.abc = function() {};\r\n});\r\n```\r\n\r\n这样的改造方式实际上是强化了原有的 $ 对象（而不是重新包装出一个新的 $），在实际调用时，可以用下面的方式：\r\n\r\n```js\r\nseajs.use(['$', 'jquery-plugin-abc'], function($) {\r\n  // $ 有了 jquery-plugin-abc 所提供的插件功能\r\n  $.abc();\r\n});\r\n```\r\n\r\n更多 jQuery 插件的包装，可以参考 [cmdjs/jquery](https://github.com/cmdjs/jquery) 里的做法。\r\n\r\n## 工具\r\n\r\n除了手动的方式修改代码外，我们推荐使用 [Grunt](http://gruntjs.com) 来进行统一的改造，官方也通过 Grunt 改造了很多主流模块和 jQuery 插件，具体的操作手册见 [引入 CMD 模块指南](https://github.com/cmdjs/gallery/blob/master/README.md) 。你可以在 [cmdjs/gallery](https://github.com/cmdjs/gallery) 和 [cmdjs/jquery](https://github.com/cmdjs/jquery) 中找到具体的 Gruntfile ，从而借鉴到您的项目中去。所有打包好的模块可以在 [spmjs.org](https://spmjs.org/) 中找到。\r\n\r\n## 小结\r\n\r\n上面提供的是原有代码包装为 `CMD 书写规范` 的方法，在具体上线前，可能还需要打包为具名模块（包含 ID 的模块）。关于构建方面的进一步知识可以参考 [构建工具](https://github.com/seajs/seajs/issues/538) 。\r\n\r\n这里提到的包装方式都比较典型和简单，具体的实践可能千差万别。您在项目中有什么探索、实践和问题，欢迎来这里分享和提问。"},"comment":{"url":"https://api.github.com/repos/seajs/seajs/issues/comments/70827741","html_url":"https://github.com/seajs/seajs/issues/971#issuecomment-70827741","issue_url":"https://api.github.com/repos/seajs/seajs/issues/971","id":70827741,"user":{"login":"jieyou","id":1785607,"avatar_url":"https://avatars.githubusercontent.com/u/1785607?v=3","gravatar_id":"","url":"https://api.github.com/users/jieyou","html_url":"https://github.com/jieyou","followers_url":"https://api.github.com/users/jieyou/followers","following_url":"https://api.github.com/users/jieyou/following{/other_user}","gists_url":"https://api.github.com/users/jieyou/gists{/gist_id}","starred_url":"https://api.github.com/users/jieyou/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jieyou/subscriptions","organizations_url":"https://api.github.com/users/jieyou/orgs","repos_url":"https://api.github.com/users/jieyou/repos","events_url":"https://api.github.com/users/jieyou/events{/privacy}","received_events_url":"https://api.github.com/users/jieyou/received_events","type":"User","site_admin":false},"created_at":"2015-01-21T12:22:49Z","updated_at":"2015-01-21T12:22:49Z","body":"截止到目前，jQuery依然没有自己实现对CMD的兼容吗？  目前还是需要手动改造？"}}