过程描述

  • 使用 RPC 通信从后台服务器获取数据
  • 模板渲染

    include 子模版
    xss 过滤、模板 helper 函数


将 ES6 模板字符串改造成模板引擎

  • 基础使用

    const vm = require('vm');const user = {name: 'haha'
    }console.log(vm.runInNewContext(`<h2>${user.name}</h2>`, { user })); // <h2>haha</h2>
    
  • XSS 过滤
    console.log(vm.runInNewContext(`<h2>${_(user.name)}</h2>`, {   // 模板字符串里可以直接写函数调用user,_: function(markup) {    // XSS 过滤规则if (!markup) return '';return String(markup).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, ''').replace(/"/g, '&quot;')}
    }));
    
  • 子模版
    const vm = require('vm');const templateMap = {templateA: '`<h2>${include("templateB")}</h2>`',templateB: '`<p>hahahaha</p>`'
    }const context = {include(name) {return templateMap[name]()},_: function(markup) {if (!markup) return '';return String(markup).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, ''').replace(/"/g, '&quot;')}
    }Object.keys(templateMap).forEach(key=> {// 将templateMap中的value值为渲染之后的const temp = templateMap[key];templateMap[key] = vm.runInNewContext(`(function() {return ${temp}})`, context);
    })console.log(templateMap['templateA']());  // <h2><p>hahahaha</p></h2>
    
  • 封装
    const fs = require('fs');
    const vm = require('vm');// 缓存
    const templateCache = {};// 创建模板渲染context
    const templateContext = vm.createContext({include: function (name, data) {const template = templateCache[name] || createTemplate(name)return template(data);}
    });/*** @param {*} templatePath 模板路径* @returns 渲染好的html字符串*/
    function createTemplate(templatePath) {templateCache[templatePath] = vm.runInContext(// data 是在这个页面中可以使用的数据`(function (data) {with (data) {return \`${fs.readFileSync(templatePath, 'utf-8')}\`}})`,templateContext);return templateCache[templatePath]
    }module.exports = createTemplate
    

代码结构

detail-server

  • 目录结构
  • lib/geeknode-rpc-server.js
    const RPC = require('./rpc-server');/*** 因为所有服务用的包头格式都一样,不一样的只有protobuf协议,所以这里可以将这段逻辑封成一个模块* * 日常做项目的时候一定要注意把重复代码做封装*/
    module.exports = function (protobufRequestSchema, protobufResponseSchema) {return new RPC({// 解码请求包decodeRequest(buffer) {const seq = buffer.readUInt32BE();return {seq: seq,result: protobufRequestSchema.decode(buffer.slice(8))}},// 判断请求包是不是接收完成isCompleteRequest(buffer) {const bodyLength = buffer.readUInt32BE(4);return 8 + bodyLength},// 编码返回包encodeResponse(data, seq) {const body = protobufResponseSchema.encode(data);const head = Buffer.alloc(8);head.writeUInt32BE(seq);head.writeUInt32BE(body.length, 4);return Buffer.concat([head, body]);}})
    }
    
  • lib/rpc-server.js
    const net = require("net");module.exports = class RPC {constructor({ encodeResponse, decodeRequest, isCompleteRequest }) {this.encodeResponse = encodeResponse;this.decodeRequest = decodeRequest;this.isCompleteRequest = isCompleteRequest;}createServer(callback) {let buffer = null;const tcpServer = net.createServer((socket) => {socket.on('data', (data) => {buffer = (buffer && buffer.length > 0) ?Buffer.concat([buffer, data]) : // 有遗留数据才做拼接操作data;let checkLength = null;while (buffer && (checkLength = this.isCompleteRequest(buffer))) {let requestBuffer = null;if (checkLength == buffer.length) {requestBuffer = buffer;buffer = null;} else {requestBuffer = buffer.slice(0, checkLength);buffer = buffer.slice(checkLength);}const request = this.decodeRequest(requestBuffer);callback({   // requestbody: request.result,socket},{   // responseend: (data) => {const buffer = this.encodeResponse(data, request.seq)socket.write(buffer);}});}})});return {listen() {tcpServer.listen.apply(tcpServer, arguments)}}}
    }
    
  • mockdata/column.js
    module.exports = [{id: 232,type: 2,column_cover: "https://static001.geekbang.org/resource/image/42/78/42db8ef7b28bcdc26410141dd97b8178.jpg",column_title: "Node.js开发实战",column_subtitle: "带你开发一个完整的Node.js项目",author_name: "杨浩",author_intro: "腾讯高级工程师",column_intro: `<h2>课程背景</h2><p>Node.js 拥有广大的 JavaScript 程序员基础并且完全开源,所以它拥有一个强大的开发者社区。依靠繁荣的社区力量,现在已经发展出成熟的技术体系与庞大的生态。它被广泛地用在 Web 服务、开发工作流、客户端应用等诸多领域。其中,在 Web 服务开发这个领域,业界对 Node.js 的接受程度最高。</p><p>对于很多前端开发者来说,掌握 Node.js 的基础知识并不难,难点在于如何按照后端工程师的思维,基于 Node.js 来一步步构建项目,其中涉及诸如 RPC 调用、系统运维以及进程管理等前端工程师较少涉及到的领域。</p><p>因此,本课程站在一个前端工程师的角度,讲解如何基于 Node.js 开发一个完整的项目,从一开始的技术预研再到实际开发、性能优化以及最终的框架架构搭建和工程化建设,带你完整体验一遍前端工程师使用 Node.js进行项目开发会碰到的各种常见场景和技术难点,学完课程之后,你将能够熟练运用 Node.js 进行大型项目的设计和开发。</p><h2>讲师简介</h2><p>杨浩,腾讯高级工程师。之前曾在腾讯视频负责 Web 端的相关工作,设计并完成了腾讯视频整站大部分页面的 Node.js 化。</p><p>腾讯视频是从 2015 年开始使用 Node.js 对整站进行改造的,杨浩与同事一起从零开始一步一步把整个 Node.js 的开发运维步骤打通,搭建了一个运行于后台服务和浏览器前端之间的 Node.js 中间层用作 SSR(Server Side Rendering),以提高搜索引擎抓取的效果以及首屏展现的速度。</p><p>在 2018 年由 InfoQ 举办的 ArchSummit 全球架构师峰会深圳站上,杨浩也对在腾讯视频进行 Node.js 改造这一经历做了公开分享:</p><p><a href="https://time.geekbang.org/dailylesson/detail/100016617">https://time.geekbang.org/dailylesson/detail/100016617</a></p><h2>课程收获</h2><ol><li>Node.js 开发必备基础知识;</li><li>使用 Node.js 构建 BFF 层;</li><li>一个完整项目的开发重构实战;</li><li>性能优化和工程化建设核心方法。</li></ol><p><img src="https://static001.geekbang.org/resource/image/99/9b/995176c4b4cb6c197414430998ad8c9b.jpg" alt="" /></p><h2>更新频率</h2><ol><li>9月18日上线 1-8 讲,9月25日开始固定为每周三更新。</li><li>全部课程预计将于 12 月 11 日前更新完毕。</li></ol><h2>如何在电脑端观看视频</h2><ol><li>用浏览器访问  <a href="https://time.geekbang.org">https://time.geekbang.org</a> ,登录极客时间账号;</li><li>然后在“讲堂”板块选择“视频课程”标签,点击相应的视频课程即可观看。</li></ol><h2 class="js-audit">订阅须知</h2><ol class="js-audit"><li> 本课程为视频课程,共55讲,订阅成功后即可通过“极客时间”App端、小程序端、<a href="https://time.geekbang.org/paid-content">Web端</a>永久观看;</li><li>由于视频内容为虚拟商品,一经订阅,概不退款;</li><li>企业批量购买请点击“<a href="https://time.geekbang.org/column/article/102047?utm_source=geektimeAPP&utm_medium=DingYueXuZhi&utm_campaign=qiyezhanghao">企业充值</a>”了解详情,可支持员工选课,企业支付;</li><li>在课程学习过程中,如有任何问题,请邮件联系 service@geekbang.org。</li><li>戳此<a href="https://promo.geekbang.org/activity/student-certificate?utm_source=app&utm_medium=xiangqingye">申请学生认证</a>,订阅课程一律 5 折。</li></ol>`,column_unit: "55讲",sub_count: 2915,update_frequency: "约550分钟",column_price: 12900,column_price_market: 12900,articles: [{id: 0,is_video_preview: true,article_title: '第一课'}, {id: 1,is_video_preview: false,article_title: '第二课'}, {id: 2,is_video_preview: false,article_title: '第三课'}, {id: 3,is_video_preview: false,article_title: '第四课'}]
    }, {id: 278,type: 2,column_cover: "https://static001.geekbang.org/resource/image/a0/19/a0ad97e899aa22023951bde5813e0819.jpg",column_title: "移动端自动化测试实战",column_subtitle: "一步一步带你成为测试高手",author_name: "思寒",author_intro: "TesterHome 社区测试专家、霍格沃兹测试学院创始人",column_intro: `<h2>课程背景</h2>↵<p>随着行业的竞争加剧,互联网产品迭代的速度越来越快,QA 与测试工程师都需要在越来越短的测试周期内充分保证质量。 App 测试则面临着更多的挑战,比如多端发布、多版本发布、多机型发布等等,这导致了手工测试很难完全胜任,自动化测试、持续测试就成为了团队的必要需求。作为传统的测试工程师与研发工程师,需要适应行业的变化,并积极做出应对。</p>↵<p>学习自动化测试有两个难点,除了其本身拥有一定的技术门槛之外,实战经验才是学习自动化测试的最大难点。部分初中级测试工程师往往在掌握了基本的编程与自动化测试框架 API 后,会认为自己已经掌握了自动化测试,便开始投入到实际开发中,却又掉进各种各样的技术债和经验债里,痛苦不堪。</p>↵<p>因此,整个课程将分为基础篇、框架篇和实战篇三个阶段,十个章节,由浅入深地带大家掌握 app 自动化测试技能。通过学习这门课程,你将能够掌握正确的自动化测试方法、理解自动化测试的技术体系,可以解决工作中遇到的自动化测试难题,并能把这项技术熟练应用在自己公司的测试体系中。</p>↵<h2>讲师简介</h2>↵<p>思寒,TesterHome 社区测试专家,霍格沃兹测试学院创始人。</p>↵<p>先后任职于阿里巴巴、百度、雪球等公司,承担测试工程师、测试开发工程师、测试架构师等工作。</p>↵<p>2013年,移动互联网开始迅猛发展,催生了对 app 测试的需求,思寒老师与其团队决定物色一个优秀的移动测试框架,在进行大量调研之后,Appium 以其优秀的特性脱颖而出。思寒老师也开始投身于这个开源框架的建设中,积极参与 Appium 框架的中文翻译、向 Appium 提交测试用例与 pull request,同时也开始在历任的公司中将 Appium 用于公司内的移动测试,积累了非常多的落地经验。</p>↵<h2>课程收获</h2>↵<ol>↵<li>系统掌握 Appium 自动化测试框架;</li>↵<li>全面提升移动端自动化测试实战能力;</li>↵<li>掌握自动遍历测试及兼容性测试技巧;</li>↵<li>构建多设备管理平台与持续集成体系。</li>↵</ol>↵<p><img src="https://static001.geekbang.org/resource/image/0a/df/0a9344cb82dce288097621a6a368cfdf.jpg" alt="" /></p>↵<h2>更新频率</h2>↵<ol>↵<li>10月23日上线 1-9 讲,10月30日开始固定为每周三更新。</li>↵<li>全部课程预计将于 2020 年 1 月 22 日前更新完毕。</li>↵</ol>↵<h2>如何在电脑端观看视频</h2>↵<ol>↵<li>用浏览器访问  <a href="https://time.geekbang.org">https://time.geekbang.org</a> ,登录极客时间账号;</li>↵<li>然后在“讲堂”板块选择“视频课程”标签,点击相应的视频课程即可观看。</li>↵</ol>↵<h2 class="js-audit">订阅须知</h2>↵<ol class="js-audit">↵<li> 本课程为视频课程,共58讲,订阅成功后即可通过“极客时间”App端、小程序端、<a href="https://time.geekbang.org/paid-content">Web端</a>永久观看;</li>↵<li>由于视频内容为虚拟商品,一经订阅,概不退款;</li>↵<li>企业批量购买请点击“<a href="https://time.geekbang.org/column/article/102047?utm_source=geektimeAPP&utm_medium=DingYueXuZhi&utm_campaign=qiyezhanghao">企业充值</a>”了解详情,可支持员工选课,企业支付;</li>↵<li>在课程学习过程中,如有任何问题,请邮件联系 service@geekbang.org。</li>↵<li>戳此<a href="https://promo.geekbang.org/activity/student-certificate?utm_source=app&utm_medium=xiangqingye">申请学生认证</a>,订阅课程一律 5 折。</li>↵</ol>`,column_unit: "55讲",sub_count: 1471,update_frequency: "约550分钟",column_price: 9900,column_price_market: 9900,articles: [{id: 0,is_video_preview: true,article_title: '第一课'}, {id: 1,is_video_preview: false,article_title: '第二课'}, {id: 2,is_video_preview: false,article_title: '第三课'}, {id: 3,is_video_preview: false,article_title: '第四课'}]
    }, {id: 211,type: 1,column_cover: "https://static001.geekbang.org/resource/image/b6/1a/b683240befccbdcaa86da8f382d3a11a.jpg",column_subtitle: "Facebook研发效率工作法",column_title: "研发效率破局之道",author_intro: "前Facebook内部工具团队Tech Lead",author_name: "葛俊",column_intro: `<p>如果你问中国和美国互联网公司都有什么差别,很多人会回答:<strong>低效加班文化</strong>。最近爆出的996大讨论,正反映出国内很多公司拼工时的做法,以及程序员群体对这种做法的反感情绪。</p>↵<p>“拼工时”说到底是为提高产出,但国内互联网产业已经步入从野蛮生长到精耕细作的过渡期,人力成本逐渐提高,通过糙快猛打拼和996加班去抢占市场获得机会的成功案例越来越少。至此,只有提高效能才是出路。</p>↵<p>事实上,越来越多的公司意识到研发效能的重要性,很多百人研发规模的公司开始组建专门的效能团队,着手提高公司的整体效能。</p>↵<p>然而,因为软件开发的灵活性,导致研发效能的提高需要关注的点太多、可以使用的方法也很多,结果就是不知道从何处着手,或者是花了精力、加大了投入却看不到效果,甚至产出抵不上投入。</p>↵<ul>↵<li>整个研发过程环节很多,到底该从哪里下手?</li>↵<li>通过设置的度量标准来看,某个指标明显提高了,但却看不到总体效果,而且引发了团队抱怨以及团队间的矛盾。这到底是怎么回事?</li>↵<li>团队成员虽然执行力强,但是不愿意思考,应该创建怎样的公司文化来激发创新?</li>↵</ul>↵<p>在这个专栏中,葛俊将基于硅谷和国内多年的从业经验,从研发流程、工程方法、个人效能、管理和文化这四个方向入手,系统介绍研发效能的理论和实践,探讨协同、开发、测试、运维等关键研发步骤中高效的工程方法。</p>↵<p>葛俊,前 Facebook内部工具团队Tech Lead,开源项目<a href="https://github.com/phacility/phabricator">Phabricator</a>的主要作者之一。在互联网行业奋斗的15年里,他曾任职于微软、Facebook、华为,以及硅谷和国内的两家创业公司。</p>↵<p>在此期间,他在研发效能团队工作过,也在使用效能流程和工具的产品团队工作过,也有过主导推进研发效能的丰富经历。可以说,他目睹了硅谷以及国内的大型企业、创业公司推进研发效能的成功经验与失败经历,同时总结了一套适用的高效能引入方法,希望在这个专栏里和你一起学习、进步。</p>↵<h2>专栏模块</h2>↵<p>专栏共35讲,分为5个模块。</p>↵<h3>1. 研发效能综述</h3>↵<p>讲解研发效能的定义、模型,并着重介绍什么是度量,以及度量的正确使用方法。借此,希望你能够梳理出研发效能的主脉络,构建出一幅清晰的知识图谱。</p>↵<h3>2. 研发流程</h3>↵<p>与你分享敏捷、持续集成、持续交付、DevOps、团队协同等话题。通过这个模块,希望帮助你深入理解研发过程中的关键流程,以及流程优化的基本原则,从而能够针对实际情况找到最合适自己的工程实践,让软件开发的整个流程更加顺畅、高效。</p>↵<h3>3. 工程方法</h3>↵<p>与你讨论研发流程(包括开发、测试、运维等)中各关键步骤的高效工程方法,并分析软件开发的趋势和热点,比如智能化、云原生等。通过这个模块,希望能够加深你对这些工程方法的了解,帮助你找到针对具体环节提高效能的方法,以及学会如何正确地使用这些方法。</p>↵<h3>4. 个人效能</h3>↵<p>聚集探讨如何提高个人效能,具体涉及深度工作、Git、命令行、VIM、工具环境集成等内容,旨在帮助你提高技术专精程度,持续成长。每个开发人员都应该提高自己的效能,只有这样才能持续学习持续提高,避免被业务拖着跑的现象。</p>↵<h3>5. 管理和文化</h3>↵<p>系统分析硅谷尤其是Facebook的工程师文化,并根据国内公司的具体落地经验,给出推荐的文化引入和建设方法。</p>↵<p><img src="https://static001.geekbang.org/resource/image/c0/e0/c0f8383def75164f9512e1a8b8af76e0.jpg" alt="" /></p>↵<h1><span class="orange">限时福利</span></h1>↵<ol class="js-audit">↵<li>订阅后,分享专属海报,每邀请一位好友订阅有奖励。</li>↵<li>戳此添加社群管理员,<a href="https://jinshuju.net/f/OCQKLn ">进入技术交流&福利群</a>。</li>↵<li>戳此<a href="https://promo.geekbang.org/activity/student-certificate?utm_source=app&utm_medium=xiangqingye">申请学生认证</a>,订阅课程一律 5 折。</li>↵</ol>↵<h2 class="js-audit">订阅须知</h2>↵<ol class="js-audit">↵<li>本专栏为订阅专栏,更新时间为2019年8月23日至2019年11月13日。订阅成功后,即可通过“极客时间”App端、小程序端、Web端永久阅读。</li>↵<li>本专栏更新时间为每周一、三、五,形式为图文 + 音频,共计35期,定价99元。</li>↵<li>企业批量购买请点击“<a href="https://time.geekbang.org/column/article/102047?utm_source=geektimeAPP&utm_medium=DingYueXuZhi&utm_campaign=qiyezhanghao">企业充值</a>”了解详情,可支持员工选课,企业支付。</li>↵<li>本专栏为虚拟商品,一经订阅,概不退款。</li>↵<li>在专栏阅读过程中,如有任何问题,请邮件联系service@geekbang.org。</li>↵</ol>`,column_unit: "35讲",sub_count: 3034,update_frequency: "每周一 / 三 / 五更新",column_price: 9900,column_price_market: 9900,articles: [{id: 0,is_video_preview: true,article_title: '第一课'}, {id: 1,is_video_preview: false,article_title: '第二课'}, {id: 2,is_video_preview: false,article_title: '第三课'}, {id: 3,is_video_preview: false,article_title: '第四课'}]
    }, {id: 180,type: 3,column_cover: "https://static001.geekbang.org/resource/image/cc/fb/ccb3acf6fcfab959aee1d800b882f7fb.png",column_subtitle: "程序员都应该学学怎么表达",column_title: "如何做好一场技术演讲",author_intro: "极客时间编辑部",author_name: "极客时间",column_intro: `<h2>内容简介</h2>↵<p>程序员都应该学学怎么表达。</p>↵<p>据调查,75% 的人在公众场合演讲时会感到非常恐慌。但是,公众演讲是每个人都需要面对的“刁难”,无论是学生时期的课题总结、毕业答辩,还是工作之后的公司内部项目汇报、外部技术交流,这些场合都需要我们具备优秀的演讲能力,才能更好地向别人展示我们的工作成果,让优秀的技术方案广为传播。</p>↵<p>公众场合的演讲能力成为职场中越来越重要的一项基础技能。 谁知道,未来的某一天,会不会是你,站在新闻发布会的台上,向下面黑压压的人群宣布一款你公司的技术产品呢? 又或者,你作为一位技术大咖,在一场技术大会上向大家讲述你的技术棋局?</p>↵<p>就像编程一样,演讲能力也是可以习得的。正如天生口吃的德摩斯梯尼通过自己的不断苦练也能成为古希腊著名的演说家一样,成为一个优秀的技术演讲者,也是有径可循的。</p>↵<p>这里收录的 6 篇文章,包含多位技术大牛的演讲经验总结,从技术人员的角度来剖析做好一场技术演讲的术与道。</p>↵<h2>内容目录</h2>↵<p>本系列共 6 篇文章,前 5 篇文章沿着“内容准备—心态调节—陈述技巧—形象管理”依次展开,每篇文章的主题各有侧重点。最后一篇是综合性的经验阐述,和前五篇提到的几个关键点既相互对照,又加入了节奏掌控、回答问题的技巧等独创性内容。</p>↵<p><img src="https://static001.geekbang.org/resource/image/34/d0/34edb1c8a377368df5a79265dbcfc0d0.jpg" alt="" /></p>↵<h1><span class="orange">限时福利</span></h1>↵<ol class="js-audit">↵<li>订阅后,分享专属海报,每邀请一位好友订阅有奖励。</li>↵<li>戳此添加社群管理员,<a href="https://jinshuju.net/f/OCQKLn ">进入技术交流&福利群</a>。</li>↵</ol>↵</ol>↵<h2>适宜人群</h2>↵<p>想提升演讲能力,向公众有效传播自己的技术方案、理念和观点的人;想学习更多的内容布局、组织方法,让自己的演讲更生动、更形象的人;想了解如何在公众场合管理好自己的身体语言,打造良好的个人形象的人。</p>↵<h2 class="js-audit">购买须知</h2>↵<ol class="js-audit">↵<li>本系列共六篇文章,现已全部上线,购买成功后,即可通过“极客时间”App端、小程序端、<a href="https://time.geekbang.org/column/intro/61">Web端</a>永久观看;</li>↵<li>由于文字内容为虚拟商品,一经购买,概不退款;</li>↵<li>在阅读过程中,如有任何问题,请邮件联系 service@geekbang.org。</li>↵</ol>`,column_unit: "6讲",sub_count: 17209,update_frequency: "约150分钟",column_price: 100,column_price_market: 100,articles: [{id: 0,is_video_preview: true,article_title: '第一课'}, {id: 1,is_video_preview: false,article_title: '第二课'}, {id: 2,is_video_preview: false,article_title: '第三课'}, {id: 3,is_video_preview: false,article_title: '第四课'}]
    }, {id: 198,type: 1,column_cover: "https://static001.geekbang.org/resource/image/7f/6d/7f9edc0620b7083074b21cc9036ffa6d.jpg",column_subtitle: "基于DDD的微服务拆分与设计",column_title: "DDD实战课",author_intro: "人保高级架构师",author_name: "欧创新",column_intro: `<p>随着分布式技术的快速兴起,我们已经进入到了微服务架构时代。微服务架构的出现,很好地实现了应用之间的解耦,解决了单体应用扩展性和弹性伸缩能力不足的问题。随着业务的复杂度升级,其好处自然不言而喻。</p>↵<p>那微服务到底怎么拆分和设计才算合理,拆多小才叫微服务?这个尖锐的问题,在业内一直被热议。紧接着,继阿里巴巴成功转型中台战略之后,微服务设计和拆分再至风口浪尖,对于众多公司来说,都是一个不小的挑战。</p>↵<p>那有没有好的方法来指导微服务和中台的设计呢?当然有,你也可能耳闻过,那就是领域驱动设计(DDD)。</p>↵<ul>↵<li>你可能会疑惑,早在2003年就诞生的DDD,怎么来指导“迟到”近20年才大热的微服务设计?</li>↵<li>怎么认识和学习这个抽象又庞大的知识体系?</li>↵<li>怎么应用,怎么实践?</li>↵<li>落地后它究竟能解决旧系统的哪些问题?</li>↵</ul>↵<p>本专栏将重点解决以上问题,力求用浅显易懂的案例,深入DDD的核心知识体系与设计思想,带你掌握一套完整而系统的基于DDD的微服务拆分与设计方法,明确从战略设计到战术设计的微服务标准设计过程,助力落地边界清晰、可持续演进的微服务架构。</p>↵<h2>你将获得</h2>↵<ul>↵<li>洞悉DDD必知必会10大核心概念</li>↵<li>掌握事件风暴与领域建模</li>↵<li>上手中台业务建模与设计</li>↵<li>实战设计清晰的微服务架构</li>↵</ul>↵<h2>作者简介</h2>↵<p>欧创新,人保高级架构师,拥有十多年的软件架构经验。他热衷于采用DDD的设计方法实现中台业务建模,专注基于DDD的微服务设计和开发。目前,他正在深入探索传统企业中台数字化转型的技术和方法体系。</p>↵<h2>课程设计</h2>↵<p>专栏共21讲,分为基础篇、进阶篇和实战篇三部分。</p>↵<p><strong>基础篇</strong>主要讲解DDD的核心知识体系,具体包括:领域、子域、限界上下文、实体、值对象、聚合和聚合根等概念。借助浅显易懂的案例,带你理解它们以及它们之间的合作、依赖关系。</p>↵<p><strong>进阶篇</strong>主要讲解领域事件、DDD分层架构、几种常见的微服务架构模型以及中台设计思想等内容。带你深入微服务分层设计的底层原理与具体实现。</p>↵<p><strong>实战篇</strong>作为本课程的重点,包含多个实战小项目,例如中台和领域建模的实战、微服务设计实战等。最后作者会用一个典型的案例将DDD所有的知识点串联,带你走一遍基于DDD的微服务设计全流程。</p>↵<p>另外,实战篇还补充有“如何借鉴微服务的设计思想来设计前端应用”“微服务设计原则”以及“分布式架构设计的关键注意事项”,以完善实战体系。</p>↵<p><img src="https://static001.geekbang.org/resource/image/3f/a7/3fe9eb89e825b14bebe4ffad68fe0da7.jpg" alt="" /></p>↵<h1><span class="orange">限时福利</span></h1>↵<ol class="js-audit">↵<li>订阅后,分享专属海报,每邀请一位好友订阅有奖励。</li>↵<li>戳此添加社群管理员,<a href="https://jinshuju.net/f/OCQKLn ">进入技术交流&福利群</a>。</li>↵<li>戳此<a href="https://promo.geekbang.org/activity/student-certificate?utm_source=app&utm_medium=xiangqingye">申请学生认证</a>,订阅课程一律 5 折。</li>↵</ol>↵</ol>↵<h2 class="js-audit">订阅须知</h2>↵<ol class="js-audit">↵<li>本专栏为订阅专栏,更新时间为2019年10月14日至2019年12月02日。订阅成功后,即可通过“极客时间”App端、小程序端、Web端永久阅读。</li>↵<li> 本专栏更新时间为每周一、三、五,形式为图文+音频,共计21期,定价68元。</li>↵<li>企业批量购买请点击“<a href="https://time.geekbang.org/column/article/102047?utm_source=geektimeAPP&utm_medium=DingYueXuZhi&utm_campaign=qiyezhanghao">企业充值</a>”了解详情,可支持员工选课,企业支付。</li>↵<li>本专栏为虚拟商品,一经订阅,概不退款。</li>↵<li>在专栏阅读过程中,如有任何问题,请邮件联系service@geekbang.org。</li>↵</ol>`,column_unit: "21讲",sub_count: 3878,update_frequency: "每周一 / 三 / 五更新",column_price: 5900,column_price_market: 5900,articles: [{id: 0,is_video_preview: false,article_title: '第一课'}]
    }]
    
  • mockdata/comment.js
    module.exports = [{id: 1,avatar: 'https://static001.geekbang.org/account/avatar/00/0f/52/62/1b3ebed5.jpg',name: '僵尸浩',isTop: true,content: '哈哈哈哈',publishDate: '今天',commentNum: 10,praiseNum: 5},{id: 2,avatar: 'https://static001.geekbang.org/account/avatar/00/0f/52/62/1b3ebed5.jpg',name: '极客主编',isTop: true,content: '我来送大礼了!!',publishDate: '上周',commentNum: 10,praiseNum: 2},{id: 3,avatar: 'https://static001.geekbang.org/account/avatar/00/0f/52/62/1b3ebed5.jpg',name: '极客老板',isTop: true,content: '我来发股票了!!!',publishDate: '十年前',commentNum: 10,praiseNum: 0}
    ]
    
  • detail.proto
    message Column {required int32 id = 1;required string column_cover = 2;required string column_title = 3;required string column_subtitle = 4;required string author_name = 5;required string author_intro = 6;required string column_intro = 7;required string column_unit = 8;required uint32 sub_count = 9;required string update_frequency = 10;required uint32 column_price = 11;optional uint32 column_price_market = 12;repeated Article articles = 13;
    }
    message Article {required uint32 id = 1;required bool is_video_preview = 2;required string article_title = 3;
    }message ColumnResponse {required Column column = 1;repeated Column recommendColumns = 2;
    }
    message ColumnRequest {required int32 columnid = 1;
    }
    
  • start.js
    const fs = require('fs')
    const protobuf = require('protocol-buffers');
    const schemas = protobuf(fs.readFileSync(`${__dirname}/detail.proto`)
    );// 假数据
    const columnData = require('./mockdata/column')/*** 服务端的编解包逻辑*/
    const server = require('./lib/geeknode-rpc-server')(schemas.ColumnRequest, schemas.ColumnResponse);server.createServer((request, response) => {// 因为都是假数据,这里就没有使用栏目id。真实项目会拿这个columnid去请求数据库const columnid = request.body;// 直接返回假数据response.end({column: columnData[0],recommendColumns: [columnData[1], columnData[2]]});}).listen(4000, ()=> {console.log('rpc server listened: 4000')});
    

node-client

  • 目录结构
  • template/index.js
    const fs = require('fs');
    const vm = require('vm');const templateCache = {};const templateContext = vm.createContext({include: function (name, data) {const template = templateCache[name] || createTemplate(name)return template(data);}
    });function createTemplate(templatePath) {templateCache[templatePath] = vm.runInContext(`(function (data) {with (data) {return \`${fs.readFileSync(templatePath, 'utf-8')}\`}})`,templateContext);return templateCache[templatePath]
    }module.exports = createTemplate
    
  • client.js
    const EasySock = require('easy_sock');const protobuf = require('protocol-buffers')
    const fs = require('fs');
    const schemas = protobuf(fs.readFileSync(`${__dirname}/detail.proto`));const easySock = new EasySock({ ip: '127.0.0.1',port: 4000,timeout: 500,keepAlive: true
    })easySock.encode = function(data, seq) {const body = schemas.ColumnRequest.encode(data);const head = Buffer.alloc(8);head.writeInt32BE(seq);head.writeInt32BE(body.length, 4);return Buffer.concat([head, body])
    }easySock.decode = function(buffer) {const seq = buffer.readInt32BE();const body = schemas.ColumnResponse.decode(buffer.slice(8));return {result: body,seq}
    }easySock.isReceiveComplete = function(buffer) {if (buffer.length < 8) {return 0}const bodyLength = buffer.readInt32BE(4);if (buffer.length >= bodyLength + 8) {return bodyLength + 8} else {return 0}
    }module.exports = easySock;
    
  • detail.proto
    message Column {required int32 id = 1;required string column_cover = 2;required string column_title = 3;required string column_subtitle = 4;required string author_name = 5;required string author_intro = 6;required string column_intro = 7;required string column_unit = 8;required uint32 sub_count = 9;required string update_frequency = 10;required uint32 column_price = 11;optional uint32 column_price_market = 12;repeated Article articles = 13;
    }
    message Article {required uint32 id = 1;required bool is_video_preview = 2;required string article_title = 3;
    }message ColumnResponse {required Column column = 1;repeated Column recommendColumns = 2;
    }
    message ColumnRequest {required int32 columnid = 1;
    }
    
  • index.js
    const mount = require('koa-mount');
    const static = require('koa-static')
    const app = new (require('koa'));
    const rpcClient = require('./client');
    const template = require('./template');const detailTemplate = template(__dirname + '/template/index.html');app.use(mount('/static', static(`${__dirname}/source/static/`)))app.use(async (ctx) => {if (!ctx.query.columnid) {ctx.status = 400;ctx.body = 'invalid columnid';return }const result = await new Promise((resolve, reject) => {rpcClient.write({columnid: ctx.query.columnid}, function (err, data) {err ? reject(err) : resolve(data)})})ctx.status = 200;ctx.body = detailTemplate(result);
    })app.listen(3000)// module.exports = app;
    

koa 项目中的知识点 - 详情页相关推荐

  1. 商品详情页html代码获取,直播带货小程序源码中,商品详情页是如何获取html图片的...

    在搭建直播带货小程序源码过程中,需要为商品构建详情页,而商品页中的图片是要通过html获取并展示到本地的,那么这个过程是如何实现的?接下来小编将通过代码演示一下: 1.配置webView mWebVi ...

  2. django博客项目8:文章详情页

    首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ...

  3. 传智健康项目中相关知识点介绍(如图片存储,发送短信,定时调度,统计报表...)

    1. 图片存储方案 1.1 介绍 在实际开发中,我们会有很多处理不同功能的服务器.例如: 应用服务器:负责部署我们的应用 数据库服务器:运行我们的数据库 文件服务器:负责存储用户上传文件的服务器 分服 ...

  4. 【Vue项目复习笔记】详情页的展示

    一.跳转详情页并携带iid 1.点击商品跳转到详情页 当我们点击GoodListItem中的每一个item,就跳转到对应的页面.我们首先要做的就是监听GoodsListItem的点击 在GoodsLi ...

  5. 【项目实战】---商品详情页的制作

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在前面的 ...

  6. 09_心理咨询_微信小程序项目实战_咨询师详情页静态效果实现

    一.咨询师信息 1.1 页面结构 在app.json里面的pages里面定义"pages/consultDetails/consultDetails" 1.定义一个view,给其添 ...

  7. 带货直播系统源码中,商品详情页是如何搭建起来的

    市面上大多数带货直播系统源码的商品介绍详情页,都是仿照淘宝的商品详情页的制作的,那么这个模块是如何通过代码建立起来的呢?下面小编将会通过代码来描述其实现过程. 1.实现滑动控制到导航栏的显示和隐藏 m ...

  8. vue项目中解决打开新页浏览器拦截的问题

    项目中,如果通过接口获取数据,并在then中打开新页面会提示浏览器阻止,如何解决呢? 其实很简单: 1.定义一个url data(){return{url:''} } 2.监听该url,url发生变化 ...

  9. vue3,电商项目中的商品详情-图片预览组件

    目的:完成商品图片预览功能和切换 分享一个vueuse的插件useMouseInElement useMouseInElement的官方文档 // 监听DOM元素 target 绑定的DOM元素中鼠标 ...

最新文章

  1. 【赠书】21世纪科技竞争的核心是超级智能的控制权
  2. 嵌套 移动端_360PC端小程序全面开放使用
  3. 关于python的垃圾回收机制_Python的垃圾回收机制
  4. QLabel显示图像
  5. Knockout.Js官网学习(创建自定义绑定)
  6. 德宝会员管理系统服务器密码是多少,易展路由器管理员密码是多少?
  7. 计算机网络故障的排除,计算机网络故障诊断与排除
  8. 通过css为类生成器给文本字体加上书名号,
  9. linux误删 bin目录,记linux下rm误删bin文件的解决方式
  10. Q2净利润同比下降1%,甲骨文转型之路错搭“老爷车”?
  11. nano spi flash linux构建指南
  12. 量子计算机的研究进展,量子计算原理及研究进展.pdf
  13. element 修改分页样式_vue想改变element分页样式
  14. Android Alpha 更改图片透明度
  15. VBA调用宏的方式总结大全
  16. 36.笔记go语言——函数
  17. Python是一种开源的、免费的、通用的脚本语言
  18. 计算机项目(毕设课设) 之 含文档+PPT+源码等]精品基于PHP实现的高校兼职应聘招聘系统
  19. 2.4G有源智能电子学生卡(SI24R2E应用实例)
  20. spwm控制算法c语言实现,三种SPWM波形生成算法的分析与实现

热门文章

  1. ILOG 甘特图 ActivityTable 去掉自动属性及其他
  2. 连接服务器教程,Xshell、Xftp及PyCharm连接深度学习GPU服务器的详细使用方法
  3. 虎牙安卓Android最新的,虎牙安卓版
  4. 一文彻底理解:训练集,验证集,测试集,交叉验证
  5. 数据分析1——系统认识数据分析
  6. ant安装、环境变量配置、ant实例
  7. c语言输入姓名查分数,输入学生姓名,查找该学生并输出其学号姓名成绩
  8. 企业舆情监测系统工作流程
  9. Matlab实验(一)
  10. android 小学课程,中小学同步课堂