APP内嵌H5开发记录
几个关键点points
- 线上的东西不要去堆了,要改就改到两个新的配置,应该是渐进式的去增加,而不是breaking的先把它改掉 - 尤其是路径那种的,去请求配置化的
- 但凡是没有use xxx包裹住的代码,都放入到外层或者用ref带上,
不然每次render 就生成一次
首先,这个东西是h5嵌入的,但是实际上是在app内打开,因为有一些经常会变动的东西会更改,尤其是现实的销售活动,再去发版本可谓是相当麻烦,而h5就很好的解决了这点,
其实还是有点区别,但是我作为前端以前没做过h5的我硬是没看出来过……
1. 通信的技术方案
通信是使用的js bridge,公司内统一封装了具体的包,适配flutter
通常情况下是可以直接调用一些方法,如直接closeWebView,或者open WebView(open的话可以直接打开,自带侧边栏)purchase之类的也可以去移动端接收
css 相关
1.vw自动转换
postcss-px-to-viewport 用这个包,所有css里写的px自动会变成vw,这非常好!不要用tailwind来了(这可比tw要好多了!!!!)
安装了 stylelint,那么说 style得驼峰命名
但是问题是,内联样式的px无法被转换。写到css里就好了(这时候就很需要cursor 来帮我写类名了,一个个写好累啊啊)
2. 一个很丑的按钮按下去效果,
需要给全部的数据都设置取消这个值。-webkit-tap-highlight-color: transparent;
其他那几个none其实没用,不然就会有个按下效果,很丑
*,
*::after,
*::before {
outline: none;
-webkit-tap-highlight-color: transparent;
user-select: none;
&:active {
outline: none;
}
}
3. header边距(又踩坑)
最开始,想用 —safe-area-inset-top来做,后面发现, 这个东西在ios非常好,但是安卓没有,后面反正也就是用了客户端传递过来的值
最开始觉得
CSS提供了env()和constant()函数来获取安全区域的边距。
需要使用safe-area-inset-top这个环境变量。类似的还有safe-area-inset-bottom、safe-area-inset-left和safe-area-inset-right,分别对应四个方向的安全区域距离。
但是这个后面发现ios有效,安卓无效,后面还是拿的客户端传递过来的值。 -- 使用了post css px to view,所以不能行内设置而是要给根元素设置上一个变量,去注入的话就能实现转换。
解决方案:
document.documentElement.style.setProperty(
'--safe-area-top',
(Number(searchParams.get('statusBarHeight')) || '0') + 'px',
);
这个东西直接改了根元素的值,
var(—safe-area) 直接用
最开始查到还有一个解决方案是给: root 打变量,后面发现,得是:root而不是#root,:root默认是到全局的那么全局的东西都有而#root都是局部
不要管这个了, #root反而不对。不如直接用。
打包相关
1. 环境变量
本来说环境变量都是默认给放到 根目录底下的。不然就要额外指定(这个 和 next还不太一样感觉,next是直接 在env/下面的就能读到,
此外,next的前缀是NEXT
NEXT_PUBLIC_APP_ENV=beta
rs build的默认就是 PUBLIC,不过也可以自定义。
默认情况下,publicVars是以PUBLIC_ 为前缀的变量

不过,也可以不用这么搞,现在项目里,只是用PUBLIC_ENV=dev 来作为区分的,
注意后面的—mode
"dev": "PUBLIC_ENV=local rsbuild dev --mode development",
"build:dev": "PUBLIC_ENV=dev rsbuild build --mode production",
"build:prod": "PUBLIC_ENV=prod rsbuild build --mode production",
这个 public env 才是真的在local里用到的,dev 是运行 build是开发
后面那个参数 看下面 其实可以这样的⬇️
不同模式对比
| 模式 | 典型特征 | 建议场景 |
|---|---|---|
| development | 1. 保留调试信息 2. 不压缩代码 3. 启用热更新 |
本地开发 |
| production | 1. 代码压缩 2. 移除日志 3. 启用 Tree-Shaking |
生产环境构建 |
| test | 1. 保留部分调试信息 2. 可能包含测试专用配置 |
测试环境构建 |
2. 打包平铺
这个由于没有安装路由(这是为什么),所以entry是自己指定的,嗯,只是读取了文件下pages下面,而且没有/components
const getEntries = async () => {
const entryFiles = await glob('./src/pages/**/index.{ts,tsx,js,jsx}');
const entries = Object.fromEntries(
entryFiles
.filter((path) => !path.includes('/components'))
.map((file) => {
const entryName = path.basename(path.dirname(file));
return [entryName, `./${file}`];
}),
);
return entries;
};
还有就是打包之后测试环境访问不到,
排查是不是nginx问题? 本地看看— 发现是结构问题,这时候

要加上 outputStructure: 'nested', 才能平铺
export default defineConfig({
html: {
template: './index.html',
templateParameters: {
process,
},
outputStructure: 'nested',
},
- 路由
因为没安装,所以得。手动写,而注意底下是一个* ,两个**会匹配任意,是不对的。
const getEntries = async () => {
const entryFiles = await glob('./src/pages/*/index.{ts,tsx,js,jsx}');
const entries = Object.fromEntries(
entryFiles.map((file) => {
const entryName = path.basename(path.dirname(file));
return [entryName, `./${file}`];
}),
);
return entries;
};
3. 打点
如果你们app内就在用神策,天然就会自动打通 文档在这里⬇️
https://manual.sensorsdata.cn/sa/docs/tech_sdk_client_link/v0300
需要传入到同一个url里,开启
app_js_bridge: true,
神策的使用方法
进入【数据管理】- 【实时导入数据查询】
然后查询那里,搜索,查询就行了,ctrl f有重新写过,反正搜出来的是最新的。嗯好,然后命中了会高亮好像仅此而已
这个开始刷新。。。反正okok就这样
swiper js
有个很狗屎的问题。10个已购买列表,他
Charles抓包 代理到本地
这样调试非常好!!!!直接在手机上用ok。注意charlse只是试用版说是30分钟内自动关闭,但是这个没什么。还是很好用的
在ios端很流畅可以开启代理。
首先ios端的wifi这里,设置成手动 这个写到csdn上去了先这样
其他经验
其他
其实经常变动的东西就用图片。。。。。用图片没什么不好,因为一大块都是这样,经常变动,emmmm.
加上没有交互。。没有交互所以没必要
search params这个 ,进入页面的时候就能拿到,所以说他不需要在use effect里。直接写就行,不然要在use effect的话多一次渲染
上滑自动隐藏,下滑显示,不是 bro 这个ai写的嗨挺好的
哎呀,踏着怎么写的,我怎么写不出来, 就是lastScrollY得换成ref,因为并没有在视图里用到。
const [isHidden, setIsHidden] = useState(false);
const [lastScrollY, setLastScrollY] = useState(0);
useEffect(() => {
const handleScroll = () => {
const currentScrollY = window.scrollY;
// 滚动方向判断
if (currentScrollY > lastScrollY && currentScrollY > 50) {
setIsHidden(true); // 向下滑动隐藏
} else if (currentScrollY < lastScrollY) {
setIsHidden(false); // 向上滑动显示
}
setLastScrollY(currentScrollY);
};
// 添加防抖优化
const debouncedScroll = () => {
window.requestAnimationFrame(handleScroll);
};
window.addEventListener('scroll', debouncedScroll, { passive: true });
return () => window.removeEventListener('scroll', debouncedScroll);
}, [lastScrollY]);
字体
需要先预加载才能再使用,注意font-family之间要有逗号
font-family: Outfit, sans-serif;

浙公网安备 33010602011771号