{"action":"opened","issue":{"url":"https://api.github.com/repos/paper/blog/issues/14","repository_url":"https://api.github.com/repos/paper/blog","labels_url":"https://api.github.com/repos/paper/blog/issues/14/labels{/name}","comments_url":"https://api.github.com/repos/paper/blog/issues/14/comments","events_url":"https://api.github.com/repos/paper/blog/issues/14/events","html_url":"https://github.com/paper/blog/issues/14","id":134796210,"number":14,"title":"requirejs 和 r.js 构建实践与练习","user":{"login":"paper","id":293908,"avatar_url":"https://avatars.githubusercontent.com/u/293908?v=3","gravatar_id":"","url":"https://api.github.com/users/paper","html_url":"https://github.com/paper","followers_url":"https://api.github.com/users/paper/followers","following_url":"https://api.github.com/users/paper/following{/other_user}","gists_url":"https://api.github.com/users/paper/gists{/gist_id}","starred_url":"https://api.github.com/users/paper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paper/subscriptions","organizations_url":"https://api.github.com/users/paper/orgs","repos_url":"https://api.github.com/users/paper/repos","events_url":"https://api.github.com/users/paper/events{/privacy}","received_events_url":"https://api.github.com/users/paper/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/paper/blog/labels/article","name":"article","color":"207de5"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2016-02-19T07:29:42Z","updated_at":"2016-02-19T07:29:42Z","closed_at":null,"body":"## 短视频构建（requirejs + r.js）\r\n\r\n2016年年底时，Android 和 iOS 短视频使用的是r.js 进行打包合并的。故在这里做一下简要说明。\r\n\r\n短视频Android和iOS的地址分别是：  \r\n`\\web_common_h5\\src\\page\\video` 和 `\\web_ios_h5\\src\\page\\video`\r\n\r\n页面需要引入的必须代码：\r\n1. `//m.sjzhushou.com/h5/thirdlib/zepto/1.1.6/zepto.all.min.js`\r\n2. `//m.sjzhushou.com/h5/thirdlib/vue/1.0.10/vue.min.js`（因为短视频使用了vue）\r\n3. `//m.sjzhushou.com/h5/thirdlib/requirejs/2.1.20/require.min.js`\r\n\r\n再引入：`index.js`\r\n\r\n这里主要说明一下`index.js`\r\n\r\n`index.js` 不仅是 requirejs 配置和执行的脚本，又是r.js的配置文件。这样做的好处就是，只需要维护一份代码，就可以同时使用开发模式和线上模式\r\n```\r\n// 这是 iOS短视频 的index.js\r\n(function(){\r\n\r\n    // 调试开关\r\n    var debug = false;\r\n    \r\n    // 版本时间戳，如果是调试模式，那么就是无缓存模式\r\n    // 每次上线时，压缩合并后的代码都具有自定义时间戳（而不使用md5）。这样方便回归代码，出问题方便回退。\r\n    var t = debug ? (+new Date) + '' : '20160203_1727';\r\n    var urlArgs = 't=' + t;\r\n    \r\n    var shortVideo_requirejs_config = {\r\n        baseUrl: '../../',\r\n        paths: {\r\n            'text': 'lib/textjs/text.min',\r\n    \t\t\r\n            // 引用线上的代码，是无法合并打包的\r\n            'md5':'http://m.sjzhushou.com/h5/lib/md5',\r\n            'client':'http://m.sjzhushou.com/h5/lib/client',\r\n            'ready':'http://m.sjzhushou.com/h5/lib/ready',\r\n            'util':'http://m.sjzhushou.com/h5/lib/util',\r\n            'video_source' : 'http://m.sjzhushou.com/h5/page/common/video_source',\r\n    \r\n            'video': 'component/video/video',\r\n            'share': 'component/share/share',\r\n            'recommend': 'component/recommend/recommend',\r\n            'comment': 'component/comment/comment',\r\n            \r\n            'main': 'page/video/main',\r\n            'main-build': 'page/video/dist/main-build-min-' + t\r\n        }\r\n    };\r\n    \r\n    // 这个是页面使用的代码，不是为了r.js构建的。\r\n    // 故延迟1ms，是为了防止使用r.js 构建时报错\r\n    setTimeout(function(){\r\n        try{\r\n            require.config({\r\n                baseUrl : shortVideo_requirejs_config.baseUrl,\r\n                paths   : shortVideo_requirejs_config.paths,\r\n                urlArgs : urlArgs\r\n            });\r\n\r\n            if (debug) {\r\n                // 测试环境\r\n                require(['main']);\r\n            } else {\r\n                // 正式环境，打包后的\r\n                require(['main-build']);\r\n            }\r\n        }catch (e) {}\r\n    }, 1);\r\n    \r\n    // for rjs build\r\n    // 这样只要写一份shortVideo_requirejs_config配置文件，就可以完成开发和上线时同步，不必担心遗漏\r\n    return {\r\n        baseUrl : shortVideo_requirejs_config.baseUrl,\r\n        paths   : shortVideo_requirejs_config.paths,\r\n        \r\n        name    : shortVideo_requirejs_config.paths.main,\r\n        out     : 'dist/main-build-min-'+ t +'.js'\r\n        \r\n        // 如何不压缩，就取消这个注释（一般都合并压缩）\r\n        //optimize: \"none\",\r\n    };\r\n    \r\n})();\r\n```\r\n\r\n配置 `gulpfile.js` \r\n```\r\n// 这是 iOS短视频 的gulp任务\r\nvar gulp = require('gulp');\r\nvar exec = require('child_process').exec;\r\nvar rjsPath = 'node_modules/requirejs/bin/r.js';\r\n\r\n// 短视频rjs构建\r\ngulp.task('shortVideoBuild', function(cb) {\r\n    var buildPath = 'src/page/video/index.js'\r\n    \r\n    exec('node ' + rjsPath + ' -o ' + buildPath, function(err){\r\n        if (err) return cb(err); // 返回 error\r\n        cb(); // 完成 task\r\n    });\r\n});\r\n```\r\n\r\n上线之前，运行一次 `gulp shortVideoBuild`，然后上传对应的代码即可。  \r\n建议：除了上传压缩版本的main-build，还要上传其他被合并的单独的文件哦。（这里吐槽一下rz -y 的上传方式）\r\n\r\n**【注意点】 **  \r\n**1，`index.js`: `t = 上线时的时间点`**  \r\n**2，`index.js`: `debug = false`**  \r\n**3，页面引入的 `index.js` 也要加时间戳哦，为了清缓存**\r\n"}}