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

news2024/9/23 9:33:12

Image

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 添加生成脚本
    • 跨平台注意事项
    • 小程序预览事项
    • 参考示例
    • Show time

对编译时原子化CSS框架的思考

笔者对目前市面上,一些流行的 编译时 动态生成css的解决方案还算有一点研究,比如 tailwindcssunocss,( windicss已死),又或者是 CSS-in-JS 思想下的 Linaria。

注意关键词 编译时(build time) 不是 runtime,所以不包括众多运行时 CSS-in-JS libs 或者是 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-morphts-patternts-evaluator 来评估和解析的所有 [jt]x? 文件内容,同时也会把 vue / svelte 文件转化成 tsx 进行提取。真是太酷了!

另外一个部分,是它的js运行时和智能提示部分代码,也是通过 panda codegen 生成到我们项目里的,这会导致在配置上稍稍复杂一点,比如要额外配置 aliastsconfig.json 等等。

总结

2CSS-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.tspandacss 的配置文件,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.jsonscripts 块中:

{
  "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;

配置好了之后,此时 pandacssh5 平台已经生效了,你可以 npm run dev:h5h5 平台初步使用了,但是为了开发体验,我们还有一些优化项要做。

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 rollbackcss 方法进行回滚到最原始适配 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 查看我的名片。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/814707.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hbase pe 压测 OOM问题解决

说明&#xff1a;本人使用CDH虚拟机搭建了Hbase集群&#xff0c;但是在压测的时发现线程多个的时候直接回OOM,记录一下 执行命令 hbase pe --nomapred --oneContrue --tablerw_test_1 --rows1000 --valueSize100 --compressSNAPPY --presplit10 --autoFlushtrue randomWrite …

SDXL 1.0 介绍和优缺点总结

2023年7月26日:Stability. AI 发布SDXL 1.0&#xff0c;这是对其生成模型的又一次重大更新&#xff0c;带来了突破性的变化。 SDXL 1.0包括两种不同的模型: sdxml -base-1.0:生成1024 x 1024图像的基本文本到图像模型。基本模型使用OpenCLIP-ViT/G和CLIP-ViT/L进行文本编码。…

详解c++继承与多继承

目录 &#x1f684;什么是继承&#x1f689;继承的概念&#x1f683;继承的定义 &#x1f687;继承基类成员访问方式的变化&#x1f686;基类和派生类对象赋值转换&#x1f690;继承时的作用域&#x1f697;派生类的默认成员函数&#x1f693;继承、友元、静态成员&#x1f69a…

运维级影像归档与通信系统(PACS)源码

运维级医院PACS系统源码&#xff0c;带演示&#xff0c;带使用手册和操作说明书 &#xff0c;带三维重建与还原功能&#xff0c;开发环境&#xff1a;VC MSSQL。 一、影像归档与通信系统&#xff08;PACS&#xff09;概述 PACS影像归档与通信系统”( Picture Archiving and C…

小型双轮差速底盘灭火功能的实现

1. 功能说明 灭火机器人是一种特殊的机器人&#xff0c;专门用于进行火灾扑救和灭火任务。它们通常具备以下功能和特点&#xff1a; ① 火灾侦测&#xff1a;灭火机器人配备了各种传感器和探测设备&#xff0c;可以检测烟雾、温度升高等火灾迹象。 ② 火灾扑救&#xff1a;灭火…

cadence virtuoso layout MOS串联线在layout中合并(merge)掉

如图&#xff0c;net10合并掉 解决办法&#xff1a; shiftE&#xff0c;取消勾选Abut server&#xff0c;save

第六章应用层

1.应用层概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分。 早期基于文本的应用(电子邮件、远程登录、文件传输、新闻组) 20世纪90年代将因特网带入千家万户的万维网www 当今流行的即时通信…

彻底解决IDEA输出中文乱码问题

本文一共有3种方法&#xff0c;针对的情况是输出中文乱码问题 问题描述 无法正确输出中文字符&#xff1a;&#xff08;请正确分辨自己是哪一种乱码问题&#xff01;&#xff09; 解决方法 1、最容易想到 File -> Settings -> File Encodings下设置编码格式为UTF-8…

安卓:JzvdStd——网络视频播放器

目录 一、JzvdStd介绍 JzvdStd的特点和功能&#xff1a; JzvdStd常用方法&#xff1a; 二、JzvdStd使用 1、补充知识&#xff1a; 例子&#xff1a; MainActivity &#xff1a; VideoPageAdapter &#xff1a; activity_main&#xff1a; video_page&#xff1a; …

如何在C#中处理空值

在任何编程语言中开发应用程序时&#xff0c;经常会遇到空异常或空引用异常。空指针或空引用是指不引用有效的内存位置或对象的指针。这是一个困扰程序员已经很久的问题&#xff0c;自从程序员开始编写程序以来。空值是一个特殊的值&#xff0c;表示没有有效值可用。当将空值赋…

hbuilderx主题色分享-github风格

效果 步骤 hbuilderx总共有三种主题&#xff0c;绿柔主题Default,酷黑主题Monokai,雅黑主题Atom One Dark,修改主题色是基于三种主题之一的&#xff0c;不能直接创建一个新主题&#xff0c;比如下方配置是基于Atom One Dark(对象名为[Atom One Dark])&#xff0c;则当前hbuild…

【Sortable】前端拖拽库 | 简洁 | 实用 | 强大

前言 官网 - http://www.sortablejs.com/index.html中文文档 - https://www.itxst.com/sortablejs/neuinffi.htmlnpm - https://www.npmjs.com/package/sortablejs npm下载 npm i sortablejsumd <script src"https://www.itxst.com/package/sortable/sortable.min.js…

达梦数据库食用说明

环境准备 达梦数据库支持Windows、Linux和Unix操作系统&#xff0c;达梦正式版需要授权&#xff0c;我们学习的话选择试用即可&#xff0c;在本机使用VM安装一个Centos&#xff0c;然后去达梦官网下载适用自己平台的安装包。 本教程使用的是VM安装的centos7.9。所以选择X86架…

伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应付单新增(应付单(伯俊)(KD 应付单)ok)

伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应付单新增(应付单(伯俊)&#xff08;KD 应付单&#xff09;ok) 数据源系统:伯俊ERP 伯俊科技&#xff0c;依托在企业信息化建设方面的领先技术与实践积累&#xff0c;致力于帮助企业实现全渠道一盘货。伯俊提供数字经营的咨询…

经典文献阅读之--NoPe-NeRF(优化无位姿先验的神经辐射场)

0. 简介 在没有预先计算相机姿态的情况下训练神经辐射场&#xff08;NeRF&#xff09;是具有挑战性的。最近在这个方向上的进展表明&#xff0c;在前向场景中可以联合优化NeRF和相机姿态。然而&#xff0c;这些方法在剧烈相机运动时仍然面临困难。我们通过引入无畸变单目深度先…

SZMMSZ5246BT1G 稳压二极管(齐纳Zener二极管)的特性和应用详解

关于齐纳二极管&#xff1a;是一种特殊的二极管&#xff0c;也被称为肖特基二极管&#xff08;Schottky Diode&#xff09;。它是由金属与半导体材料的结合构成的。与普通的PN结二极管不同&#xff0c;齐纳二极管的结由金属与半导体材料组成&#xff0c;而不是两个不同的半导体…

菜单 vue3 h函数创建组件

目录 index/.vue <template><div class"menu_table"><divclass"table_row"v-for"(item, index) in menuList"click"item.disabled ! true && itemClick(item)"><!-- :style"{border-top:item.line…

一文了解DMX512透明屏的工作原理

DMX512透明屏是一种新型的显示屏技术&#xff0c;它采用了DMX512控制协议&#xff0c;可以实现透明显示效果。 DMX512是一种数字控制协议&#xff0c;常用于舞台灯光和音响设备的控制&#xff0c;通过DMX512控制器可以实现对透明屏的亮度、颜色、动画等参数的调节。 DMX512透明…

泛微最新漏洞汇总

泛微 e-cology 前台SQL注入漏洞 app.name"泛微 e-cology 9.0 OA" 验证poc: POST /weaver/weaver.file.FileDownloadForOutDoc HTTP/1.1 Host: {{Hostname}} Accept: */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9 Connection: close …

探索前端图片如何携带token进行验证

前言 图片在前端开发中扮演了重要的角色&#xff0c;它们不仅仅是美观的元素&#xff0c;还可以传递信息和激发用户的兴趣。随着应用场景的增多&#xff0c;前端开发人员就需要在图片加载过程中携带验证的信息。如 token&#xff0c;用于身份验证、权限控制等方面。通过在图片的…