背景
看到这篇文章 https://mp.weixin.qq.com/s/0q0E3fIxdii5e-AgjXskdA 发现活动这边基本上也是重复代码率很高,例如 React, React-DOM, encrypt-fetch 这几个包能占到每次活动 js 的 80%文件体积。
将这份代码放到通用库中,从缓存或者离线包中获取,这样每次上线就可以打包非常小体积的代码上线。
静态部署相关
部署 id = 项目 id + 环境 id
形如 xxxx/appcore-react16.js 的 CDN 地址,其中 5fc64a46358dbb5df667b1d0 是项目 id 大家都知道,但是后面的 5fcee95c3d3224c86b199944 其实是环境地址,同一个环境也是不会变的。
一开始我以为这个是版本 id,每次发包都会改变,但实际上不会。而且这个普通的包和离线包都是如此,离线包后缀会带 _0,这也是预留字段,目前也是不会变的。
期间还踩了个坑:webpack 5 + webpack cli 4.2.0 在跑 webpack –env.id xxx 的时候就会报错 Unknown argument: –env,仿佛不支持 –env.id 这种写法,于是降级到 webpack 4 + webpack cli 3 跑通(还把 wepback 5 下的 target: [‘web’, ‘es5’] 写法改回了 target: ‘web’ 终于发布成功)。
离线包的 url
顺带说下,走离线包的 url 测试环境是 mpcdn.xxx、线上环境是 s7/s8.xxx,且目录一定要是 public 下。
客户端存储
另外客户端离线包用来保存区分的是时候也不是只按照项目 id 存的,而是按照项目 id+环境 id 的完整形式存的。所以同一环境的离线包就算更新了,对应的 cdn 地址也不会变。
离线包相关
CDN 与强缓存
强缓存的优先级要高于离线包,CDN 文件都是走的强缓存,也就是说离线包只能优化第一次访问的速度,从第二次开始都是走的强缓存。
客户端支持
目前感觉走缓存的体验效果良好,同时把通用库做成离线包,增加了第一次体验质量。
使用
1.通过 webpack 插件引入脚本:
1 | const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin'); |
注 1:千万不要用 async,加载时会报错,可以用 defer
注 2:直接用 script 标签用离线包可能在替换时出现问题,建议用 webpack 插件的方式引入
2.在 webpack 中配置:
1 | { |
之后就能正常使用啦,import ‘react’ 的时候就相当于从 window.React 中获取。
版本
目前根据 React 版本分为两个 cdn 地址:
React 16:xxxx/appcore-react16.js?v=0
React 17:xxxx/appcore-react17.js?v=0
这边带v=0是为了方便之后强制更新版本, 因为重新部署不会使得离线包升级
打包内容
React 16 之后依赖集合类型 Map、Set 和 requestAnimationFrame,为了支持老设备使用了全局的 polyfill。
polyfill
React 在低版本手机可能有兼容性问题,要主动打 polyfill。
1 | import 'core-js/es/map'; |