clsx源码阅读分析

clsx源码

版本 2.1.1

一个处理类名的函数。

地址:https://github.com/lukeed/clsx/blob/master/src/index.js

源码文件index.js

文件 src/index.js

//src/index.js
function toVal(mix) {var k,y,str = "";// 判断参数min类型, 字符串或数值类型 直接 拼接if (typeof mix === "string" || typeof mix === "number") {str += mix;} else if (typeof mix === "object") {// 数组类型if (Array.isArray(mix)) {var len = mix.length;for (k = 0; k < len; k++) {// 为真 才递归调用toVal函数处理if (mix[k]) {if ((y = toVal(mix[k]))) {str && (str += " ");str += y;}}}} else {// 对象类型for (y in mix) {// 为真 才拼接if (mix[y]) {str && (str += " ");str += y;}}}}return str;
}export function clsx() {var i = 0,tmp,x,str = "",len = arguments.length;// 参数遍历for (; i < len; i++) {if ((tmp = arguments[i])) {// 处理参数, 最后都是拼接成字符串if ((x = toVal(tmp))) {str && (str += " ");str += x;}}}return str;
}export default clsx;

源码文件lite.js

只处理字符串。

//src/lite.js
export function clsx() {// 定义声明变量var i = 0,tmp,str = "",len = arguments.length;// 参数遍历for (; i < len; i++) {if ((tmp = arguments[i])) {// 当参数为字符串时处理,拼接字符串if (typeof tmp === "string") {str += (str && " ") + tmp;}}}return str;
}export default clsx;

使用

import clsx from "clsx";
// or
import { clsx } from "clsx";// Strings (variadic)
clsx("foo", true && "bar", "baz");
//=> 'foo bar baz'// Objects
clsx({ foo: true, bar: false, baz: isTrue() });
//=> 'foo baz'// Objects (variadic)
clsx({ foo: true }, { bar: false }, null, { "--foobar": "hello" });
//=> 'foo --foobar'// Arrays
clsx(["foo", 0, false, "bar"]);
//=> 'foo bar'// Arrays (variadic)
clsx(["foo"], ["", 0, false, "bar"], [["baz", [["hello"], "there"]]]);
//=> 'foo bar baz hello there'// Kitchen sink (with nesting)
clsx("foo",[1 && "bar", { baz: false, bat: null }, ["hello", ["world"]]],"cya"
);
//=> 'foo bar hello world cya'

打包分析

{"name": "clsx","version": "2.1.1","repository": "lukeed/clsx","description": "A tiny (239B) utility for constructing className strings conditionally.","module": "dist/clsx.mjs","unpkg": "dist/clsx.min.js","main": "dist/clsx.js","types": "clsx.d.ts","license": "MIT","exports": {//条件加载,利用.这个别名".": {"import": {"types": "./clsx.d.mts",//default条件指定其他情况的入口(即 ES6 的入口)。"default": "./dist/clsx.mjs"},"default": {"types": "./clsx.d.ts","default": "./dist/clsx.js"}},"./lite": {"import": {"types": "./clsx.d.mts","default": "./dist/lite.mjs"},"default": {"types": "./clsx.d.ts","default": "./dist/lite.js"}}},"author": {"name": "Luke Edwards","email": "luke.edwards05@gmail.com","url": "https://lukeed.com"},"engines": {"node": ">=6"},"scripts": {"build": "node bin","test": "uvu -r esm test"},"files": ["*.d.mts", "*.d.ts", "dist"],"keywords": ["classes", "classname", "classnames"],"devDependencies": {"esm": "3.2.25","terser": "4.8.0","uvu": "0.5.4"//UVU是Node.js和浏览器的一个非常快速和轻量级的测试运行器}
}

main属性

定义这个 package 的入口文件位置。

在不支持 ES6 的 Nodejs 中,它指向的就是CommonJs模块系统的入口位置。

在 Nodejs 支持 ES6 的版本中,只要显示定义 "type": "module",那么它指向的就是 ESM 模块系统的入口位置

exports属性

export的使用:https://es6.ruanyifeng.com/#docs/module-loader#package-json-%E7%9A%84-exports-%E5%AD%97%E6%AE%B5

exports 字段可以配置不同环境对应的模块入口文件,并且当他存在时,它的优先级最高,当package.json文件中存在 exports 字段,设置的 main 字段会失效。exports 字段的优先级高于 main 字段。

示例

利用.这个别名,可以为 ES6 模块和 CommonJS 指定不同的入口。

{"type": "module","exports": {".": {"require": "./main.cjs","default": "./main.js"}}
}

上面代码中,别名.require条件指定require()命令的入口文件(即 CommonJS 的入口),default条件指定其他情况的入口(即 ES6 的入口)。

执行打包

命令


{"scripts": {"build": "node bin","test": "uvu -r esm test"},
}

bin/index.js文件

// @ts-check
const fs = require("fs");
// zlib 模块提供了使用 Gzip、Deflate/Inflate、以及 Brotli 实现的压缩功能。
const zlib = require("zlib");// 一个用于ES6+的JavaScript管理器/压缩器工具包。
const { minify } = require("terser");
const pkg = require("../package.json");// file 文件的路径 , source文件的内容
function write(file, source) {let isModule = !source.startsWith("!function");// 一个可配置的高级函数async minify(code, options),它将以可配置的方式执行所有缩小阶段。默认情况下,minify()将启用compress和mangle。let result = minify(source, {module: isModule,compress: true,});
// console.log(result.code);  // minified output: function add(n,d){return n+d}
// console.log(result.map);  // source mapif (result.code) {fs.writeFileSync(file, result.code);// zlib.gzipSync压缩数据块   byteLength获取字节大小let size = zlib.gzipSync(result.code).byteLength;console.log('~> "%s" (%d b)', file, size);} else {console.error('!! "%s" ::', file, result.error);}
}// file文件名称,entry文件别名
function bundle(file, entry) {// 判断是否存在文件夹dis,不存在则创建fs.existsSync("dist") || fs.mkdirSync("dist");//pkg 即package.json默认导出的对象let output = pkg.exports[entry];// 读取文件let input = fs.readFileSync(file, "utf8");// copy for ESM filewrite(output.import.default, input);// transform ESM -> CJS exportswrite(output.default.default,input.replace("export function", "function").replace("export default clsx;","module.exports = clsx;\n" + "module.exports.clsx = clsx;"));if (entry === ".") {// transform ESM -> UMD exportsinput = input.replace("export function", "function").replace("export default clsx;", "return clsx.clsx=clsx, clsx;");// 写入文件write(pkg.unpkg,'!function(global,factory){"object"==typeof exports&&"undefined"!=typeof module?module.exports=factory():"function"==typeof define&&define.amd?define(factory):global.clsx=factory()}(this,function(){' +input +"});");}
}bundle("src/index.js", ".");bundle("src/lite.js", "./lite");

package.josn文件中的exports配置信息


{"exports": {".": {"import": {"types": "./clsx.d.mts","default": "./dist/clsx.mjs"},"default": {"types": "./clsx.d.ts","default": "./dist/clsx.js"}},"./lite": {"import": {"types": "./clsx.d.mts","default": "./dist/lite.mjs"},"default": {"types": "./clsx.d.ts","default": "./dist/lite.js"}}}
}

npm install过程

首先安装的依赖都会存放在根目录的node_modules,默认采用扁平化的方式安装,并且排序规则.bin第一个,然后@系列,再然后按照首字母排序abcd等,并且使用的算法是广度优先遍历,在遍历依赖树时,npm会首先处理项目根目录下的依赖,然后逐层处理每个依赖包的依赖,直到所有依赖都被处理完毕。在处理每个依赖时,npm会检查该依赖的版本号是否符合依赖树中其他依赖的版本要求,如果不符合,则会尝试安装适合的版本。

扁平化的理想状态

APP————A模块(c1.0)APP————B模块(c1.0)

安装某个二级模块时,若发现第一层级有相同名称,相同版本的模块,便直接复用那个模块

因为A模块下的C模块被安装到了第一级,这使得B模块能够复用处在同一级下;且名称,版本,均相同的C模块

扁平化的非理想状态

APP————A模块(c1.0)APP————B模块(c2.0)

因为B和A所要求的依赖模块不同,(B下要求是v2.0的C,A下要求是v1.0的C )所以B不能像2中那样复用A下的C v1.0模块 所以如果这种情况还是会出现模块冗余的情况,他就会给B继续搞一层node_modules,就是非扁平化了。

uvu插件

UVU是Node.js和浏览器的一个非常快速和轻量级的测试运行器.

# via `uvu` cli, for all `/tests/**` files
$ uvu -r esm tests# via `node` directly, for file isolation
$ node -r esm tests/demo.js

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

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

相关文章

C++中的左值、右值介绍

C中的左值、右值介绍 在C中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是非常重要的概念&#xff0c;尤其是在C11及以后的版本中引入的右值引用&#xff08;rvalue reference&#xff09;和移动语义&#xff08;Move Semantics&#…

Ubuntu系统复制文件到共享文件夹出错

1、问题描述 Ubuntu系统复制文件到共享文件夹时&#xff0c;出现拼接文件时出错&#xff1a;输入/输出错误。 使用cp命令&#xff1a; cp -Rf XXX YYY 也是出错&#xff1a; cp: 写入 xxx 出错: 输入/输出错误 2、查看磁盘空间 查看磁盘空间&#xff0c;显示空间还有剩余…

安乃达:看不懂的募资

不好玩啊&#xff0c;高标接连被S&#xff0c;市场激进资金找到了新股作为抱团方向。 首日大涨超100%&#xff0c;两日涨幅133%&#xff0c;今天果不其然被电风扇刮走了&#xff0c;今天我们聊聊新加入A股大本营的公司——安乃达。 首先&#xff0c;安乃达是国内直驱轮毂电机头…

Golang栈空间管理

分段栈 在Go1.3之前&#xff0c;所有goroutine在初始化时都会分配一块固定大小的内存空间。 在固定8KB或者满足其他条件下&#xff0c;会在全局的栈缓存链表中找到空闲的内存块作为新goroutine的栈空间返回其余情况&#xff0c;会在堆上申请一块合适的内存 所有栈空间会以链…

hot100 | 六、矩阵

1-leetcode73. 矩阵置零 注意&#xff1a; 注意第一行和第一列如果检查到了0&#xff0c;直接break也可以使用HashSet方法&#xff0c;直接把0的数字对应的横纵坐标放在两个不同的HashSet当中&#xff0c;最后如果HashSet中Contain了当前数字下标中的一个&#xff0c;就直接给…

Amazon SQS应用场景及Python实现案例

1. SQS简介 Amazon Simple Queue Service (SQS) 是一种完全托管的消息队列服务,可以帮助解耦和扩展微服务、分布式系统和无服务器应用程序。SQS 可以在分布式应用程序组件之间传输任何数量的消息,而无需丢失消息或要求其他服务始终可用。 2. SQS应用场景 SQS 在许多场景中…

零基础学python(一)

1. 匿名函数 常规函数&#xff1a; def fun(x, y):return x y 匿名函数&#xff1a; # lambda 空格后面是函数入参&#xff0c;冒号后面写函数体/函数逻辑 a lambda x,y: x y print(a(2,3)) 匿名函数/lambda函数的最大优点就是快速定义函数&#xff0c;使代码更精简。 …

Redis 的缓存淘汰策略

Redis 作为一个高性能的内存数据库&#xff0c;提供了多种缓存淘汰策略&#xff08;也称为过期策略或驱逐策略&#xff09;&#xff0c;用于管理内存使用。当 Redis 达到其内存限制时&#xff0c;系统会根据配置的策略删除一些数据&#xff0c;以释放内存空间。以下是 Redis 支…

【数据结构】(6.3)堆的应用——堆排序(C语言)

系列文章目录 文章目录 系列文章目录前言1. 堆排序的基础知识2. 堆排序详解2.1 堆排序整体思路2.2 思路详解2.2.1 建堆2.2.2 堆排序完整代码2.2.3 输出数据 3. 时间复杂度分析 前言 1. 堆排序的基础知识 堆排序&#xff08;Heap Sort&#xff09;就是对直接选择排序的一种改进…

04通俗理解自注意力机制(self-attention)

04浅谈自注意力机制&#xff08;self-attention&#xff09; 1. 基本概念 注意力机制 是Transformer模型的核心。它的作用是让模型能够“关注”输入数据的不同部分&#xff0c;而不是一次只处理一个词。比如&#xff0c;当模型在处理一句话时&#xff0c;它可以同时考虑句子中…

2024攻防演练:亚信安全新一代WAF,关键时刻守护先锋

实网攻防 网络安全如同一面坚固的盾牌&#xff0c;保护着我们的信息资产免受无孔不入的威胁。而其中&#xff0c;WAF就像网络安全的守门员&#xff0c;关键时刻挺身而出&#xff0c;为您的企业筑起一道坚实的防线。 攻防不对等 防守方实时应答压力山大 在攻防对抗中&#xf…

day04-matplotlib入门

matplotlib Matplotlib 提供了一个套面向绘图对象编程的 API接口 是一款用于数据可视化的 Python 软件包&#xff0c;支持跨平台运行 它能够根据 NumPyndarray 数组来绘制 2D(3D) 图像&#xff0c;它使用简单、代码清晰易懂&#xff0c;深受广大技术爱好 者喜爱。 实列&…

Django学习第五天

启动项目命令 python manage.py runserver 图像验证码生成随机字母或者数字 import random from PIL import Image, ImageDraw, ImageFont, ImageFilterdef check_code(width120, height40, char_length5, font_fileZixunHappyBold.ttf, font_size28):code []img Image.new…

liunx离线安装Firefox

在Linux系统中离线安装Firefox浏览器&#xff0c;您需要先从Mozilla的官方网站下载Firefox的安装包&#xff0c;然后通过终端进行安装。以下是详细的步骤&#xff1a; 准备工作 下载Firefox安装包&#xff1a; 首先&#xff0c;在一台可以上网的电脑上访问Firefox官方下载页面…

Spring框架Mvc(2)

1.传递数组 代码示例 结果 2.集合参数存储并进行存储类似集合类 代码示例 postman进行测试 &#xff0c;测试结果 3.用Json来对其进行数据的传递 &#xff08;1&#xff09;Json是一个经常使用的用来表示对象的字符串 &#xff08;2&#xff09;Json字符串在字符串和对象…

实证Stata代码命令汇总

实证Stata代码命令汇总 更新时间:2024.4 实证Stata代码命令汇总 (一) 数据导入和管理 1. 数据导入 2. 数据导出

图文识别0难度上手~基于飞浆对pdf简易ocr并转txt

前言 本篇pdf适用windows对视觉识别0基础的的纯小白用户。大佬请绕道~~ 注意&#xff1a; 本项目pdf的ocr对于表格、画图文字&#xff0c;水印等干扰没做任何处理&#xff0c;因此希望各位使用该功能的pdf尽量不要含有这些干扰项&#xff0c;以免影响翻译效果。 流程 1.构建…

【c语言】轻松拿捏自定义类型

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C语言 目录 前言 一、结构体 1.结构体类型的定义和使用 1.1 结构体类型声明 1.2 结构体变量的创建和初始化 1.3 结构体变量成员的访问 1.4 结构体的特殊声…

MobPush iOS端 扩展业务功能设置

1、扩展业务说明 MobPush提供的扩展业务功能为&#xff1a; &#xff08;1&#xff09;按照地域提供更为精准的推送&#xff1b; &#xff08;2&#xff09;实现网络链路的选择与优化、检测并实现与特定区域相关的服务&#xff1b; &#xff08;3&#xff09;生成用户画像&…

三万字带你一遍跑通uer

三万字带你一遍跑通uer 参考文档 今天给大家介绍个非常强大的项目uer&#xff0c;集成了许多可以做自然语言的东西&#xff0c;效果的话也非常好&#xff0c;很适合企业级的应用&#xff01; 1. 先将项目uer从github拉取下来&#xff08;zip或git都ok&#xff09; 2. 用pycha…