@jdt-jinke-open/vite-plugin-legacy-lib
v1.0.0
Published
支持库模式的Legacy Jssdk打包输出插件,基于legacy插件改造
Maintainers
Readme
@jdt-jinke-open/vite-plugin-legacy-lib
一个专门为Vite库模式设计的Legacy插件,用于打包输出Jssdk。基于官方的@vitejs/plugin-legacy插件改造,专注于库代码的转换和polyfill处理。
特性
- ✅ 库模式专用:支持vite库模式legacy打包
- ✅ 智能Polyfill检测:自动检测和处理需要的polyfills
- ✅ SystemJs模块格式:更安全的模块格式,使用
System.import轻松完成模块加载 - ✅ css隔离:自动隔离css样式,支持组件库前缀替换
安装
pnpm add @jdt-jinke-open/vite-plugin-legacy-lib -D使用方法
配置vite.config.lib.ts,以下是一个最简化的配置参考:
import vitePluginLegacyLib from '@jdt-jinke-open/vite-plugin-legacy-lib'
export default defineConfig({
root: __dirname,
build: {
lib: {
// sdk入口
entry: resolve(__dirname, 'src/sdk-a/index.ts'),
// sdk文件名
fileName: 'sdk-a',
},
},
plugins: [
Vue(),
vitePluginLegacyLib(),
// ...
],
})运行时变量
可以从@jdt-jinke-open/vite-plugin-legacy-lib/runtime获得几个关键的运行时变量
import {
isJSSDKEnv, // 用于判断当前是否Jssdk执行环境
prefixClass, // css隔离类名,前面带`.`的
prefixClassName, // css隔离类名,前面不带`.`的
teleportRootId, // 自动创建的给全局弹框类组件挂载的teleport id,自动添加了css隔离类名
} from '@jdt-jinke-open/vite-plugin-legacy-lib/runtime'Jssdk管理和调试
推荐使用如下结构管理多个jssdk
可选,在sdk入口js相同的位置,增加index-dev文件支持本地调试功能:
src/jssdk/
|__some-sdk/
|__index.ts # Jssdk的输出入口
|__index-dev.ts # 调试Jssdk入口
|__index-dev.html # 调试Jssdk的页面入口
|__other-sdk/
|__index.ts # Jssdk的输出入口
|__index-dev.ts # 调试Jssdk入口
|__index-dev.html # 调试Jssdk的页面入口在启动服务前,使用插件提供的legacyLibSelect终端选择控件,此时可以移除build.lib配置了:
import { legacyLibSelect } from '@jdt-jinke-open/vite-plugin-legacy-lib'
export default defineConfig(async () => {
// 终端交互选择启动的jssdk
const selectInfo = await legacyLibSelect({
manageDir: resolve(__dirname, 'src/jssdk'),
})
// selectInfo.config.theme // 配置的主题可以传给按需引入插件
return {
// ...
}
})调试页面大致如下
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/some-sdk/index-dev.ts"></script>
</body>
</html>存量项目改造
如果你是存量vite+legacy项目,2步配置:
- 复制
vite.config.ts为vite.config.lib.ts,替换legacy插件和增加lib配置即
export default defineConfig({
// ...其他配置
build: {
lib: {
// sdk入口
entry: resolve(__dirname, 'src/some-sdk/index.ts'),
// sdk文件名
fileName: 'some-sdk',
},
},
plugins: [
Vue(),
// legacy({
// // ...
// }),
// 将legacy 替换为 @jdt-jinke-open/vite-plugin-legacy-lib
vitePluginLegacyLib(),
],
})- 业务项目输出jssdk时,组件多是复用的,如下操作在
vite.config.ts中添加运行时支持
export default defineConfig({
// ...其他配置
plugins: [
Vue(),
legacy({
// ...
}),
// 关闭插件仅提供runtime支持,,这样全局依旧支持`import { prefixClass } from '@jdt-jinke-open/vite-plugin-legacy-lib/runtime'`
vitePluginLegacyLib({
enable: false,
}),
],
})宿主如何接入sdk
先安装必要依赖
pnpm i systemjs @types/systemjs确保在应用入口(main.ts)引入systemjs模块
// 放到最顶部
import 'systemjs'使用sdk
System.import('url').then((exports) => {
/**
* 假如sdk是这样导出的:
*
* export const a = 1
* export const b = 2
*
* exports就是
* {
* a: 1,
* b: 2,
* }
*/
console.log(exports)
})组件库前缀替换
使用libPrefixReplace选项开启组件库前缀替换,所有组件名、组件类名等相关的前缀都会被替换为指定的前缀
import { getRandomNameHash } from '@jdt-jinke-open/vite-plugin-legacy-lib'
// 替换组件库前缀,注意resolver、unplugin等插件也需要一致
const customFinMPrefixName = getRandomNameHash()
export default defineConfig({
plugins: [
// ...
vitePluginLegacyLib({
cssIsolation: {
libPrefixReplace: {
// 全局替换FinD Mobile组件前缀
jdtm: customFinMPrefixName,
},
},
}),
]
})全部配置
/**
* Jssdk主要配置
*/
export interface LegacyLibOptions extends Pick<CssIsolationOption, 'enable'> {
/**
* 打包输出目录,默认输出到相对sdk入口的dist目录
*/
outDir?: string
/**
* 目标浏览器
* @default ['ie >= 11']
*/
targets?: string | string[] | Record<string, string>
/**
* css隔离配置
*/
cssIsolation?: Omit<CssIsolationOption, 'enable'>
/**
* default: true
*/
polyfills?: boolean | string[]
additionalLegacyPolyfills?: string[]
/**
* @see https://babeljs.io/docs/assumptions
*
* default: {}
*/
assumptions?: Record<string, boolean>
}
/**
* 针对Jssdk复用业务代码的场景,为业务代码运行时和类型支持
*/
export interface LegacyLibTypeOptions {
enable: false
}
/**
* 插件配置
*/
export type Options = LegacyLibOptions | LegacyLibTypeOptionscss隔离配置
export interface CssIsolationOption {
/**
* 是否启用插件功能,在业务`vite.config.ts`中注册这个插件并传`false`以支持任意地方获取css隔离前缀:\
* ```js
* `import { prefixClass } from '@jdt-jinke-open/vite-plugin-legacy-lib/runtime'`
* ```
* 关闭后,获取到的前缀为空字符串
* @default true
*/
enable?: boolean
/**
* 组件库前缀替换,完全隔离可能的组件库样式冲突,比如样式覆盖 \
* 注意这里忽略大小写,所有组件名、组件类名等相关的前缀都会被替换 \
* 规则是基于`jdtm`定义的,如有遗漏,可通过`values`选项先自定义,内置规则见`genLibPrefixReplaceConfig`
* @example
*
* ```js
* libPrefixReplace: {
* // 将组件库的`jdtm`前缀替换为`abc`
* jdtm: 'abc',
* // 将组件库的`fin`前缀替换为`cde`,并添加了自定义的替换规则
* fin: {
* prefix: 'cde',
* values: {
* 'fin--': 'cde--'
* }
* }
* }
* ```
*/
libPrefixReplace?: {
[prefix: string]: string | {
/**
* 新前缀
*/
prefix: string
/**
* 新增自定义的前缀替换规则
*/
values?: Record<string, string>
}
}
/**
* 全局类名前缀,主要隔离对宿主环境样式的影响
*/
prefix?: string | ((randomHash: string) => string)
/**
* 单类名场景,需要排除的类名,设置不影响默认值
* - 传入string类型时,需完全匹配
* - 传入正则类型时,注意影响范围,限制开头和结尾
* @default
* const defaultExclude: (string | RegExp)[] = [
* '.dark', // 业界常用的暗黑主题切换类名
* '.van-theme-dark', // vant基础库暗黑主题切换类名
* '.van-overflow-hidden', // vant基础库禁止页面滚动
* '.el-loading-parent--hidden', // element基础库loading
* '.el-popup-parent--hidden', // element基础库禁止页面滚动
* '.el-loading-parent--relative', // element基础库loading
* ]
*/
exclude?: (string | RegExp)[]
/**
* 多类名场景,在匹配的开头类名之后插入前缀,设置不影响默认值
* @default
* const defaultInsertAfter = [
* ...defaultExclude, // 默认排除的类名
* 'html',
* 'body',
* ]
* @example
* // before
* `.dark .some-class`
* // after
* `.dark .prefixClass .some-class`
*
* // before
* `body .some-class`
* // after
* `body .prefixClass .some-class`
*/
insertAfter?: (string | RegExp)[]
/**
* 添加自定义逻辑,返回类名则覆盖默认逻辑,否则继续执行默认逻辑
*/
transform?: (prefix: string, selector: string, prefixedSelector: string, filePath: string, rule: import('postcss').Rule) => string | void
/**
* 忽略的文件
*/
ignoreFiles?: (string | RegExp)[]
/**
* 手动指定包含的文件
*/
includeFiles?: (string | RegExp)[]
}