├── .gitignore ├── index.html ├── docs ├── intro │ ├── index.html │ ├── 1.png │ └── README.md └── index.html ├── README.md ├── package.json └── LICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | docs/index.html -------------------------------------------------------------------------------- /docs/intro/index.html: -------------------------------------------------------------------------------- 1 | ../index.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | https://elemefe.github.io/clouding/docs/intro/ 2 | -------------------------------------------------------------------------------- /docs/intro/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElemeFE/clouding/HEAD/docs/intro/1.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clouding", 3 | "version": "1.2.5", 4 | "description": "A MODULARIZATION SOLUTION OF FRONTEND ", 5 | "main": "jinkela.js", 6 | "author": "YanagiEiichi (yanagieiichi@web-tinker.com)", 7 | "license": "MIT", 8 | "scripts": { 9 | "test": "ui-tester-start tests" 10 | }, 11 | "reciperConfig": { 12 | "name": "Jinkela", 13 | "darkColor": "#333", 14 | "normalColor": "#666", 15 | "primaryColor": "#000", 16 | "logoUrl": "//fuss10.elemecdn.com/9/ca/f88b429d6278cdf69e0027dfea51ejpeg.jpeg", 17 | "languages": [ 18 | "xml", 19 | "markdown", 20 | "bash", 21 | "javascript" 22 | ] 23 | }, 24 | "devDependencies": { 25 | "ui-tester": "~1.1.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) <2016> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/intro/README.md: -------------------------------------------------------------------------------- 1 | ## 解决的问题 2 | 3 | 消除前端项目部署与业务量之间的关系 4 | 5 | 无论业务量增加多少倍,前端所需的硬件资源都是额定的 6 | 7 | ## 背景 8 | 9 | 很早以前 Web 开发是不区分前后端的,HTML 由服务器动态生成,项目部署只是服务器端的代码发布而已。 10 | 后来浏览器提供了越来越多的 API 支持,前端开发逐渐复杂起来。 11 | 于是诞生了专注于浏览器端程序开发的「前端」这个分支。 12 | 13 | 虽然现在前后端分离开发已经非常普遍,但是在很多古老的程序架构下,它们只是实现了开发人员的职责分离。 14 | **这种前后端混部的模式会带来巨大的风险。** 15 | 16 | 1. 后端发布的风险 17 | 18 | 前端的变更往往是小而频繁的,也许只是修改一个文案或一个颜色。 19 | 在前后端混部的情况下,这些变更都需要所有代码重新编译重新发布,发布过程的每个环节都是风险。 20 | 比如编译过程中的某个依赖的版本错误,或者发布后重启服务导致本地缓存丢失,甚至是发布过程中网络抖动等。 21 | 22 | 2. 服务器负载的风险 23 | 24 | 有一类前端页面是属于纯展示性的,完全不涉及数据交互。 25 | 而且出于营销等目的,它们的业务量会非常巨大,而且难以预估。 26 | 这类页面带来的流量很可能是服务器无法接受的。 27 | 28 | **真正的前后端分离是后端完全 API 化,前后端分别开发和部署,互不干扰。** 29 | 一个前端项目可能调用多套后端 API,一套后端 API 也可能提供给多个前端项目使用。 30 | 31 | 前后端完全分离后我们可以观察到,数据的变更不会导致前端的变更。 32 | 这意味着**前端更趋向于「资源型产出」,而不是后端那样的「运营型产出」**。 33 | 举例来说就是一个项目的业务量增加了 100 倍,后端开发人员可能要一直调整架构变更方案,而前端开发人员可以和设计师一样完全使用同一套东西。 34 | 35 | 既然前端可以是资源型产出,那么就可以和资源类部署结合起来。 36 | **这就是 Clouding 这套方案**。 37 | 38 | ## 零机器 39 | 40 | 所谓的「零机器」并不是完全没有服务器,理论上必须要有服务器才能跑 http 服务。 41 | 这里的「零机器」是指没有任何与业务量相关的机器。 42 | 43 | 一般后端服务的机器数量与业务量是有关的,大多数程线性关系。 44 | 而资源类型的部署可以使用 CDN,对源站的压力只有 CDN 节点乘以资源量而已,这些都是常量。 45 | 46 | ## 部署原理 47 | 48 | **Clouding** 方案的核心其实就是把前端项目完全部署在 CDN 上。 49 | 50 | 由于 CDN 总是需要一个中心数据源,所以这个过程需要一个源服务器(下图中的 OSS)。 51 | 52 | 53 | 54 | OSS 可以是第三方的服务,也可以是自建的。 55 | 56 | 整个工作流畅大概有这么几个步骤: 57 | 58 | 1. 发布系统将代码推送到 OSS 59 | 2. 调用 CDN 的 API 清缓存 60 | 3. 由于缓存被清空,CDN 被请求后回到 OSS 取资源 61 | 62 | 有些云服务提供商同时提供了 OSS 和 CDN 服务,并且提供了 OSS 到 CDN 的自动同步功能。 63 | 如果使用这种方式我们要做的只是将代码发布到 OSS,其它事情全交给云提供方的程序搞定。 64 | 65 | ## 缓存设置 66 | 67 | **Clouding** 方案中最关键的参数配置就是缓存时间了。 68 | 我们不仅要关心资源在客户端缓存多久,还得关心资源在 CDN 节点缓存多久。 69 | 这可以在响应的 Cache-Control 中分别使用 max-age 和 s-maxage 来配置。 70 | 由于 **Clouding** 的数据流向是主动的,我们主动调用 CDN 的 API 来清缓存,所以 CDN 到 源站的缓存可以设非常大。 71 | 也就是 s-maxage 的取值非常大,可以设置个一年之类的时间。 72 | 73 | 至于客户端要缓存多久那就得看业务需求了。 74 | 如果前端项目构建时会自动给资源文件加版本号,那么我们可以针对 html 文件关闭缓存,对其它类型的资源文件开启一个非常大的缓存。 75 | 或者最坏的情况是完全关闭客户端缓存,让所有请求打到 CDN 节点。即便是这样也只是多出点流量而已,对源站并没有额外的压力。 76 | 77 | ## 前端项目改造 78 | 79 | **Clouding** 方案的难点并不是在部署上,而是对于前端项目的改造。 80 | 81 | 并不是任何前端项目都可以直接使用这套方案。 82 | 这套方案有许多局限性,在使用时前端项目可能是需要改造的。 83 | 下面我们逐个介绍。 84 | 85 | 1. URL 路由 86 | 87 | CDN 本身是为静态资源设计的,而静态资源 http 服务器通常被设计成 URL 与磁盘文件直接对应。 88 | 所以前端项目也只能使用此种方式来访问资源。 89 | 90 | 自从前端有了 History API 后,在前端圈有个非常普遍的做法。 91 | 让服务器将所有请求都指向同一个 html 文件,由前端自己处理路由并展示。 92 | 这种做法到 **Clouding** 上就不再适用了,或者即便有一些黑科技可以实现但也不建议使用。 93 | 94 | 前端业务如果希望自己维护 URL 与展示逻辑可以选择 QueryString 和 hash。而 QueryString 可能造成 http 无法 cache,所以这里推荐的方案是使用 hash。 95 | 96 | 2. 跨域 API 调用 97 | 98 | 即便是前后端分离,一些前端项目依然会通过服务器代理来调用后端 API 以解决跨域问题。 99 | 如果前端项目完全在 CDN 上,CDN 是无法帮你代理调用 API 的。 100 | 或者即便通过 CDN 从源站调用 API,这也会导致源站的负载变得与业务有关,违背了我们的理念。 101 | 所以 **Clouding** 方案中的前端项目需要完全跨域调用 API。 102 | 至于如何跨域,这就得根据自己的项目需求来考虑了。 103 | 现代浏览器对 CORS 的支持是不错的,大部分使用可以满足业务需求。 104 | 如果实在是要考虑低版本 IE 的话建议使用 jsonp。 105 | --------------------------------------------------------------------------------