工作中的遇到的一些小知识 4

lottie production环境下bug修复总结

现象:
前段时间,用lottie-web做动画的时候,发现在有个别动画在本地测试时可以正常播放,打包上线后会报库代码内的错误

猜测原因:
打包过程中的uglify有损压缩了lottie-web的代码,导致部分特性的bug

修复方式:

  1. 在webpack配置中,为lottie-web专门指定一个chunk
  2. 在optimization中,指定一个lottie的cacheGroup,保证一个专门的chunk
  3. minimizer中uglifyJSConfig指定exclude为lottie的chunk名,避免被uglify
  4. resolve中,指定lottie-web resolve到’../node_modules/lottie-web/build/player/lottie.min.js’,使用压缩过的版本

大致像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module.exports = {
entry: {
// ...
lottie: ['lottie-web'],
// ...
},
// ...
resolve: {
alias: {
// ...
'lottie-web': path.join(__dirname, '../node_modules/lottie-web/build/player/lottie.min.js')
}
},
// ...
optimization: {
splitChunks: {
cacheGroups: {
lottie: {
chunks: 'initial',
name: 'lottie',
test: 'lottie',
enforce: true
}
}
},
minimizer: [
new UglifyJsPlugin({
exclude: /lottie/,
})
]
}
};

结果:
问题解决。

Android机型下rem适配不准的问题

参考 https://www.jianshu.com/p/14f6ce51a75f

通过比较document.documentElement.style.fontSizewindow.getComputedStyle(document.documentElement)['font-size'],假设前者是a,后者是b,a * a / b计算得到和设计一致的尺寸。

3D旋转效果

利用CSS中的backface-visibility: hidden;属性,实现在transform: rotateY(180deg)时,页面翻转到不可见区域。

egret学习

场景:H5小游戏开发

投放场景:各种小游戏平台,也可以打包为Android、iOS、Windows Phone应用发布,甚至直接web访问H5页面

开发语言:TypeScript

开发方式:

  • 类Java的代码组织方式,MVC分离项目代码,M和C开发体验类似“用JavaScript写Java项目”。在View部分开发体验类似于用canvas API写页面结构
  • 类Android的resource管理方式(定义json文件描述资源组和路径对应),在代码中用API动态分组或逐个load资源
  • 单一入口,流程上在stage加载完成后,load资源(同时给出loading页面),之后执行游戏逻辑
  • 使用dispatchEvent实现组件间的信息交流

项目结构

入口文件为index.html。在其中引入manifest.json。读入所需的库文件后,根据DOM容器的data-*属性确定项目配置,以及项目入口*.ts(一般是Main.ts)。之后打包编译到bin-debug

业务逻辑放在/src下,资源文件放在/resources中,资源文件用类似于Android的形式进行存取管理。

视图

Displayable元素可以添加到容器中显示。包含下面基类。

  • displayableContainer 视图元素容器
    • stage
    • scrollView
    • sprite
  • bitmap
  • bitmapText
  • textField
  • movieClip
  • shape

movieClip表示逐帧动画。生成方法如下:

  1. RES.getRes获取资源
  2. 使用factory方法构造movieClipData
  3. 使用movieClipData构造movieClip

简单动画用tween来实现。

发布

  • egret publish或run build。发布H5,runtime版本
  • 对应平台support工具,如Android、iOS、微信小程序

不过在最新的egret launcher下,项目本身已经提供的发布到原生的快捷入口,参考官方解释

难点

和React如何结合开发?

View层通过canvas、WebGL实现,不适合和React结合。

部署方式如何结合在App里

小游戏可以发布到HTML5平台,之后类似老的webview页面开发方式,部署到离线包平台或在线页面即可。

SSO实现方案

SSO - Single Sign On 单一站点登录。由一个站点的登录状态实现关联网站免登录。

背景

由sso.xxx.com记录用户登录态,其他需要使用同一登录态的网站需要同步该域名下的登录态cookie到自己的独立域名下。

实际场景

一般公司内部的网站或ToC的集团网页间都有SSO控制,任意访问一个清除了所有cookie网页,观察network中开头的302报文即可发现实现SSO过程中的各跳转逻辑。

实际步骤因实现而异:

  1. (转让控制权)访问目标网页,302到SSO的跳转特定页面,如jump.sso.xxx.com
  2. (写入cookie)302回目标网页的特定页面,如sso.mysite.com。该域名CNAME到sso.xxx.com的服务器
  3. (写入cookie)sso.mysite.com写入cookie到自己的同域名下,再次302到目标网页,完成SSO过程

或者

  1. 同上
  2. (写入cookie)jump.sso.xxx.com做cookie的检查确认,通过url的方式写入回调的user session,再302回mysite.com。
  3. (写入cookie)mysite.com的后台对应路由根据URL里的回调写入cookie,302到目标页面

在写入cookie到新域名过程中,可以有不同的实现方式。

原理

第一步302到sso.xxx.com的时候已经可以带上xxx.com的cookie了,但是由于浏览器安全限制,并不能直接set cookie到独立域名下。需要再次302回原始域名,CNAME到sso的服务器,实现set cookie到独立域名。

为了保证安全性,CNAME到sso的sso.mysite.com所传递的参数需要有安全机制保证。如时间戳、秘钥等保证请求的完整性。避免中间人伪造域名下的请求。同时,链接本身也应有时效性,在超过时间范围失效,避免拦截链接,实现钓鱼网站获取sso.xxx.com的登录态。

具体步骤:

  1. 302到jump.sso.xxx.com后,进行权限检查判断域名是否允许同步,匹配SSO的cookie域名下的cookie取交集,得到需要同步的cookie。
  2. 通过以上两步后,302到sso.mysite.com,url中带上cookie和安全相关的参数
  3. 根据安全参数校验、target是否允许同步,决定返回403还是302。
  4. 通过校验后,同步登录态cookie,302到目标网页

清除登录态时,如何做到相关域名的同时清除,还需要额外设计。

当然,如果sso只在内网使用,在jump.sso.xxx.com做完安全验证后,通过url将结果交由sso.mysite.com设置登录态Cookie,要更为简洁。

git branch rename

如果分支在远端也有的话,工作需要分为本地和远端两部分。

  1. 重命名本地分支
  • 如果就在该分支
    1
    git branch -m new-name
  • 如果在其他分支
    1
    git branch -m old-name new-name
  1. 删除原分支,推送新分支
    1
    git push origin :old-name new-name
  2. 重置upstream设置
    1
    git push origin -u new-name

webpack无痛mock方案

使用webpack-api-mocker实现,对比axios-mock-adapter和其余方案有几个优势:

  • mock部分代码和业务代码分离开,让网络请求部分代码(/apis)有清晰的逻辑,不混杂业务无关内容
  • 热更新,保存即生效
  • 本地dev环境无痛切换到production环境,无需修改任何代码
  • 基于webpack-dev-server,和整个项目耦合,无需本地起服务
    本地开发时,配置webpack.dev.config.js,在devServer部分的配置中加入apiMocker即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const apiMocker = require("webpack-api-mocker");
// ...
devServer: {
// ...
before(app) {
apiMocker(app, path.resolve('./mock/index.js'))
}
}
对应的路径下,写入mock数据和路径即可,可以灵活组织各模块的mock数据:
const proxy = {
'GET /user/info': {
"code": 200,
"message": "success",
"data": {
// your mock data
}
},
'POST /user/update': {
"code": 200,
"message": "success",
"data": null
}
}

module.exports = proxy;

更多使用,参考webpack-api-mocker文档。

webpack配置使用es6语法

如今现代的前端开发早已采用全es6的语法书写,然而webpack的配置文件需要通过node解析执行,一般还使用es5的语法书写。在需要使用importexport,数组、对象解构等最新特性时就很蛋疼。

比如在最近的开发中,使用webpack-api-mocker时,希望拆分不同领域的接口到不同文件,最后通过对象结构的方式聚合在mocker的入口文件中。使用es5的语法就很麻烦。

实际上,让webpack使用babel解析配置文件分两步即可:

  1. yarn add -D babel-register,让webpack能够使用babel-loader转译配置文件
  2. 修改配置文件后缀为,webpack.config.babel.js,webpack会使用.js前的字符串作为loader

之后就可以愉快地使用es6语法写配置文件了。

autoprefixer remove -webkit-box-orient解决方案

autoprefixer是postcss的插件,会根据browser list,删除一些autodated的样式,其中就包括-webkit-box-orient这个用于hack实现多行省略号的CSS样式。

几种方法:

  • 设置autoprefixer,{remove: false},保留autodated的样式规则
  • 添加flexbox 2009老旧浏览器到broswer list中
  • 如下,通过注释临时disable autoprefixer
1
2
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;