【Vite 实践】Vite 库模式能满足你吗?或许你需要统一构建

news/2024/4/29 14:02:59/文章来源:https://blog.csdn.net/qq_53225741/article/details/126938145

2022 年本人投入了 Vite 的怀抱,开始参与到 Vite 社区中,陆续开发了一些插件。

Vite 秉承了开箱即用,简化配置的思路,确实显著提升了前端开发体验。

但是在类库模式的构建上却有所欠缺,只能处理单个输入和单输入出的情况,构建场景单一,Vite 社区上目前也没有可直接使用的工具,所以才有了开发一个统一构建插件的想法。

目前 vite-plugin-build 插件已可以直接使用,也录入了 Vite 官方 awesome-vite,希望也刚好能满足一些人的需要。

什么是统一构建?

因为没有特别好的叫法,本人暂且把这叫做统一构建,本人把统一构建归纳为如下构建:

  • Bundle 构建即 Vite(也是 Rollup)的库打包模式,单输入文件,单输出 bundle 文件,如果没有设置外部依赖(external)所有涉及的依赖包都会打包到一个 bundle 文件中。优点: 支持 umd 格式,浏览器中可作为外部依赖,不受业务代码 bundle 影响,可利用浏览器缓存机制,提高加载性能。缺点: 不支持 Tree Shaking 没有使用到的代码也会加载进来,由于打包到一个 bundle 文件,本地源码可读性差。

  • 文件夹构建(文件到文件转换器,file-to-file transformer)文件夹所有的符合格式的文件(['ts', 'tsx', 'js', 'jsx', 'vue', 'svelte'])会转换为对应同名的 .js 文件,只支持 commonjses 格式。转换的时候,所有的 import 依赖包不会打包进来,根据需要转换的格式转换为 commonjsrequire 或者 esimport 语法。优点: es 模式可支持 Tree Shaking,本地源码可读性高。缺点: 代码在 Webpack、Vite 这些构建工具中会和业务代码一起打包到 bundle 文件中,很难利用跨站点缓存优势。

  • 生成 TypeScript 声明文件支持原生 TypeScript、Vue TypeScript 和 Svelte TypeScript 声明文件的生成(如果有其他类型的框架也可以在此拓展)。vite-plugin-build 通过 Vite 配合使用 @vitejs/plugin-react@vitejs/plugin-vue@sveltejs/vite-plugin-svelte 可支持上面的三种构建方式。

为什么要开发一个 Vite 统一构建插件?

理由一,Vite 构建场景单一,不支持如下场景:

  • 多输入多输出(多输入多 bundle)
  • 转换文件夹(文件转文件的转换方式,不打包成一个 bundle 文件)
  • 生成 TypeScript 声明文件

理由二,Vite 社区缺乏可直接代替的工具。

Vite Github 上官方插件库使用的是 unbuild,是一款统一构建的工具,虽然挺方便的,但是 unbuild 更倾向于处理纯 JavaScript 或者 TypeScript 的代码,对于 React、Vue、Svelte 等浏览器 UI 类型相关的打包缺乏相关的转换处理。

理由三,Vite 体系一条龙服务。

Vite 统一构建插件,可在一些场景下让 Vite、Vitest 形成以个闭环体系,无需用到其他的构建和单元测试工具,一个 Vite 配置文件闯天下。

萌生想法

Vite 还没有兴起的之前,公司组内业务组件和个人的一些 Github 项目一开始是使用 Rollup 进行构建,Rollup 并不能开箱即用,还需要各种插件配置,相对较繁琐。

后来使用 Vite 的库模式来代替原生的 Rollup 可以减少不少的插件配置,不过整个文件夹的所有文件单独转换为 commonjs 和 es 的格式,还是需要通过 Vite 提供的 build API 实现,如下是通过指定文件夹下的所有目标文件,然后遍历运行 build 方式实现(还需要多一个 Vite 配置文件来配置):

const fs = require('fs');
const path = require('path');
const spawn = require('cross-spawn');
const srcDir = path.resolve(__dirname, '../src');
​
// 所有 src 文件夹包括子文件夹的 js、ts、jsx、tsx 文件路径数组
const srcFilePaths = getTargetDirFilePaths(srcDir);
srcFilePaths.forEach((file) => {const fileRelativePath = path.relative(srcDir, file);spawn('npm',['run', 'vite', '--', 'build', '--mode', fileRelativePath, '--outDir', 'es', '--config', './vite.file.config.ts'],{stdio: 'inherit',},);
}); 

同时还需要配置 npm run tsc 生成声明文件,pacakge.json scripts 字段比较繁琐:

{"scripts": {"tsc:es": "tsc --declarationDir es","tsc:lib": "tsc --declarationDir lib","tsc": "npm run tsc:lib && npm run tsc:es","vite": "vite","build:lib": "vite build","build:file": "node ./scripts/buildFiles.js","build": "npm run tsc && npm run build:file && npm run build:lib"}
} 

新的项目,就直接复制修改一下,虽然也能达到构建的目的,但是就是不够方便,本人懒所以还是想有没有更简单点的方式?如下方使用一个 script 就可以解决?

{"scripts": {"build": "vite build"}
} 

实现思路

首先完全通过 Vite 配置文件是无法实现统一构建的功能,即通过正常运行一次 Vite 构建服务无法实现统一构建的功能。

还是得多次运行 Vite 构建服务来实现此功能(表面上使用者无感知)。

实现的关键点

Bundle 构建

Vite 库模式就是 bundle 构建模式,不过只能设置一个入口文件,一个 bundle 输出文件。

实际场景可能需要多个入口文件,多个 bundle 输出文件,这个功能不复杂,通过遍历多个 vite build 构建即可实现,代码大致如下:

import { build } from 'vite';
​
const buildPs = lastBuildOptions.map((buildOption) => {return build({...viteConfig, // 透传 vite.config.ts 或者 vite.config.js 的用户配置,插件需要过滤自身(vite-plugin-build)mode: 'production',configFile: false,logLevel: 'error',build: buildOption,});
});
await Promise.all(buildPs); 

文件夹构建

实现思路也不复杂,如下:

1.获取文件夹中所有符合的文件路径
2.遍历所有文件路径,运行 vite build 构建

3.由于 Vue 和 Svelte 的 import 是需要带后缀名的,需要额外移除文件内容中的 .vue.svelte 后缀名。

简单代码实现大致如下:

import { build } from 'vite';
import fg from 'fast-glob';
​
const {inputFolder = 'src',extensions = ['ts', 'tsx', 'js', 'jsx', 'vue', 'svelte'],ignoreInputs,...restOptions,
} = options;
// 获取默认为项目根目录下 src 文件夹包括子文件夹的所有 js、ts、jsx、tsx、vue、sevele 文件路径,除开 .test.*、.spec.* 和 .d.ts 三种后缀名的文件
// 返回格式为 ['src/**/*.ts', 'src/**/*.tsx']
const srcFilePaths = fg.sync([`${inputFolder}/**/*.{${extensions.join(',')}}`], {ignore: ignoreInputs || [`**/*.spec.*`, '**/*.test.*', '**/*.d.ts', '**/__tests__/**'],
});
const buildPromiseAll = srcFilePaths.map((fileRelativePath) => build({...viteConfig, // 透传 vite.config.ts 或者 vite.config.js 的用户配置,插件需要过滤自身(vite-plugin-build)mode: 'production',configFile: false,logLevel: 'error',build: {lib: {entry: fileRelativePath,...},...restOptions},
}));
await Promise.all(buildPromiseAll);
await removeSuffix(); // 移除生成文件内容中的 `.vue` 和 `.svelte` 后缀名 

TypeScript 声明文件生成

前端 UI 框架的多种多样,像 Vue、Svlete 这类有自身自定义的语法,TypeScript 的语法需要特殊支持,生成声明文件自然也需要特殊处理。

原生 TypeScript

原生的 TypeScript 官方直接提供 tsc 工具可直接使用,通过直接运行 tsc bin 文件,并传递对应的配置即可实现。

简单的代码实现如下:

import spawn from 'cross-spawn';
​
const { rootDir, outputDir } = options;
const tscPath = path.resolve(require.resolve('typescript').split('node_modules')[0], 'node_modules/.bin/tsc');
spawn.sync(tscPath,['--rootDir', rootDir, '--declaration', '--emitDeclarationOnly', '--declarationDir', outputDir],{stdio: 'ignore',},
); 

Vue TypeScript

Vue 3 出来后,对 TypeScript 的支持就比较完善了,Vue 社区的 vue-tsc 可以用来替代 tsc,用法保持和 tsc 一致。

有一点不一样的是 vue-tsc 生成的声明文件是 .vue.d.ts 后缀名的,所以需要重命名为 .d.ts 后缀名。

简单的代码实现如下:

import spawn from 'cross-spawn';
​
const { rootDir, outputDir } = options;
const vueTscPath = path.resolve(require.resolve('vue-tsc/out/proxy').split('node_modules')[0],'node_modules/.bin/vue-tsc',
);
spawn.sync(vueTscPath,['--rootDir', rootDir, '--declaration', '--emitDeclarationOnly', '--declarationDir', outputDir],{stdio: 'ignore',},
);
​
if (isVue) {renameVueTdsFileName(); // 重命名 .vue.d.ts 为 .d.ts
} 

Svelte TypeScript

Svelte 社区没有像 Vue 那么强大,没有类似 vue-tsc 这样的工具,最终找到 svelte-type-generator 可以实现,参考 svelte-type-generator 的代码实现了,生成声明文件的功能(暂时不支持 tsc cli 的功能)。

const { compile } = require('svelte-tsc');
const { rootDir, outputDir } = options;
​
compile({rootDir,declaration: true,emitDeclarationOnly: true,declarationDir: outputDir,
});
​
if (isVue) {renameSvelteTdsFileName(); // 重命名 .svelte.d.ts 为 .svelte.d.ts
} 

打印构建信息

由于是触发运行多个 vite build 所以如果直接输出默认的构建信息,那么会显得混乱,无法像运行一个 vite build 输出构建信息。

所以得拦截和隐藏原有的构建信息,自定义输出新的构建信息。

1.拦截和隐藏原有的构建信息,通过重写 console.logconsole.warn 可以达到目的,代码如下:export const restoreConsole = { ...console };​export class InterceptConsole { public log: typeof console.log; public warn: typeof console.warn; public clear: typeof console.clear;​ constructor() { const { log, warn } = console; this.log = log; this.warn = warn;}​ silent() { console.log = () => {}; console.warn = () => {};}​ restore() { console.log = this.log; console.warn = this.warn;}} 2.自定义输出新的构建信息功能参考 Vite 的内置 reporter 插件,通过对应的钩子函数,实现构建信息的输出。最终效果

Github 例子

vanilla

vanilla-ts

react

react-ts

vue

vue-ts

svelte

svelte-ts

所有例子,运行如下命令即可

$ npm install
$ npm run build 

Codesandbox 在线例子

  • vanilla-ts
  • react-ts
  • vue-ts
  • svelte-ts

后续

如果感兴趣的也可以加入一起建设,目前 svelte-tsc 实现和 vue-tsc 一样的用法,是有点挑战性的。

1.生成声明文件支持配置 tsconfig 配置文件路径
2.svelte-tsc 支持 bin 文件,功能参照 vue-tsc ,支持所有 tsc 的 cli 选项。

最后,整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

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

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

相关文章

个人笔记--数据库理论 01 关系模型介绍——基于《数据库系统概念》第七版

关系模式 关系的例子 关系模型是目前广泛应用的数据模型由表的集合构成 例如 IDnamedpt_namesalary11111JAMCS12345 元组 tuple:表中的一行,元素无所谓属性 attribute : 原子的,不可再分的,要有属性域,如上表的nam…

云原生爱好者周刊:延迟加载任意 OCI 镜像 | 2022-09-13

开源项目推荐 SOCI Snapshotter SOCI Snapshotter 是一个 Containerd Snapshotter 插件,可以延迟加载任意 OCI 镜像,不需要 Stargz Snapshotter 一样构建特殊格式的镜像才能延迟加载。 Authentication Proxy 这个项目使用 YARP (Yet Another Reverse…

Git的认识和使用

目录 一、前置准备 二、git简介 三、gitee.com的基本使用 1.创建仓库(私库和公库) 2.创建文件及文件夹 新建文件夹两种方式 ①​ ② 3.删除 删除文件 删除仓库 四、组长组员的git使用 git clone 查看文件 git status git add git commit git push ## 命令行配置 多个…

葡聚糖-MAL/NHS/N3/Alkyne/SH/Biotin/CHO/OPSS/OH

产品名称: 葡聚糖-马来酰亚胺,葡聚糖-MAL,马来酰亚胺功能化葡聚糖 英文名称:Dextran-MAL PEG分子量可选:350,550,750,1k,2k,3.4k,5k,10k,20k(可…

[仅需1步]企业微信群机器人[0基础接入][java]

[仅需1步]企业微信群机器人[0基础接入][java]背景介绍使用测试项目背景 公司需要把日常的服务器错误抛到企业微信群中,我正好记录下使用企业微信群机器人… 介绍 企业微信群机器人 应用介绍 企业微信是腾讯微信团队打造的企业通讯与办公工具,具有与微信一致的沟…

医院检验LIS系统源码

医院lis源码 实验室信息管理系统源码 .net检验系统源码 医院系统源码 了解更多源码内容,可私信我。 开发环境:.NET4.0 WPF VS2017或VS2019SQL2016 实验室信息管理系统以条码标本为主线,实现从采集、检测、报告、归档的全程跟踪管理。 支持…

DevOps自动化测试的原则和实践

DevOps是为了在保证高质量的前提下缩短系统变更从提交到部署至生产环境的时间。在对系统进行变更时,质量很重要。高质量才能让业务价值传递到系统干系人。『自动化测试既是提高质量的一种重要手段,也是实施持续测试必需的能力,因此它是DevOps…

修改WebBrowser控件的内核解决方案

首先说一下原理 当下很大浏览器他们都是用了IE的core, 这个core只提供HTML/JS的执行和渲染,并没有给出关于界面和一些特性上的事,所以开发自己浏览器如果基于IE core需要自己完成这些内容。 一张图很好的说明了这个情况,IE浏览器的架构:http://msdn.microsoft.com/en-us/li…

nginx - 负载均衡配置-负载均衡策略

目录 知识点1:网站流量分析指标 什么是pv? 什么是uv? 什么是IP? 知识点2:正向代理和反向代理 知识点3:负载均衡实验 IP地址规划: 实验拓扑图 知识点4:负载均衡策略 1、请求…

Spring5.3学习——from 官网 day1-1

Spring5.3学习——from 官网day1-1Spring5.3学习——from 官网day1-1前言概述Spring的设计理念Spring核心:IOC什么是IOC解释IOC容器的包什么是BeanBeanFactory接口简述ApplicationContext接口简述BeanFactory源码描述以下是Bean工厂创建和销毁bean的完整生命周期流程…

Matlab论文插图绘制模板第48期—平行坐标图(Parallelplot)

​上一期文章中,分享了Matlab帕累托图的绘制模板: 这一次,再来分享一种特殊的线图:平行坐标图。 ‘平行坐标图是一种通常的可视化方法,用于对高维几何和多元数据的可视化……为了克服传统的笛卡尔直角坐标系容易耗尽空…

好心情精神心理科:80%双相情感障碍被误诊,千万注意鉴别

双相情感障碍又称躁郁症,其表现复杂,容易与其他精神疾病(包括边缘型人格障碍)相混淆,超过80%的患者未能得到正确诊断。 具体如何区分双相情感障碍与边缘型人格障碍?在回答这个问题之前,好心情精…

从规模走向规模经济,锅圈食汇回归餐饮初心

预制菜源自美国,在日本因冷链技术发展而普及。后疫情时代,预制菜在中国餐饮市场加速渗透,成为行业的新风向。 9月,第一财经与CBNData发布“Growth502022中国新消费品牌年度增长力榜单”,预制菜品牌锅圈食汇入选。 锅…

设计模式学习笔记--责任链模式

责任链模式 责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求&…

Tuxera NTFS21Mac苹果电脑读取硬盘磁盘软件

我们经常会使用移动硬盘或 U 盘进行大体积文件的分享、携带。但有时候别人提供的NTFS移动硬盘或者U 盘在 Mac 电脑中只能读取,无法将文件导入到其中。这是因为常见的 NTFS 硬盘格式在 Mac 中不能兼容。 当你从 Windows 转到了 Mac 平台,可能会发现之前用…

RocketMQ-流程图-概念

文章目录RocketMq的角色消息发送的流程RocketMq的角色 Producer:消息的发送者,生产者;举例:发件人Consumer:消息接收者,消费者;举例:收件人Broker:暂存和传输消息的通道…

Python数据分析教程(一):Numpy

数据的纬度 一维数据:列表和集合类型二维数据:列表类型多维数据:列表类型高维数据:字典类型或数据表示格式,如json、xml、yaml维度:一组数据的组织形式列表和数组:一组数据的有序结构Numpy Numpy介绍NumPy是一个开源的Python科学计算基础库,包含:一个强大的N维数组对象…

渗透测试神器Nmap使用教程

渗透测试神器Nmap使用教程1.nmap简介2.常用参数3.nmap实战命令1.nmap简介 Nmap (网络映射器)是Gordon Lyon最初编写的一种安全扫描器,用于发现计算机网络上的主机和服务,从而创建网络的“映射”。为了实现其目标,Nmap…

java计算机毕业设计基于安卓Android的金融保险app(源码+系统+mysql数据库+Lw文档)

项目介绍 计算机信息技术的发展,推动了金融保险信息化管理的进程,并随着互联网概念的提出,各种互联网软件也应运而生。在传统的管理中,各种信息管理难,传播速度慢,需要耗费很长时间统计核查,不…

Oracel中视图相关概念和操作(一)

目录 1.视图概念(有必要) (1)视图基本概念 (2)视图和定义的表的联系 (3)视图的优点 2.创建视图 (1)使用SQL DEVELOPER创建视图(可视化&#x…