Panda 编译时原子化 CSS-in-JS 框架的跨平台方案

Panda 编译时原子化 CSS-in-JS 框架的跨平台方案
- Panda 编译时原子化 CSS-in-JS 框架的跨平台方案
- 对编译时原子化CSS框架的思考
- 编译时 CSS-in-JS 方案对比
- Linaria
- Pandacss
- 总结
- weapp-pandacss 介绍
- 快速开始
- pandacss 安装和配置
- 0. 安装和初始化 pandacss
- 1. 配置 postcss
- 2. 检查你的 panda.config.ts
- 3. 修改 package.json 脚本
- 4. 全局 css 注册 pandacss
- 5. 配置的优化与别名
- weapp-pandacss 配置
- 0. 回到 postcss 进行注册
- 1. 回到 package.json 添加生成脚本
- pandacss 安装和配置
- 跨平台注意事项
- 小程序预览事项
- 参考示例
- Show time
对编译时原子化CSS框架的思考
笔者对目前市面上,一些流行的 编译时 动态生成css的解决方案还算有一点研究,比如 tailwindcss,unocss,( windicss已死),又或者是 CSS-in-JS 思想下的 Linaria。
注意关键词
编译时(build time)不是runtime,所以不包括众多运行时CSS-in-JSlibs 或者是twind这种方案
其中之前也写了 weapp-tailwindcss 这样一个开源项目,来和大家探讨 tailwindcss 的跨平台方案。
虽然大部分情况下 tailwindcss 已经非常强了,我们可以通过 plugin / preset / @apply 等等功能,为自己的项目提炼出大量的样式,缩短我们的类名,提升我们的效率,但是 tailwindcss 有个问题,就是 js 天然不亲和。
是的,回想我们在使用 tailwindcss 的时候,要不就是直接在模板文件里写原子类,要不就是在类 js 文件里操纵原子类的字面量,要不就是在 css 去 @apply/theme 来提取或组合多个原子类。
这看似灵活的同时,却给我们加了诸多限制。试想这样一个场景,一个现成使用 tailwindcss 的项目, 有一天突然要去改所有原子类的前缀(prefix),那这个改动将是一个浩劫!因为 prefix 这个配置项,会影响到整个 tailwindcss 上下文提取器的正则匹配方式,这意味着所有使用原子类的标签都要改!
而 CSS-in-JS 方案就不需要,因为类名是计算出来的,这显然更加灵活。
编译时 CSS-in-JS 方案对比
这里重点介绍 2 种方案,一种是 Linaria,另外一种是最近新出的 Pandacss
Pandacss的作者Segun Adebayo是一个尼日利亚(Nigeria)黑人小哥,也是Chakra UI的作者,真是太强了!
Linaria
一想到 linaria 我就想到一个字,牛逼!,两个字,太酷啦!,它对 babel ast 的处理简直是教科书级别的出神入化,令人着迷。
是的,它值得这么高的评价,只要你看过它 babel 插件的实现。这里我们不深入探讨,你只要知道它会去计算 css 模板字符串里的值和表达式(eval流程),并把里面的计算结果提取成一个个 css 节点,然后在原先的 js文件中 css 模板字符串处留下对应的 css selector 的值。
不过这种方式生成的 class 选择器名称,虽然可以自定义,但是不能很好的代表生效样式的内容。因为一个 linaria css template string 只对应一个 css 节点,所以说它不够原子化。
这点不如 tailwindcss 直观,例如,你一瞅见类名是 relative flex items-start ,你甚至都不需要打开 Chrome devtool 就知道里面的样式是什么样的。
Pandacss
而 pandacss 就是另外一种方案,它是原子化的,这意味着一个css()方法会生成多个 css节点,还有就是它和 [jt]sx? 文件相结合的写法灵活而又令人印象深刻。
另外它的实现其实很像 tailwindcss。
首先它们核心用法都是一个 postcss plugin,其次,它们都是通过分析我们源码的内容,去进行提炼和生成css原子类的。
不过不同的是,相比于 tailwindcss 这种基于文件内容进行 正则(regex) 匹配提取 token 的方式。pandacss 的提取器更为复杂。
它直接通过 ts-morph,ts-pattern,ts-evaluator 来评估和解析的所有 [jt]x? 文件内容,同时也会把 vue / svelte 文件转化成 tsx 进行提取。真是太酷了!
另外一个部分,是它的js运行时和智能提示部分代码,也是通过 panda codegen 生成到我们项目里的,这会导致在配置上稍稍复杂一点,比如要额外配置 alias 和 tsconfig.json 等等。
总结
这 2 种 CSS-in-JS 方案各有它们出彩之处。目前我倾向于 pandacss,只因 linaria 实在是太 hack 了! 它的 css模板字符串,有自己的语法,有自己的词法分析器,就像在创造一个 Domain Specific Language,真是太复杂了!但是它非常值得研究!
另外 pandacss 一个优势就是,它不会去修改我们的源代码,这带来了更少的出错的可能性,而本人在使用 linaria 的时候,配置稍复杂就有 fatal 的可能,这就需要我们花更多的时间去修复它。
它们各自有各自独一无二的优势,相互无法完全替代,看它们各自的源代码,就像在紫禁之巅欣赏叶孤城与西门吹雪的决战,令人赏心悦目的同时,受益匪浅!
所以我推荐 pandacss 给大家,另外 panda 也是我国的国宝,这预示着中国又赢了!
weapp-pandacss 介绍
接下来进入正题,我在使用了一段时间后的 pandacss 后,想在写 taro react 项目的时候也去使用它,于是我就写了这个 weapp-pandacss。
让我们快速来看看怎么使用它吧!
快速开始
pandacss 安装和配置
0. 安装和初始化 pandacss
首先我们需要把 @pandacss/dev 这些都安装和配置好,这里我们以 tarojs 项目为例:
npm install -D @pandacss/dev weapp-pandacss postcss # 或者 yarn / pnpm
npx panda init
此时会在当前目录生成一个 panda.config.ts 和一个包含大量文件的 styled-system。
panda.config.ts是pandacss的配置文件,styled-system文件夹里的是pandacss的运行时js。
把 styled-system 加入我们的 .gitignore 中去。
# .gitignore
+ styled-system
1. 配置 postcss
接着在根目录里,添加一个 postcss.config.cjs 文件,写入以下代码注册 pandacss:
module.exports = {plugins: {'@pandacss/dev/postcss': {}}
}
2. 检查你的 panda.config.ts
生成的配置文件大概长下面这样,尤其注意 include 是用来告诉 pandacss 从哪些文件中提取原子类的,所以这个配置一定要准确
import { defineConfig } from "@pandacss/dev"export default defineConfig({// 小程序不需要preflight: process.env.TARO_ENV === 'h5',// ⚠️注意这里,假如你使用 vue,记得把 vue 文件格式包括进来!!!include: ["./src/**/*.{js,jsx,ts,tsx}"],exclude: [],theme: {extend: {}},outdir: "styled-system",
})
3. 修改 package.json 脚本
然后,我们添加下方 prepare 脚本在我们的 package.json 的 scripts 块中:
{"scripts": {
+ "prepare": "panda codegen",}
}
这样我们每次重新 npm i / yarn /pnpm i 的时候,都会执行这个方法,重新生成 styled-system,当然你也可以直接通过 npm run prepare 直接执行这个脚本。
4. 全局 css 注册 pandacss
然后在我们的全局样式文件 src/app.scss 中注册 pandacss:
@layer reset, base, tokens, recipes, utilities;
配置好了之后,此时 pandacss 在 h5 平台已经生效了,你可以 npm run dev:h5 在 h5 平台初步使用了,但是为了开发体验,我们还有一些优化项要做。
5. 配置的优化与别名
来到根目录的 tsconfig.json 添加:
{"compilerOptions": {"paths": {"@/*": ["src/*"],
+ "styled-system/*": [
+ "styled-system/*"
+ ]}},"include": ["./src","./types","./config",
+ "styled-system"],
}
接着来到 config/index.ts 添加 alias(参考链接):
import path from 'path'{alias: {'styled-system': path.resolve(__dirname, '..', 'styled-system')},
}
这样我们就不需要使用相对路径来使用 pandacss 了,同时 ts 智能提示也有了,你可以这样使用它:
import { View, Text } from "@tarojs/components";
import { css } from "styled-system/css";const styles = css({bg: "yellow.200",rounded: "9999px",fontSize: "90px",p: "10px 15px",color: "pink.500",
});export default function Index() {return (<View className={styles}><Text>Hello world!</Text></View>);
}
此部分参考的官方链接 https://panda-css.com/docs/installation/postcss
接下来进入 weapp-pandacss 的插件配置,不用担心,相比前面那些繁琐的步骤,这个可简单多了。
weapp-pandacss 配置
记得安装好
weapp-pandacss!
0. 回到 postcss 进行注册
回到项目根目录的 postcss.config.cjs 注册 weapp-pandacss,添加以下配置:
module.exports = {plugins: {'@pandacss/dev/postcss': {},
+ 'weapp-pandacss/postcss': {}}
}
1. 回到 package.json 添加生成脚本
然后去 package.json 你添加 prepare 脚本的地方,加点代码
{"scripts": {
- "prepare": "panda codegen",
+ "prepare": "panda codegen && weapp-panda codegen",}
}
注意这里必须用
&&而不能用&,&任务执行会并行不会等待,而&&会等待前一个执行完成再执行后一条命令
然后,你再手动执行一下
npm run prepare
来重新生成 styled-system, 此时你会发现 pandacss 的命令行输出中多了 2 行:
✔️ `src/styled-system/css`: the css function to author styles
✔️ `src/styled-system/tokens`: the css variables and js function to query your tokens
✔️ `src/styled-system/patterns`: functions to implement apply common layout patterns
✔️ `src/styled-system/jsx`: styled jsx elements for react
+ ✔️ `src/styled-system/weapp-panda`: the core escape function for weapp
+ ✔️ `src/styled-system/helpers.mjs`: inject escape function into helpers
这代表着小程序相关的转义逻辑已经被注入进去,此时 panda css 生成的类就兼容小程序平台啦,是不是很简单?
当然为了防止你配置失败,我也给出了参考项目: taro-react-pandacss-template 方便进行排查纠错。
跨平台注意事项
你可能同时开发 小程序 和 h5 平台,但是你发现使用 weapp-pandacss 之后,h5 平台似乎就不行了?
这时候你可以这样配置:
process.env.TARO_ENV === 'h5' 的时候,不去加载 weapp-pandacss/postcss (根据环境变量动态加载 postcss 插件)
同时你也可以执行 weapp-panda rollback 把 css 方法进行回滚到最原始适配 h5 平台的状态。
当然你恢复到小程序版本也只需要执行 weapp-panda codegen 就会重新注入了。
小程序预览事项
当小程序预览时会出现 Error: 非法的文件,错误信息:invalid file: pages/index/index.js, 565:24, SyntaxError: Unexpected token . if (variants[key]?.[value]) 错误。
这是因为 panda 生成的文件 cva.mjs 使用了 Optional chaining (?.)语法,这个语法小程序原生不支持,这时候可以开启勾选 将JS编译成ES5 功能再进行预览,或者使用 babel 预先进行处理再上传预览。
参考示例
taro-react-pandacss-template
Show time
最后给自己的个人小程序打个小小的推广:
想要你的Github项目在微信内分享吗?快来试试 程序员名片 吧。
进入方式:微信内,搜索 程序员名片,快速注册后添加名片,导入 Github 项目即可。
在使用过程中,如果遇到问题,或者你有好的意见和建议,欢迎与我讨论。
Demo short link: 微信内访问 #小程序://程序员名片/c9lmHLg29GtN2PH 查看我的名片。
相关文章:
Panda 编译时原子化 CSS-in-JS 框架的跨平台方案
Panda 编译时原子化 CSS-in-JS 框架的跨平台方案 Panda 编译时原子化 CSS-in-JS 框架的跨平台方案 对编译时原子化CSS框架的思考编译时 CSS-in-JS 方案对比 LinariaPandacss总结 weapp-pandacss 介绍快速开始 pandacss 安装和配置 0. 安装和初始化 pandacss1. 配置 postcss2. …...
【图论】BFS中的最短路模型
算法提高课笔记 目录 迷宫问题题意思路代码 武士风度的牛题意思路代码 抓住那头牛题意思路代码 BFS可以解决边权为1的最短路问题,下面是三道相关例题 迷宫问题 原题链接 给定一个 nn 的二维数组,如下所示: int maze[5][5] {0, 1, 0, 0, …...
Linux Mint 21.2 ISO 镜像开放下载
导读Linux Mint 21.2 ISO 镜像于 2023 年 6 月 21 日公测,开发者在这段时间内收集并修复了用户反馈的诸多问题。 代号为“Victoria”的 Linux Mint 21.2 ISO 镜像于今天正式开放下载,新版本基于 Ubuntu 22.04 LTS,提供 Cinnamon 5.8、Xfce 4.…...
版本适配好帮手 Android SDK Upgrade Assistant / Android Studio Giraffe新功能
首先是新版本一顿下载↓: Download Android Studio & App Tools - Android Developers 在Tools中找到Android SDK Upgrade Assistant 可以在此直接查看SDK升级相关信息,不用跑到WEB端去查看了。 例如看一下之前经常要对老项目维护的android 12蓝牙…...
kafka权威指南学习以及kafka生产配置
0、kafka常用命令 Kafka是一个分布式流处理平台,它具有高度可扩展性和容错性。以下是Kafka最新版本中常用的一些命令: 创建一个主题(topic): bin/kafka-topics.sh --create --topic my-topic --partitions 3 --replic…...
自由行的一些小tips
很多很多年前,写过一些关于自由行的小攻略,关于互联网时代的自助旅游,说起来八年了,很多信息可能过期了。 前几天准备回坡,因为自己比较抠门,发现目前大陆回新加坡的机票比较贵(接近4000人民币&…...
uiautomatorViewer无法获取Android8.0手机屏幕截图的解决方案
问题描述: 做APP UI自动化的时候,会碰到用uiautomatorViewer在Android 8.0及以上版本的手机上,无法获取到手机屏幕截图,无法获取元素定位信息的问题,会有以下的报 在低版本的Android手机上,则没有这个问题…...
使用LangChain构建问答聊天机器人案例实战(三)
使用LangChain构建问答聊天机器人案例实战 LangChain开发全流程剖析 接下来,我们再回到“get_prompt()”方法。在这个方法中,有系统提示词(system prompts)和用户提示词(user prompts),这是从相应的文件中读取的,从“system.prompt”文件中读取系统提示词(system_tem…...
在windows上安装minio
1、下载windows版的minio: https://dl.min.io/server/minio/release/windows-amd64/minio.exe 2、在指定位置创建一个名为minio文件夹,然后再把下载好的文件丢进去: 3、右键打开命令行窗口,然后执行如下命令:(在minio.…...
22. 数据库的隔离级别和锁机制
文章目录 数据库的隔离级别和锁机制一、数据库隔离级别1. 隔离级别说明2. 如何选择隔离级别3. 查询当前客户端隔离级别的命令.4. 修改隔离的命令 二、数据库中的锁1. 共享锁、排他锁2. 死锁3. 行级锁、表级锁 三、解决更新丢失问题1. 解决方案2. 乐观锁、悲观锁3. 乐观锁、悲观…...
【题解】[ABC312E] Tangency of Cuboids(adhoc)
【题解】[ABC312E] Tangency of Cuboids 少见的 at 评分 \(2000\) 的 ABC E 题,非常巧妙的一道题。 特别鸣谢:dbxxx 给我讲解了他的完整思路。 题目链接 ABC312E - Tangency of Cuboids 题意概述 给定三维空间中的 \(n\) 个长方体,每个长方体…...
k8s服务发现之使用 HostAliases 向 Pod /etc/hosts 文件添加条目
某些情况下,DNS 或者其他的域名解析方法可能不太适用,您需要配置 /etc/hosts 文件,在Linux下是比较容易做到的,在 Kubernetes 中,可以通过 Pod 定义中的 hostAliases 字段向 Pod 的 /etc/hosts 添加条目。 适用其他方…...
python中有哪些比较运算符
目录 python中有哪些比较运算符 使用比较运算符需要注意什么 总结 python中有哪些比较运算符 在Python中,有以下比较运算符可以用于比较两个值之间的关系: 1. 等于 ():检查两个值是否相等。 x y 2. 不等于 (!):检查两个…...
Python网络编程详解:Socket套接字的使用与开发
Python网络编程详解:Socket套接字的使用与开发 1. 引言 网络编程是现代应用开发中不可或缺的一部分。通过网络编程,我们可以实现不同设备之间的通信和数据交换,为用户提供更加丰富的服务和体验。Python作为一种简洁而强大的编程语言&#x…...
Appium+python自动化(二十六)- Toast提示(超详解)简介
开始今天的主题 - 获取toast提示 在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,这个和我日常生活中看到的烟花和昙花是多么的相似,那么我们该如何获取…...
SpringBoot自动装配介绍
SpringBoot是对Spring的一种扩展,其中比较重要的扩展功能就是自动装配:通过注解对常用的配置做默认配置,简化xml配置内容。本文会对Spring的自动配置的原理和部分源码进行解析,本文主要参考了Spring的官方文档。 自动装配的组件 …...
1400*D. Candy Box (easy version)(贪心)
3 10 9 Example input 3 8 1 4 8 4 5 6 3 8 16 2 1 3 3 4 3 4 4 1 3 2 2 2 4 1 1 9 2 2 4 4 4 7 7 7 7 output 题意: n个糖果,分为多个种类,要求尽可能的多选,并且使得不同种类的数量不能相同。 解析: 记录每种糖…...
设计模式-备忘录模式在Java中使用示例-象棋悔棋
场景 备忘录模式 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效 或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销(Undo)操作࿰…...
用合成数据训练托盘检测模型【机器学习】
想象一下,你是一名机器人或机器学习 (ML) 工程师,负责开发一个模型来检测托盘,以便叉车可以操纵它们。 你熟悉传统的深度学习流程,已经整理了手动标注的数据集,并且已经训练了成功的模型。 推荐:用 NSDT设…...
人性-基本归因错误
定义 基本归因谬误指出,你评价别人的一个行为时,你会高估他的内部因素——比如性格的影响,低估外在的情景之类各种复杂因素的影响。 具体表现是对自己,我们很愿意分析复杂的原因;对别人,如果他一句话说的…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
