Appearance
架构协同常见问题
DevOps
参考链接:
详解:
概念
DevOps 是一种软件开发方法,为了让开发、运维和 QA 可以高效协作的流程。可以把 DevOps 看作开发(development)、技术运营(technology)和质量保障(quanlity assurance)三者的交集。
演变
DevOps 从现有的软件开发策略/方法发展而来,以响应业务需求。
阶段 1:瀑布模型
需要清晰固定的需求。
阶段 2:敏捷开发
需求变化快,需要快速开发。
阶段 3:devops
需求变化快,快速开发,尽可能自动化。
对应用程序发布的影响
- 频繁发布时每次程序变化少,程序能平滑生长。
- 高效协调开发与运营,确保人员理解变更和充分合作。
- 自动化部署,减少出错的可能性
工具链
- 代码管理(SCM):GitHub、GitLab、BitBucket、SubVersion
- 构建工具:Ant、Gradle、maven
- 自动部署:Capistrano、CodeDeploy
- 持续集成(CI):Bamboo、Hudson、Jenkins
- 配置管理:Ansible、Chef、Puppet、SaltStack、ScriptRock GuardRail
- 容器:Docker、LXC、第三方厂商如 AWS
- 编排:Kubernetes、Core、Apache Mesos、DC/OS
- 服务注册与发现:Zookeeper、etcd、Consul
- 脚本语言:python、ruby、shell
- 日志管理:ELK、Logentries
- 系统监控:Datadog、Graphite、Icinga、Nagios
- 性能监控:AppDynamics、New Relic、Splunk
- 压力测试:JMeter、Blaze Meter、loader.io
- 预警:PagerDuty、pingdom、厂商自带如 AWS SNS
- HTTP 加速器:Varnish
- 消息总线:ActiveMQ、SQS
- 应用服务器:Tomcat、JBoss
- Web 服务器:Apache、Nginx、IIS
- 数据库:MySQL、Oracle、PostgreSQL 等关系型数据库;cassandra、mongoDB、redis 等 NoSQL 数据库
- 项目管理(PM):Jira、Asana、Taiga、Trello、Basecamp、Pivotal Tracker
跨端框架
参考链接:
详解:
描述
传统网页开发受浏览器能力限制太大,如 PC 端各浏览器和移动端的 android 和 ios 限制,以及前端框架 jquery,vue,react 等的不同,相同的功能需要适配不同的平台,大大增加了开发难度。造成这种问题的原因是各平台由终端开发者主导开发,而不是从前端开发者角度出发。
腾讯 hippy
https://github.com/Tencent/Hippy
实现了类似 Flutter 的引擎直通架构(在 React Native 中的 Fabric 架构),通过 C++ 开发的模块直接插入 JS 引擎中运行,绕过了前终端通讯编解码的开销,有效提升了 JS 前端代码和终端的通讯性能。
整体划分为框架层、引擎层、渲染层。每层均可自由替换。框架层既可以使用 React 也可以使用 Vue,或者未来的新兴框架。引擎层可以使用 JS,将来也支持 Dart,Lua 等语言。渲染层目前使用原生 Native 绘制,也支持自绘,业务可以根据需求自由选择。
hippy-vue 的组件、参数和接口完全符合浏览器标准,前端开发用浏览器标签和常用的 CSS 选择器就可以完成跨端界面绘制。其优势如下:
- 前端开发基本了解一下 hippy-vue 开发的限制就可以上手跨端开发;
- 可以复用 Web 端绝大多数的生态;
- 不需要 Web 转接库就可以直接生成网页。
应用场景:
- 全民 K 歌:react + hippy-react + hippy-react-web
- 王者营地:vue + hippy-vue
taro
https://github.com/NervJS/taro
Taro 是一套遵循 React 语法规范的多端统一开发框架,只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端,生成能运行在微信小程序、H5、React Native 等的应用。
uni app
uni app 使用 vue 语法
跨端框架原理
背景
小跨端框架发展到如今已经百花齐放、百家争鸣:除了美团的 mpvue 、网易的 megalo 、滴滴的 chameloen 已经趋于稳定,京东的 Taro开始探索 taro next, Hbuilder 的uni-app 产品和生态持续完善,微信新推出了支持H5和微信小程序的 kbone 框架,蚂蚁金服的 remax
按语法分类:vue/react
按实现原理分类:compile time 编译时(通过语法树转换为小程序语法)/runtime 运行时(更有优势,通过适配层运行vue/react)
从vue到小程序
.vue -> .wxml/wxss/js/json template -> .wxml //mpvue、megalo、uni-app 的框架是采用了 ast 来解析转化模板 div -> view v-if -> wx:if/a:if(支付宝)/s-if(百度) @click -> bindtap style -> wxss script -> js new Vue() -> Page() vue -> vnode/diff -> render函数 -> setData() //vue上数据变化,通过运行时来通知小程序,更新page,小程序触发事件,通过运行时,找到vue的回调函数
从react到小程序
.jsx -> babel -> ast -> .wxml/wxss/js/json fiber -> 自定义生命周期render的渲染器remax -> vnode/remax镜像树 在第一次 mount 时,Remax 运行时初始化时会通过小程序的 setData 初始化小程序的 JSON 树状数据, 在小程序加载完毕后, Remax 通过递归模板的形式,把JSON 树状数据渲染为小程序的页面 Remax 运行时在数据发生更新时,就会通过小程序的 setData 去更新上面小程序的 JSON 树状数据, JSON 树状数据被更新了,小程序自然会触发更新数据对应的那块视图的渲染
自动部署
参考链接:
详解:
- 描述
发布前端代码,操作流程长,有出错风险。因此需要自动化构建和部署。
步骤:
本地构建:
1. 执行 build 命令,等待 build 完成。 2. build 完成后,提交打包后的 HTML 文件。
发布代码:
1. 打开发布系统 2. 选择发布项目及环境 3. 打开发布页面 4. 选择发布文件 5. 填写发布信息 6. 点击确认发布
- 搭建 GitLab CI/CD
新建 GitLab 项目
配置 runner
GitLab Runner 一般由 GitLab 系统维护者管理,配置后,同类项目可以共享,一般不需要进行修改。
参考文档:GitLab Runner 文档
注意:
- 配置 Runner 后,push 代码,触发了 pipeline,但一直处于 Pending 状态
This job is stuck, because you don’t have any active runners that can run this job
注册的 Runner,默认情况下,不会运用没有 tag 的 job,可以在 Settings→CI/CD→Runners Settings,去掉 Runner untagged jobs 即可。
- GitLab Runner 的类型
有三种类型的 Runner,Shared Runners 在整个系统所有项目都可以使用,Group Runners 注册后,同一个项目下的不同代码库共享,Specific Runners 需要给项目单独配置,使用 Specific Runners 注意考虑是否需要关闭 Shared Runners、和 Group Runners。
Shared Runners
Specific Runners
Group Runners
- 在 GitLab CI 中使用 docker
在部署到阿里云时,需要在 GitLab CI/CD 中使用 docker 打镜像发布。可以参考 Building Docker images with GitLab CI/CD(https://docs.gitlab.com/ee/ci/docker/using_docker_build.html)
- 在 GitLab CI/CD 中访问 Runner 宿主机目录
活动项目 .gitlab-ci.yml 文件如下,下面主要通过活动项目的 .gitlab-ci.yml 文件来介绍我们的实践过程、.gitlab-ci.yml 详细的用法,可参考 GitLab CI/CD Pipeline Configuration Reference 文档(https://docs.gitlab.com/ee/ci/yaml/README.html)
.gitlab-ci.yml
拉取项目到本地;
在项目根目录新建 .gitlab-ci.yml 文件;
提交 .gitlab-ci.yml 文件;
在项目的 CI/CD 中,可以看到 CI/CD 的运行情况
yaml# 执行 CI/CD 依赖的 Docker 基础镜像。镜像中有 Node、Yarn、Dalp image: node # 定义 stages,定义了pipeline 分为几个过程: # 下载依赖阶段 pre_build,构建阶段 build,发布阶段 deploy stages: - build - test # 定义 job build 阶段: stage: build # 声明当前的阶段,在 stages 中使用 # before_script 执行 script 前的操作 script: # 当前 stage 需要执行的操作 - echo "build stage" # 定义 job 发布到测试环境: stage: test script: - echo "test stage" # variables 用于定义变量 # changes 指定 stage 触发条件 # refs 指定 stage 触发的分支
完整
yamlimage: registry.huajiao.com/gitlab-ci/node-yarn:v1.4 variables: # $CI_PROJECT_PATH :项目id,用于项目唯一区分本项目与其它项目 # $CI_PROJECT_DIR :本地项目路径 # $PROCESS_PATH :临时文件目录(包括日志和一些临时文件) NODE_MODULES_PATH: /runner-cache/frontend/$CI_PROJECT_PATH/$CI_BUILD_REF_NAME/node_modules stages: - pre_build - build - deploy 下载依赖: before_script: # 无 node_modules 文件时,新建 node_modules 文件 - /bin/bash ./ci/mkdir.sh $NODE_MODULES_PATH # 软链 node_modules 到宿主机 - ln -s $NODE_MODULES_PATH . - cd webpack@next stage: pre_build script: - echo "yarn install" - yarn install --network-timeout 60000 only: changes: - webpack@next/package.json refs: - test - test-99 - test-128 - master - ci - feature/ci-test 构建: stage: build variables: CI_COMMIT_BEFORE_SHA_PATH: /mnt/gv0/gitlab-runner-cache/$CI_PROJECT_PATH CI_COMMIT_BEFORE_SHA_FILE_NAME: $CI_BUILD_REF_NAME.sh CI_COMMIT_BEFORE_SHA_FILE: /mnt/gv0/gitlab-runner-cache/$CI_PROJECT_PATH/$CI_BUILD_REF_NAME.sh before_script: # 建存此次 CI CI_COMMIT_SHA 的文件 - /bin/bash ./ci/mkfile.sh $CI_COMMIT_BEFORE_SHA_PATH $CI_COMMIT_BEFORE_SHA_FILE_NAME # 软链 node_modules 到宿主机 - ln -s $NODE_MODULES_PATH . - rm -rf php/share/* - cd webpack@next script: # 缓存上次ci - source $CI_COMMIT_BEFORE_SHA_FILE - echo "CI_COMMIT_BEFORE_SHA=$CI_COMMIT_SHA" > $CI_COMMIT_BEFORE_SHA_FILE - python3 ../ci/build.py # 编译 - /bin/bash ../ci/commit.sh # 提交编译结果 only: changes: - www_src/**/* refs: - test - test-99 - test-128 - master - ci
测试发布: stage: deploy variables: PROCESS_PATH: /mnt/gv0/gitlab-runner-cache/deploy/process/$CI_JOB_ID # 目录不要换,用于日志服务器获取日志展示 script: - mkdir $PROCESS_PATH # 建立发布临时路径,存放发布配置中间文件和结果日志用 - dplt $CI_PROJECT_DIR/.deploy_test.yml $CI_PROJECT_PATH $CI_PROJECT_DIR/php/ $PROCESS_PATH # dplt 发布yml配置 - echo "发布完成,错误日志查看http://new.admin.wolffy.qihoo.net/log?path="$PROCESS_PATH - echo
ls $PROCESS_PATH/*.log
only: changes: - php/**/* refs: - test* 下载依赖阶段(pre_build stage) 下载依赖的方案是:当 package.json 文件发生变化时,触发 pre_build stage,执行 yarn install。下载的 node_modules 放在宿主机下,执行时通过软链获取依赖。 * 构建阶段(build stage) 1. diff 文件变化 每次 CI 时,将当前 CI commit SHA(CI_COMMIT_SHA 变量)存在文件中,存为 CI_COMMIT_BEFORE_SHA 变量, diff 时,git diff 当前 CI 与上次 commit SHA 的变化。 2. 前端 build 根据 git diff 的变化情况,确定本次需要打包的项目。 3. commit build 后结果 在 GitLab CI/CD 提交代码时,使用 Git 凭证存储,提交打包后的 HTML 文件。Git 凭证存储细节可参考凭证存储文档(https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%87%AD%E8%AF%81%E5%AD%98%E5%82%A8) * 发布阶段(deploy stage) 发布阶段,使用内部的 rsync 工具 dplt 将打包后的 HTML 文件部署。dplt 可配置集群、机器列表。
单点登录
SSO(Single Sign On,单点登录,架构)优点
- 提升用户体验:用户使用同一公司的不同产品,只需登录一次即可
- 避免重复开发:后端不用开发多套登录逻辑
- 提升安全系数:运维不需维护多个登录系统而导致疏忽修复漏洞
CAS(Central Authentication Service,中心授权服务)
- 1.0 称为基础模式,web 端单点登录。
- 2.0 称为代理模式,适用于存在非 Web 应用之间的单点登录。
SSO 的演进与分类
同域 SSO
共用同域 cookie 即可
同父域 SSO
共用同域 cookie,把 cookie 的 domain 设置为其父域,设置方法见参考链接 2
跨域 SSO
设置独立的 SSO 服务器,CAS 方案
CAS 1.0
概念
TGT:Ticket Grangting Ticket
TGT 是 CAS 为用户签发的登录票据,拥有了 TGT,用户就可以证明自己在 CAS 成功登录过。TGT 封装了 Cookie 值以及此 Cookie 值对应的用户信息。当 HTTP 请求到来时,CAS 以此 Cookie 值(TGC)为 key 查询缓存中有无 TGT ,如果有的话,则相信用户已登录过。
TGC:Ticket Granting Cookie
CAS Server 生成 TGT 放入自己的 Session 中,而 TGC 就是这个 Session 的唯一标识(SessionId),以 Cookie 形式放到浏览器端,是 CAS Server 用来明确用户身份的凭证。
ST:Service Ticket
ST 是 CAS 为用户签发的访问某一 service 的票据。用户访问 service 时,service 发现用户没有 ST,则要求用户去 CAS 获取 ST。用户向 CAS 发出获取 ST 的请求,CAS 发现用户有 TGT,则签发一个 ST,返回给用户。用户拿着 ST 去访问 service,service 拿 ST 去 CAS 验证,验证通过后,允许用户访问资源。
流程
- 用户访问 a 网站,并首次登陆,因没有任何票据,重定向到 SSO 服务器登录页,并带上登陆成功后需要返回的地址
- 用户在 SSO 登录页登陆,SSO 后端产生 Session 票据 TGT,重定向到之前指定的页面,并在 response 带上 cookie 的票据 ST
- 用户回到 a 网站,根据返回的 ST 设置 cookie
- 用户继续访问 a 网站,判断到 cookie 中有 ST,a 服务器请求 SSO 服务器,SSO 验证成功,在 a 网站后端产生 session,更新 cookie 为 a 网站 session 的登录状态
- 用户访问 b 网站,因没有任何票据,重定向到 SSO 服务器登录页,此时 SSO 登录页 cookie 已存在票据 TGC,经过校验后,证实已经登录
- SSO 页面重定向到 b 网站,并带上新的 ST,设置 cookie
- 用户继续访问 b 网站的流程同第 4 步
- 登出流程核心为清除 SSO 对应的 session,再通知更网站清除 cookie
淘宝天猫方案
天猫中嵌淘宝 iframe,天猫登录后,从 SSO 中获取到 token,并设置天猫 cookie,再设置淘宝 iframe 的 src,传入 token,淘宝 onload 检测到 url 有 token,则设置淘宝的 cookie。
codeReview
参考链接:
详解
背景
每人需要维护
- PC:vue/react/angular/typescript/es6/eslint/prettier
- h5:flexible/ssr
- 多端:小程序/app/electron
- 后端:koa/express
- 测试:jest/puppeteer
技术要求
需要技术架构、开发流程、数据流处理、资产市场、最佳实践
代码质量问题
- 项目Bug较多,同样的坑不同的人会踩
- 迭代后的代码难维护,包括代码可读性差、复用度低等
- 模块的整体设计也欠缺,扩展能力难以支撑业务发展。
定义需求
从源头把控代码质量和效率
统一代码评判标准和认知
发现边界问题
提出改进建议
共享和迭代集体代码智慧
交流计思路和编码实践
沉淀最佳实践
迭代统一规范
标准化方案
review 小组
各端经验丰富的人员讨论对规范和原则的实践
代码质量评价维度和标准
基本
- 是否符合基本规范
架构
- 是否按照设计文档思路来写代码
- 是否发现了更好的解决方案
- 是否提供了很好的解决思路
代码
- 是否明显重复代码
- 是否合理抽取枚举值,禁止使用“魔法值”
- 是否合理使用已有的组件和方法
- 对已有的、不合理的代码进行重构和优化
- 职责(组件、方法)、概念是否清晰
健壮性
- 边界和异常是否考虑完备
- 在review阶段是否发现明显bug
- 是否考虑安全性(xss)
效率
- 是否抽取共用常量
- 否抽取沉淀基础组件和通用业务组件到组件库
review
提供文档
- 地址、产品文档、UI稿、技术设计、效率平台、接口文档
review人员分配
- 技术栈、业务熟悉程度、空闲程度、
要求
- 在提测前进行
- 各项评分、备注、解决方案
- 提测体现review内容
- 讨论和反馈,确认review有效
- 记录、分享
平台化方案
标准化缺点
操作欠缺自动化
- 流程的很多环节明显可以自动化,节省重复的工作量
- 对流程的把控依赖人,容易执行不到位
信息欠缺数字化
- 对 code review 的评分统计需要人工,工作量大
- code review 的总览和数据分析可以支撑更好的判断团队问题和决策提升整体代码质量的策略
流程欠缺可视化
- 所有流程应该是可以大盘总览,单个详情全面的
- 每个code review事务的状态是可见的
解决
- 程序自动同步信息到微信:相关负责人review状态
- 自动创建文档模板承载一次code review 全过程:立项、材料、评审、记录
Serverless
参考链接:
详解
概念
简单理解为:把代码文件放到云平台,运维交给云平台处理,云平台按次/流量收费。
无服务器(Serverless)计算,过去是“构建一个框架运行在一台服务器上,对多个事件进行响应”,Serverless则变为“构建或使用一个微服务或微功能来响应一个事件”,做到当访问时,调入相关资源开始运行,运行完成后,卸载所有开销,真正做到按需按次计费。这是云计算向纵深发展的一种自然而然的过程。
它与传统架构的不同之处在于,完全由第三方管理,由事件触发,存在于无状态(Stateless)、暂存(可能只存在于一次调用的过程中)计算容器内。构建无服务器应用程序意味着开发者可以专注在产品代码上,而无须管理和操作云端或本地的服务器或运行时。
FaaS(Function as a Service,函数即服务)
无须自行管理服务器系统或自己的服务器应用程序,即可直接运行后端代码。
BaaS(Backend as a Service,后端即服务)
不再编写或管理所有服务端组件,可以使用领域通用的远程组件(而不是进程内的库)来提供服务(依赖第三方服务)。
工作原理
与使用虚拟机或一些底层的技术来部署和管理应用程序相比,无服务器计算提供了一种更高级别的抽象。因为它们有不同的抽象和“触发器”的集合。
拿计算来讲,这种抽象有一个特定函数和抽象的触发器,它通常是一个事件。以数据库为例,这种抽象也许是一个表,而触发器相当于表的查询或搜索,或者通过在表中做一些事情而生成的事件。
API接口一旦构建完成,应用程序的功能就可以在基于移动和基于 Web 的版本中重用。
使用场景
- 在Web及移动端服务中,可以整合API网关和Serverles服务构建Web及移动后端,帮助开发者构建可弹性扩展、高可用的移动或 Web后端应用服务。
- 在IoT场景下可高效的处理实时流数据,由设备产生海量的实时信息流数据,通过Serverles服务分类处理并写入后端处理。
- 在实时媒体资讯内容处理场景里,用户上传的音视频到对象存储OBS,通过上传事件触发多个函数,分别完成高清转码、音频转码等功能,满足用户对实时性和并发能力的高要求。
- 还适合于任何事件驱动的各种不同的用例,这包括物联网,移动应用,基于网络的应用程序和聊天机器人等。
应用负载有显著的波峰波谷
当自有机器的利用率小于 30%,使用 Serverless 后会有显著的效率提升。对于云服务厂商,在具备了足够多的用户之后,各种波峰波谷叠加后平稳化,聚合之后资源复用性更高。
如外卖企业负载高峰是在用餐时期,安防行业的负载高峰则是夜间,这是受各个企业业务定位所限的;而对于一个成熟的云服务厂商,如果其平台足够大,用户足够多,是不应该有明显的波峰波谷现象的。
基于事件的数据处理
视频转码、抽取数据、人脸识别等,这些均为通用计算任务,可由函数计算执行。
开发者需要自己写出实现逻辑,再将任务按照控制流连接起来,每个任务的具体执行由云厂商来负责。如此,开发变得更便捷,并且构建的系统天然高可用、实时弹性伸缩,用户不需要关心机器层面问题。
优点
- 支持Serverless计算的平台可以节省大量时间和成本,同时可以释放员工,让开发者得以开展更有价值的工作,而不是管理基础设施。
- 提高敏捷度,更快速地推出新应用和新服务,进而提高客户满意度。
缺点
不适合长时间运行应用
Serverless 在请求到来时才运行,当应用不运行的时候就会进入 “休眠状态”,下次当请求来临时,应用将会需要一个启动时间,即冷启动时间。
如果你的应用需要一直长期不间断的运行、处理大量的请求,那么你可能就不适合采用 Serverless 架构。
如果你通过 CRON 的方式或者 CloudWatch 来定期唤醒应用,又会比较消耗资源。
需要我们对它做优化,如果频繁调用,这个资源将会常驻内存,第一次冷启之后,就可以一直服务,直到一段时间内没有新的调用请求进来,则会转入“休眠”状态,甚至被回收,从而不消耗任何资源。
完全依赖于第三方服务
当我们采用某云服务厂商的 Serverless 架构时,我们就和该服务供应商绑定了,那么我们再将服务迁到别的云服务商上就没有那么容易了。
修改底层代码建立隔离层,就需要隔离 API 网关、隔离数据库层,市面上还没有成熟的 ORM 工具,让你既支持Firebase,又支持 DynamoDB等等。这些带给我们额外的成本。
缺乏调试和开发工具
需要日志记录插件
配置复杂
AWS Lambda的 CloudFormation配置是如此的复杂,并且难以阅读及编写(JSON 格式),虽然CloudFomation提供了Template模板,但想要使用它的话,需要创建一个Stack,在Stack中指定你要使用的Template,然后aws才会按照Template中的定义来创建及初始化资源。
Serverless Framework的配置更加简单,采用的是 YAML 格式。在部署的时候,Serverless Framework 会根据我们的配置生成 CloudFormation 配置。然而这也并非是一个真正用于生产的配置,真实的应用场景远远比这复杂。
工具
k8s容器服务,docker
小程序云开发
提供serverless云服务,快速实现小程序业务开发
开发对比
传统
- 产品经理->后端开发->部署上线->前端开发->正式发布
- 关注非业务逻辑
- 前期预付成本
- 自行开发产品逻辑
- 自行运维系统
- 前后端联调,上线时间长
- 小程序->后端api->数据库->小程序
- 购买资源->搭建环境->上传代码->部署应用->正式发布
- 自行维护文件系统
- 自行配置cdn
云开发
- 产品经理->->前端开发->正式发布
- 只关心业务逻辑
- 按需付费
- 使用云逻辑
- 云端服务商运维
- 前端一站式解决
- 小程序->数据库->小程序
- 购买资源->上传代码->正式发布
- 云服务商维护文件系统
- 云服务器提供cdn
云开发能力
- 储存:上传下载文件,可视化管理
- 云函数:云端运行代码,自动鉴权
- 云数据库:读写json数据库
- 音视频:通话服务,互动白板,美颜滤镜,高清视频通话
- 图像服务:人脸识别,鉴黄
云开发控制台
- 查看数据统计
- 管理用户信息
- 管理数据库
- 管理云函数
- 管理文件储存
云开发API分类
- 按端:小程序端、服务端
- 类型:数据储存、文件储存、云函数
代码智能自动化
参考链接:
详解
社区
- 2w 多用户、6w 多模块、 0 前端参与研发的双十一等大促营销活动、70% 阿里前端在使用
- 79.26% 无人工参与的线上代码可用率、90.9% 的还原度、Icon 识别准确率 83%、组件识别 85%、布局还原度 92.1%、布局人工修改概率 75%
- 研发效率提升 68%
使用
- 下载ps插件,解压安装
- 重启ps,打开psd,找到窗口--拓展功能--ImgCook ,选择图层,点击插件上的导出数据
- 导出完毕,点击去粘贴,会打开一个网页,ctrl+V 粘贴
- 选择dsl,选择何种方式导出代码(很多格式),右上角保存,然后导出为 .taz 压缩包,解压
- 项目里粘贴,修改图片路径,预览
对UI的要求
- 图层建立文件夹,鼓励在文件夹上写有意义的名字,汉语英语均可
- 同一个元素不能跨文件夹复用,比如背景图由多个不同位置的图层拼贴
- 直线,图形使用矢量图,减少位图的使用
对前端的要求
- 给文件夹添加 ‘-合并’ 会自动合并图层
- 在文件夹上添加 '#英文名字# 会作为class的前缀