笔记:使用 unbuild 搭建 JavaScript 构建系统笔记
jcLee95:https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343
邮箱 :291148484@163.com
简介:
本文是笔者阅读分析 elementPlus 项目时记录的。该项目用到了一个完全没有文档和资料的工具 unbuild。为了搞清楚其功能,在github上看了一下该模块的源代码并记录之。
本文地址:https://blog.csdn.net/qq_28550263/article/details/129016838
1. unbuild 简介与安装
2. unbuild 的用法
- 2.1 配置文件
build.config.ts - 2.2 pacakage.json 与 cli 用法
3. 该模块用到的一些模块
-
3.1 一款 await 的挂钩系统:hookable
- 3.1.1 安装
- 3.1.2 通过直接创建 hookable 实例使用
- 3.1.3 通过从 Hookable 扩展你的基类使用
- 3.1.4 Hookable 类的接口解析
-
3.2 轻量级文件到文件转换器:mkdist
-
3.2.1 简介与安装
-
3.2.2 mkdist 的用法
3.3 Node.js 的运行时Typescript 和 ESM 支持:jiti
- 3.3.1 简介与安装
- 3.3.2 jiti 的用法
3.4 将字节转换为人类可读的字符串:pretty-bytes
- 3.4.1 简介与安装
- 3.4.2 用法
附录
1. unbuild 简介与安装
搭建前端项目时,我们经常需要寻找一些构建工具来辅助我们自动化地进行打包和完成其它工作,如 webpack、rollup、gulp、vite 等等。对于一些功能的需求比较简单的场景,我们用不着使用 webpack 之类的重型构建工具,完全可以考虑使用一些小工具完成。本文介绍的 unbuild 就是这样一个小工具,它是一个强大的基于 rollup 的捆绑器,支持 TypeScript 并生成 commonjs 和 module 格式 + 类型声明。它能够能够自动推断 package.json 中的 build 配置和条目。
你可以通过如下方式安装到项目依赖中:
npm i unbuild -D
# 或
yarn add unbuild -D
# 或
pnpm i unbuild -D
2. unbuild 的用法
2.1 配置文件 build.config.ts
unbuild CLI 基于配置文件 build.config.ts 工作,你应该手动在项目根目录中创建它,以便于执行脚本的时候被 unbuild 所找到。一个该文件的实例为:
import { defineBuildConfig } from 'unbuild'export default defineBuildConfig({// 如果没有提供entries,将从package.json中自动推断出entries: [// 指定源文件入口,默认值为 './src/index''./src/index',// mkdist builder 传输文件到文件,保持原始源结构{builder: 'mkdist',input: './src/package/components/',outDir: './build/components'},],// 指定输出目录,默认为 'dist'outDir: 'build',// 指定是否生成 .d.ts 声明文件declaration: true,
})
其中 defineBuildConfig 传入的对象可以配置以下内容:
| 配置项 | 类型 | 描述 |
|---|---|---|
| rootDir | string | 指定根目录起始位置 |
| entries | BuildEntry[]; | 指定源文件入口,默认值为 './src/index' |
| clean | boolean | 输出前是否清空输出目录 |
| declaration | boolean | 指定是否生成 .d.ts 声明文件 |
| outDir | string | 指定输出目录,默认为 'dist' |
| stub | boolean | 跳过 stub 的剩余部分 |
| externals | string[] | 是否所有依赖项作为外部项添加(dependencies、peerDependencies) |
| dependencies | string[] | 从pkg推断的依赖关系 |
| peerDependencies | string[] | 从pkg推断的依赖关系 |
| devDependencies | string[] | 从pkg推断的依赖关系 |
| alias | { [find: string]: string;} | 由 unbuild 传给 rollup 的 alias 配置项 |
| replace | { [find: string]: string;} | 由 unbuild 传给 rollup 的 replace 配置项 |
| rollup | RollupBuildOptions | 由 unbuild 传给 rollup 的构建选项 |
| hooks | Partial<BuildHooks> | |
| preset | string | BuildPreset |
2.2 pacakage.json 与 cli 用法
{"main": "./dist/index.cjs","module": "./dist/index.mjs","types": "./dist/index.d.ts","scripts": {"build": "unbuild","dev": "pnpm run stub","stub": "unbuild --stub"},"devDependencies": {"unbuild": "^0.7.4"}
}
3. 该模块用到的一些模块
这个部分是在分析 unbuild 模块源码中用到的一些库。
3.1 一款 await 的挂钩系统:hookable
3.1.1 简介与安装
该模块用于管理注册和调用钩子,你可以通过以下方式进行安装:
npm install hookable
# or
yarn add hookable
# or
pnpm install hookable
3.1.2 通过直接创建 hookable 实例使用
import { createHooks } from 'hookable'// 创建一个 hookable 实例
const hooks = createHooks()// 挂上 'hello'
hooks.hook('hello', () => { console.log('Hello World' )})// 调用 'hello' 钩子
hooks.callHook('hello')
3.1.3 通过从 Hookable 扩展你的基类使用
import { Hookable } from 'hookable'export default class FooLib extends Hookable {constructor() {// 调用父类进行初始化super()// 用自定义 logger 初始化可挂钩// super(consola)}async someFunction() {// 按顺序调用并等待“hook1”挂钩(如果有)await this.callHook('hook1')}
}
在插件中,注册任意钩子:
const lib = new FooLib()// 注册“hook2”的处理程序
lib.hook('hook2', async () => { /* ... */ })// 一次注册多个处理程序
lib.addHooks({hook1: async () => { /* ... */ },hook2: [ /* 也可以是一个数组 */ ]
})
3.1.4 Hookable 类的接口解析
3.2 轻量级文件到文件转换器:mkdist
3.2.1 简介与安装
Bundling 库有时候不是最佳的选择,因为通过捆绑传输丢失现代语法,也让我们丢失原有的文件结构,也有时通过将css提取到全局dist(vue) 而丢失关键css。
即使不使用,依赖项也将总是从 bundle 绑包中导入(第二个捆绑步骤可能会解决这个问题,但这通常不会发生在开发中和有副作用的依赖项中)。
虽然有像 tsc 和 @babel/cli 这样的工具,但它们大多专注于传输文件,而不是保持源代码级别的质量。此外,它们缺乏对处理自定义扩展的支持,如。vue和复制assets
mkdist可以:
- 复制所有的 assets;
- 支持 Vue 单文件组件;
- 通过 esbuild 实现快速和最小的转换;
- .为
.ts,.js和.vue文件生成d.ts类型声明文件
你可以通过以下方式进行安装:
npm install mkdist
# or
yarn add mkdist
# or
pnpm install mkdist
3.2.2 mkdist 的用法
CLI 的语法格式
mkdist [rootDir] [--src=src] [--dist=dist] [--pattern=glob [--pattern=more-glob]] [--format=cjs|esm] [-d|--declaration] [--ext=mjs|js|ts]
3.3 Node.js 的运行时 Typescript 和 ESM 支持:jiti
3.3.1 简介与安装
jiti 是一款Node.js 的运行时 Typescript 和 ESM 支持模块,也就是说它可以让 Nodejs 运行时运行 Typescript 和 ESM 代码,该模块可以:
- 无缝typescript和ESM语法支持;
- ESM和CommonJS之间的无缝互操作性;
- 替换 require 的同步API;
- 超级苗条和零依赖;
- 智能语法检测,避免额外的转换;
- CommonJS缓存集成;
- 文件系统传输文件硬缓存;
- V8编译缓存;
- 自定义解析别名
你可以通过如下之一的方式进行安装:
npm install jiti
# or
yarn add jiti
# or
pnpm install jiti
3.3.2 jiti 的用法
1. 编程用法
const jiti = require("jiti")(__filename);jiti("./path/to/file.ts");
2. 命令行用法
若是全局安装了 jiti ,可以直接使用 jiti 命:
jiti index.ts
若只在当前项目中安装了 jiti ,可用 npx jiti 运行脚本文件
npx jiti index.ts
3.4 将字节转换为人类可读的字符串:pretty-bytes
3.4.1 简介与安装
该模块可用于打包时在终端更好地输出文件大小,可以通过如下方式进行安装:
npm install pretty-bytes
# or
yarn add pretty-bytes
# or
pnpm install pretty-bytes
3.4.2 用法
import prettyBytes from 'pretty-bytes';prettyBytes(1337);
//=> '1.34 kB'prettyBytes(100);
//=> '100 B'// 以位为单位显示
prettyBytes(1337, {bits: true});
//=> '1.34 kbit'// 显示文件大小差异
prettyBytes(42, {signed: true});
//=> '+42 B'// 使用德语语言环境的本地化输出
prettyBytes(1337, {locale: 'de'});
//=> '1,34 kB'
附录
- BuildEntry:
declare type BuildEntry = BaseBuildEntry | RollupBuildEntry | UntypedBuildEntry | MkdistBuildEntry;
interface BaseBuildEntry {builder?: 'untyped' | 'rollup' | 'mkdist';input: string;name?: string;outDir?: string;declaration?: Boolean;
}interface UntypedBuildEntry extends BaseBuildEntry {builder: 'untyped';defaults?: Record<string, any>;
}
interface RollupBuildEntry extends BaseBuildEntry {builder: 'rollup';
}
interface MkdistBuildEntry extends BaseBuildEntry {builder: 'mkdist';format?: 'esm' | 'cjs';ext?: 'cjs' | 'mjs' | 'js' | 'ts';
}
- RollupBuildOptions:
import { RollupReplaceOptions } from '@rollup/plugin-replace';
import { RollupAliasOptions } from '@rollup/plugin-alias';
import { RollupNodeResolveOptions } from '@rollup/plugin-node-resolve';
import { RollupJsonOptions } from '@rollup/plugin-json';
import { Options as Options$1 } from 'rollup-plugin-dts';declare type RollupCommonJSOptions = Parameters<typeof commonjs>[0] & {};interface RollupBuildOptions {emitCJS?: boolean;cjsBridge?: boolean;inlineDependencies?: boolean;replace: RollupReplaceOptions | false;alias: RollupAliasOptions | false;resolve: RollupNodeResolveOptions | false;json: RollupJsonOptions | false;esbuild: Options | false;commonjs: RollupCommonJSOptions | false;dts: Options$1;
}
- BuildHooks:
import { RollupOptions, RollupBuild } from 'rollup';interface BuildHooks {'build:prepare': (ctx: BuildContext) => void | Promise<void>;'build:before': (ctx: BuildContext) => void | Promise<void>;'build:done': (ctx: BuildContext) => void | Promise<void>;'rollup:options': (ctx: BuildContext, options: RollupOptions) => void | Promise<void>;'rollup:build': (ctx: BuildContext, build: RollupBuild) => void | Promise<void>;'rollup:dts:options': (ctx: BuildContext, options: RollupOptions) => void | Promise<void>;'rollup:dts:build': (ctx: BuildContext, build: RollupBuild) => void | Promise<void>;'rollup:done': (ctx: BuildContext) => void | Promise<void>;'mkdist:entries': (ctx: BuildContext, entries: MkdistBuildEntry[]) => void | Promise<void>;'mkdist:entry:options': (ctx: BuildContext, entry: MkdistBuildEntry, options: MkdistOptions) => void | Promise<void>;'mkdist:entry:build': (ctx: BuildContext, entry: MkdistBuildEntry, output: {writtenFiles: string[];}) => void | Promise<void>;'mkdist:done': (ctx: BuildContext) => void | Promise<void>;'untyped:entries': (ctx: BuildContext, entries: UntypedBuildEntry[]) => void | Promise<void>;'untyped:entry:options': (ctx: BuildContext, entry: UntypedBuildEntry, options: any) => void | Promise<void>;'untyped:entry:schema': (ctx: BuildContext, entry: UntypedBuildEntry, schema: Schema) => void | Promise<void>;'untyped:entry:outputs': (ctx: BuildContext, entry: UntypedBuildEntry, outputs: UntypedOutputs) => void | Promise<void>;'untyped:done': (ctx: BuildContext) => void | Promise<void>;
}
interface BuildContext {options: BuildOptions;pkg: PackageJson;buildEntries: {path: string;bytes?: number;exports?: string[];chunks?: string[];}[];usedImports: Set<string>;hooks: Hookable<BuildHooks>;
}
- BuildPreset:
declare type BuildPreset = BuildConfig | (() => BuildConfig);
interface BuildConfig extends DeepPartial<Omit<BuildOptions, 'entries'>> {entries?: (BuildEntry | string)[];preset?: string | BuildPreset;hooks?: Partial<BuildHooks>;
}
相关文章:
笔记:使用 unbuild 搭建 JavaScript 构建系统笔记
使用 unbuild 搭建 JavaScript 构建系统jcLee95:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 :291148484163.com 简介: 本文是笔者阅读分析 elementPlus 项目时记录的。该项目用到了一个完全没有文档和资料的工具 unbu…...
【SpringBoot3.0源码】启动流程源码解析 •下
文章目录初始化DefaultBootstrapContext开启Headless模式获取监听器并启动封装命令行参数准备环境打印Banner创建上下文容器预初始化上下文容器刷新Spring容器打印启动时间发布事件执行特定的run方法上一篇《【SpringBoot3.0源码】启动流程源码解析 • 上》,主要讲解…...
QT(56)-动态链接库-windows-导出变量-导出类
1.导出变量 1.1不使用_declspec(dllimport) _declspec(dllexport) 使用_declspec(dllimport) _declspec(dllexport) 1.2win32 mydllwin32 myexe 1.3win32 mydllqt myexe 2.导出类 使用_declspec(dllimport) _declspec(dllexport) 2.1不用关键…...
TCP传输文件
传输文件和传输信息的区别: 传输信息,只是一条数据,传输文件是多条数据传输信息传输过去一般都会显示,传输文件一般不会显示,一般只是存放在文件中传输文件需要传输,文件大小和文件名称(不然不知…...
vue3:加载本地图片等静态资源
背景 在我们用 vue2 webpack 的时候,加载图片资源是这样用的: <img :src"require(/assets/test.png)" />这样打包后就会触发 file-loader 打包图片资源,在 dist 文件夹中就可以看到这个图片(如果图片较小会打包…...
工作记录------数据库group_concat函数长度问题
工作记录------group_concat函数长度问题 背景:页面在数据展示时,报错,错误显示:String index out of range: -1 异常信息 java.lang.StringIndexOutOfBoundsException: String index out of range: -1at java.lang.String.sub…...
Python基础语法
1 编程环境 1.1 编译环境 pycharmpython/anaconda 1.2 环境设置 File -> settings -> Project interpreter -> 1.3 Hello world 2 条件判断 2.1 例题 【题1】输入一个年份,判断是否是闰年 ①能被4整除,但不能被100整除; ②能被400整…...
windows环境下安装Nginx及常用操作命令
windows环境下安装Nginx及常用操作命令nginx基本概述基本用途nginx安装nginx基本概述 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。基本用途 nginx是一个轻量级高并发服务器,而tomcat并不是。nginx一般被用来做反向代理,将请求转发到应用…...
python excel数据处理?
前段时间做了个小项目,帮个海洋系的教授做了个数据处理的软件。基本的功能很简单,就是对Excel里面的一些数据进行过滤,统计,对多个表的内容进行合并等。之前没有处理Excel数据的经验,甚至于自己都很少用到Excel。记得《…...
Hudi-集成Flink
文章目录集成Flink环境准备sql-client方式启动sql-client插入数据查询数据更新数据流式插入code 方式环境准备代码类型映射核心参数设置去重参数并发参数压缩参数文件大小Hadoop参数内存优化读取方式流读(Streaming Query)增量读取(Increment…...
重新认识 React Hooks useContext
通常来说,React 数据的传递方式都是一层一层把资料 props 传到子层的 就算第二层(Function Component)、第三层(Button Group Compontn) 根本没有用到这个资料,但是为了传到最底层(button) ,每一层还是必须要传props // App.js const App = () => {const [dark, setDark…...
数据库(2)--加深对统计查询的理解,熟练使用聚合函数
一、内容要求 利用sql建立学生信息数据库,并定义以下基本表: 学生(学号,年龄,性别,系号) 课程(课号,课名,学分,学时) 选课࿰…...
stm32f407探索者开发板(十五)——NVIC中断优先级管理
文章目录零、前言一、NVIC中断优先级分组1.1 中断的管理方法1.2 抢占优先级&相应优先级的区别1.3 举例1.4 特别说明1.5 中断优先级分组函数二、NVIC中断优先级设置2.1 中断设置相关寄存器2.2 中断设置优先级2.2.1 中断优先级控制的寄存器组 IP[240]2.2.2 中断使能寄存器组 …...
【Azure 架构师学习笔记】-Azure Logic Apps(6)- Logic Apps调用ADF
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Logic Apps】系列。 接上文【Azure 架构师学习笔记】-Azure Logic Apps(5)- 标准和使用量类型的区别 前言 Logic Apps 和 ADF 的搭配使用是常见的组合,它们可以互相弥补各自的不足和…...
python随机获取列表中某一元素
1、利用Python中的random模块中的choice方法 random.choice()可以从任何序列,比如list列表中,选取一个随机的元素返回,可以用于字符串、列表、元组等。 import random arr[1,2,3,4,5,6] print(random.choice(arr))2、利用Python中的random模…...
Nacos微服务笔记
Nacos安装Nacos 的 Github(Tags alibaba/nacos GitHub)下载我们所需的 Nacos 版本,可以选择 windows 或者 Linux。 进入官网,选择合适版本,tar.gz为linux版本,zip为windows版本。下载并解压 nacos-server…...
MAC文件误删怎么办?mac数据恢复,亲测很好用的方法
电脑文件误删,应该很多人都经历过。之前分享了很多关于Windows电脑文件误删如何恢复的方法,那么MAC电脑文件误删该怎么办?有什么好方法可以使得mac数据恢复回来吗?下面就给大家分享一些亲测好用的方法! 一、MAC电脑的文…...
机械革命z2黑苹果改造计划第二番-MacOS实用软件渗透工具
机械革命z2黑苹果改造计划第二番-实用软件 Mac实用工具 这是旧电脑改造计划的第二篇,就是安装一些常用软件和一些渗透测试工具,武装灵魂成为真正的生产力工具 首先推荐一个网站,www.mactools.app,这个软件里边有大多数常用的软…...
【LeetCode】每日一题(4)
目录 题目:1124. 表现良好的最长时间段 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:1124. 表现良好的最长时间…...
Linux内核移植:内核的启动过程分析、启动配置与rootfs必要文件
Linux内核移植:内核的启动过程、启动配置与rootfs必要文件一、启动过程二、启动配置(一)SysV初始化(二)systemd初始化三、rootfs中的启动配置文件1、inittab2、/etc/init.d/rcS 脚本3、fstab4、profile 文件5、其他文件…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
