一个混淆Tailwindcss类的工具

news2024/7/6 19:59:37

Image

一个混淆Tailwindcss类的工具

  • 一个混淆Tailwindcss类的工具
    • 前言
    • 方案的寻找
    • 如何实现混淆
    • 如何使用
      • 1. 安装这2个包
      • 2. 执行一下脚本
      • 3. 添加 prepare script 在你的 package.json
      • 4. 注册这个插件
        • webpack
        • vite
      • 效果预览
    • 核心原理
      • SSR 场景思考和解决方案
    • 错误与反馈

前言

tailwindcss 是一个原子类优先的css框架,现如今非常的流行。它语义化的 类名 能够让前端开发人员直观地对元素的样式进行编写和维护。

然而这种直观性,有时候也会带来一定的困扰。有时候我们不想让用户或者外界的开发人员也能直观的观测到所有元素的样式,

比如我们访问 https://tailwindcss.com , 然后打开开发者工具,检查元素。瞬间,页面上那些元素的排版和样式都能猜测出来,甚至都不需要看右边的 style 面板。

所以,出于让其他人在生产环境中无法直观的看出一个元素的样式,我们就需要对 tailwindcss 生成的原子类进行混淆。

方案的寻找

起初我在网络上寻找解决方案时,我找到了 mangle-css-class-webpack-plugin,这是一个 webpack 插件,专门用来压缩和混淆在 html,js,css 里的类名。

然而我在尝试使用它去混淆 tailwindcss 的类名的时候遇到了困难,一开始我无法准确的传入 classNameRegExp 和其他的参数,这导致我 webpack build 之后的结果,要不就完全是错的,要不就完全达不到预期,后来找了一些 issue 看似解决了这个问题,但是可维护性极差。

另外直接通过正则去修改 js 里的字面量的方式,很容易造成小范围误伤,导致整个项目运行不起来报错。

于是我开始思考,有没有什么方式能够精准的实现混淆 tailwindcss 的类名,以下是我的解决方案。

如何实现混淆

首先为了更加精确的进行匹配,我决定从以下角度去实现

  1. 为了精确找到 tailwindcss 生成了多少的类,我需要在运行时,得到 tailwindcss 的上下文。
  2. 放弃正则匹配,全面使用AST,即使用 prase5 来解析转化 html ,使用 babel 来解析转化 js,使用 postcss 来解析转化 css

为了达到第一点,我设计编写了一个npm包: tailwindcss-patch 使用它来获取到所有生成的 class 集合。

为了达到第二点,我编写了一个unplugin插件: unplugin-tailwindcss-mangle, 这是一个 webpack/vite 插件,用来在打包的时候,修改html,js,css混淆所有的类名。

如何使用

那么如何使用它们呢?很简单只要以下几步:

1. 安装这2个包

<npm|yarn|pnpm> i -D unplugin-tailwindcss-mangle tailwindcss-patch

2. 执行一下脚本

npx tw-patch

3. 添加 prepare script 在你的 package.json

  "scripts": {
    "prepare": "tw-patch"
  },

4. 注册这个插件

这里以 webpackvite 为例

webpack

// esm
import { webpackPlugin as utwm } from 'unplugin-tailwindcss-mangle'
// or cjs
const { webpackPlugin: utwm } = require('unplugin-tailwindcss-mangle')
// use this webpack plugin
// for example next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  webpack: (config) => {
    config.plugins.push(utwm())
    return config
  }
}

module.exports = nextConfig

这里我以 nextjs 为例,当然 vue.config.js 那些也都是类似的,把 utwm() 注册进 webpack 然后打包构建,预览即可看到效果。

vite

// for example: vue vite project
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { vitePlugin as utwm } from 'unplugin-tailwindcss-mangle'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), utwm()]
})

然后执行脚本:

# generate bundle
<npm|yarn|pnpm> run build
# preview
<npm|yarn|pnpm> run preview

效果预览

<!-- before -->
<div class="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex"></div>
<!-- after -->
<div class="tw-g tw-h tw-i tw-d tw-e tw-j tw-k tw-l"></div>

当然,你也可以自定义生成的类名,查看文档获取更多的配置项。

核心原理

上面简单的介绍了一下使用方式,下面才是正文,当然只是用就没必要看这一段了。

思路上,首先我们仿照 tailwindcss 的文件提取方式,先从源文件(content 配置的 glob 表达式 覆盖到的文件),比如 html,js,ts,jsx,tsx,vue,svelte…这类的文件中,读取内容生成 class,然后,利用 html astbabel ast 转义,把转义结果保存起来,最后交给 postcss 对所有的 css 选择器进行转义。

一图以蔽之:

Image

当然有些聪明的小伙伴,可能会产生疑问,为什么图上的 css 被处理了 2 次呢?

因为 css 有可能是变成一段 inlinejs,这种情况下,没有 css 文件产生,只有一个 js 块,里面包含着样式内容,这时候使用插入 loader 的方案可以解决。而最后获取生成器内的map进行转化和比较,算是一道双保险。

SSR 场景思考和解决方案

然而上述方案还有一些缺陷,尤其是在 ssr 场景下

我们都知道 react/vue ssr 模式下面会打 2类包,一类是服务端,一类是客户端的。

这意味着我们在运行构建任务时,我们的插件会被跑 2 次。

然而这里面存在一个严重的问题,我们能得到 tailwindcss 上下文的时机,是在客户端的 postcss 被触发后,然而服务端打包时,并不会触发 postcss 的处理。假如 server 的包,在 client 的包之前打好了,这时候运行项目。由于 clinet 包被混淆了,server包没有被混淆,这时候就会出现 2边的dom 属性不对等的问题,从而造成客户端水合激活报错。遇到这种情况,我们应该怎么办呢?

实际上很简单,既然插件在同一个 nodejs 进程里,被运行了 2 次,那么我们大可创建一块缓存区域,当发现 server 端的打包先被激活的时候,我们就缓存住它的运行结果,就是那些 Webpack Source 或者 Vite Chunk/Asset 对象。等到客户端获取上下文,处理好了之后,再把它们去取出来,使用上下文对 server bundle 进行处理混淆,然后再对之前 server 已经输出的结果进行覆写,这样不就可以了吗?

所以这个方案,我用在了 nextjs/nuxtjs 里。

错误与反馈

如果你在使用过程中,遇到了问题或者疑问,或者想进行交流,欢迎提 issue 给我.

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

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

相关文章

Ant Design Pro---【03 UMI中使用MOCK】

Mock 数据 Mock 数据是前端开发过程中必不可少的一环&#xff0c;是分离前后端开发的关键链路。通过预先跟服务器端约定好的接口&#xff0c;模拟请求数据甚至逻辑&#xff0c;能够让前端开发独立自主&#xff0c;不会被服务端的开发所阻塞。 约定式 Mock 文件 Umi 约定 /mo…

SpringData-Redis配置及常用操作

文章目录 1.引入依赖2.yml配置文件3.设置Redis序列化4.使用教程5.操作String数据类型6.操作Hash数据类型7.操作Set数据类型8.操作List数据类型9.操作Sorted Set 数据类型 1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId…

史上最烂 spring web 原理分析

盗引下篇spring web spring web、spring web 与 tomcat、映射器与适配器、参数解析器与类型转换器、返回值处理器与消息转换器、异常处理器、ControllerAdvice、spring web 工作流程。 版本 jdk&#xff1a;8spring&#xff1a;5.3.20spring boot&#xff1a;2.7.0 1 spring…

关键词高亮显示浏览器 Edge 插件开发 源码

插件功能 将网页中的关键词高亮显示 项目结构 $ tree . |-- content # 注入到网页中的 js 与 css | |-- content.css | -- content.js |-- icons # 插件用到的图标 | |-- icon128.png | |-- icon16.png | |-- icon32.png | -- icon48.png |-- manifest.json # …

Python+Yolov5电梯口跌倒识别

程序示例精选 PythonYolov5电梯口跌倒识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonYolov5电梯口跌倒识别>>编写代码&#xff0c;代码整洁&#xff0c;规则&#x…

【AGC】applinking服务接入产生崩溃问题

【关键字】 AGC、applinking、崩溃 【问题描述】 开发者反馈在应用中集成了AGC的applinking服务&#xff0c;在打开app时遇到了一些问题。具体如下所述&#xff1a; 在接入app linking后&#xff0c;从浏览器中访问短链接&#xff0c;能正常唤起app, 但app启动后就崩溃了&am…

UAD142A01 3BHE012551R0001使用以太网交叉电缆,您也可以直接连接。

​ UAD142A01 3BHE012551R0001使用以太网交叉电缆&#xff0c;您也可以直接连接。 如何将 MicroLogix PLC 连接到计算机并将程序下载到 MicroLogix 1100 MicroLogix PLC由美国罗克韦尔自动化旗下知名工业自动化厂商Allen-Bradley设计。MicroLogix 1100 主要用于小型工业。我们在…

【视频解读】动手学深度学习V2_02深度学习介绍

1.AI地图 人工智能的地图&#xff0c;x轴是不同模式&#xff0c;由符号学到概率模型 到机器学习&#xff0c;Y轴是我想做的东西&#xff0c;最底下的是感知&#xff0c;我得了解这是什么东西&#xff0c;然后做推理&#xff0c;形成自己的知识&#xff0c;最后做规划。最底层的…

07-Vue技术栈之(组件之间的通信方式)

目录 1、组件的自定义事件1.1 绑定自定义事件&#xff1a;1.1.1 第一种方式1.1.2 第二种方式1.1.3 自定义事件只触发一次 1.2 解绑自定义事件1.3绑定原生DOM事件1.4 总结 2、全局事件总线&#xff08;GlobalEventBus&#xff09;2.1 应用全局事件总线 3、 消息订阅与发布&#…

SwiftUI 极简实现文本摆动弹性动画

概览 SwiftUI 为我们来了界面设计和调试上的便利&#xff0c;只需几行代码我们就能实现一个不错的文本动画效果&#xff1a; 如上图所示&#xff0c;我们在 SwiftUI 中基本还没发力&#xff0c;就实现了文本摆动弹性动画。 这究竟是怎么做到的呢&#xff1f; 无需等待&#…

英文论文(sci)解读复现【NO.7】基于注意机制的改进YOLOv5s目标检测算法

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

Loadrunner性能测试(一)

备注&#xff1a;电脑最好安装有IE浏览器 一、下载安装包 链接&#xff1a;https://pan.baidu.com/s/1f5Sw0QK5zrLCU1EbN01evg?pwdbite 提取码&#xff1a;bite 包含的文件有&#xff1a; 二、安装loadrunner 注意&#xff0c;以下教程仅展示需要特别注意的步骤&#x…

PHP学习笔记第一天

前言 作者简介&#xff1a;不知名白帽&#xff0c;网络安全学习者。 博客主页&#xff1a;不知名白帽的博客_CSDN博客-网络安全,CTF,内网渗透领域博主 网络安全交流社区&#xff1a;https://bbs.csdn.net/forums/angluoanquan 目录 PHP语法 基本的PHP语法 PHP的数据类型 PH…

Kubernetes 集群中某个节点出现 Error querying BIRD: unable to connect to BIRDv4 socket

1. 问题描述 Readiness probe failed: calico/node is not ready: BIRD is not ready: Error querying BIRD: unable to connect to BIRDv4 socket: dial unix /var/run/calico/bird.ctl: connect: connection refusedReadiness probe failed: 2023-05-04 22:13:23.706 [INFO]…

LiangGaRy-学习笔记-Day10

1、知识回顾 1.1、rpm依赖报错问题 rpm安装的时候&#xff0c;会有依赖报错rpm安装httpd服务&#xff0c;体现报错 #rpm安装httpd [rootNode1 ~]# rpm -ivh /mnt/cdrom/Packages/httpd-2.4.6-88.el7.centos.x86_64.rpm warning: /mnt/cdrom/Packages/httpd-2.4.6-88.el7.ce…

自己组装的电脑怎么用U盘安装系统操作教学

自己组装的电脑怎么用U盘安装系统操作教学分享。有的用户使用台式机的时候&#xff0c;会自己去进行硬件的组装&#xff0c;但是这样的电脑在安装好了之后&#xff0c;里面还没有系统&#xff0c;需要进行安装。如果你不知道怎么去安装&#xff0c;可以来看看以下的操作方法。 …

HummerRisk 使用教程:源码检测

HummerRisk 是开源的云原生安全平台&#xff0c;以非侵入的方式解决云原生环境的安全和治理问题。核心能力包括混合云的安全治理和云原生安全检测。 本文将介绍HummerRisk中「源码检测模块」的功能&#xff0c;包括如何配置项目源码&#xff0c;以及使用源码检测规则进行安全检…

香港top5功能完善炒期货投资app软件排名(最新评测)

选择一款合适的炒期货投资软件对于投资者来说至关重要。考虑软件稳定、交易流畅度、交易品种、数据可靠性、而且还要考虑费用等多方面因素。 首先&#xff0c;软件的稳定性很重要。选用稳定性高的软件可以避免如断电、手机或电脑死机等突发状况&#xff0c;保证交易安全顺畅。…

FreeRTOS 低功耗 Tickless 模式

文章目录 一、低功耗模式1. 睡眠(Sleep)模式2. 停止(Stop)模式3. 待机(Standby)模式 二、Tickless 模式详解1. 如何降低功耗&#xff1f;2. Tickless 具体实现 一、低功耗模式 STM32 本身就支持低功耗模式&#xff0c;有三种低功耗模式&#xff1a; ● 睡眠(Sleep)模式。 ● 停…

5_服务编排_docker-compose

服务编排之Docker Compose 微服务架构的应用系统中一般包含若干个微服务&#xff0c;每个微服务一般都会部署多个实例&#xff0c;如果每个微服务都要手动启停&#xff0c;维护的工作量会很大。 要从Dockerfile build image 或者去dockerhub拉取image 要创建多个container 要…