vite + vue3 + storybook + ts 搭建组件库记录
目标
- 只按需引入,不依赖babel-import-plugin 插件。
- 第三方依赖都不打包。
- 用原生fetch请求数据。
- 仅支持esmodule。配置package.json type:"module"
搭建
根据storybook 官网文档,需要在已有的项目中运行
npx storybook@latest init
也就是事先需要通过vite创建一个项目。
npm create vite@latest
之后再运行storybook 的命令,storybook会自动分析使用的构建工具,安装好需要的依赖,并自动新增文件。
storybook 增加了/src/stories目录,用于存放组件。
默认情况下,/src/stories 中放着 .vue, .stories, .css 文件,由于我希望把组件源代码单独放在一个文件夹下
目录预设
因此在项目根目录 增加 /packages 目录,下面存放以组件名称命名的文件夹。以每个文件夹为单位表示为一个组件。
/src/stories 中.stories 文件引用/packages 目录下的.vue 用于生成storybook演示文档。
对于vite 的普通打包模式下,入口必须为index.html,因此需要使用vite 支持的lib模式打包。
lib模式下,对于图片等静态资源,处理为base64内联到代码中。且不支持配置。
base64的问题在于增大js体积,且不利于相同图片的复用。这块待研究。
构建vue组件
直接使用vite build 命令,会使用项目根目录下的vite.config.js 对指定的入口进行构建。构建产物默认输出到dist目录下。
lib模式下,构建产物有
- index.js
- style.css
对于一个vue组件来说,这种格式正式我想要的。
而/package 目录下面会有好多组件,因此需要借助vite 的JavsScript API 进行循环
vite JS API 构建 /packages 目录
根据官网描述,使用下面js代码, 可以通过js启动vite 打包。
import { build } from 'vite';
build({//... vite config
})
这里的 build() 方法传入的config对象,会和项目下的 vite.config.js 合并。
所以将一些公共的配置可以写在 vite.config.js下
vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import dts from 'vite-plugin-dts';// https://vitejs.dev/config/
export default defineConfig({build: {rollupOptions: {external: ['vue'], // 排除三方包},},plugins: [vue(),vueJsx(),dts({outputDir: './lib',entryRoot: './packages',}),],
});
build.js 主要的构建方法
/*** 构建一个组件* @param {string} compName 组件名称,对应packages目录下的文件夹名称*/
async function buildAComponent(compName) {const entry = path.join(packagesDir, compName, 'index.ts');const out = path.join(outDir, compName);await build({build: {outDir: out,lib: {entry: [entry],formats: ['es'],},},});
}
这个是构建一个组件的方法,因此,我只要通过node 的 fs 模块读取并分析/packages 路径下的文件夹,遍历出来构建即可。
build.js代码
import { readdirSync, writeFileSync } from 'fs';
import path, { dirname } from 'path';
import { fileURLToPath } from 'url';
import { build } from 'vite';const __dirname = dirname(fileURLToPath(import.meta.url));
const packagesDir = path.join(__dirname, './packages');
const outDir = path.join(__dirname, './lib');
async function main() {const packages = readdirSync(packagesDir);let indexFileContent = '';const exportNames = [];const promise = [];for (const folderName of packages) {// const stats = lstatSync(path.join(packagesDir, compName));// if (stats.isDirectory()) {// // 如果是目录,则构建// }const firstLetter = folderName[0];const isFirstLetterUpperCase = /[A-Z]/.test(firstLetter);if (isFirstLetterUpperCase && folderName.indexOf('.ts') === -1) {promise.push(buildAComponent(folderName));indexFileContent += `import { ${folderName} } from './${folderName}/index.js';\n`;exportNames.push(folderName);}}await Promise.all(promise);indexFileContent += `export { ${exportNames.join(', ')} };`;writeFileSync(path.join(outDir, 'index.js'), indexFileContent);console.log('created: lib/index.js');}
main();/*** 构建一个组件* @param {string} compName 组件名称,对应packages目录下的文件夹名称*/
async function buildAComponent(compName) {const entry = path.join(packagesDir, compName, 'index.ts');const out = path.join(outDir, compName);await build({build: {outDir: out,lib: {entry: [entry],formats: ['es'],},},});
}
main 函数中判断文件夹名称前面是大写字母开头的才当作组件来处理。
构建结果
- /package/Button
- index.ts
- style.less
- Button.vue
这一个目录入口为index.ts 构建完成后,输出到lib
- /lib/Button
- index.js
- style.css
至此,主要构建完成了
库入口
由于一个npm库需要有一个默认的入口js,因此需要在/lib 目录下面增加一个index.js 用于导入lib 下面所有组件,并导出。这部分代码在上面 build.js 中已经体现。
/lib/index.js
export { Button } from './Button/index.ts';
package.json 增加配置
{"main": "lib/index.js","module": "lib/index.js","files": ["lib","packages"],//...
}
d.ts生成
使用vite-plugin-dts 插件
import dts from 'vite-plugin-dts';// ... plugins:[// vue(),// vueJsx(),dts({outputDir: './lib',entryRoot: './packages',}),
]
构建dts速度有点慢 。
这样配置,会在lib/Button/ 下面增加d.ts 文件了。
与库的默认入口文件一样,需要指定默认declare 文件,package.json types 指定为 /packages/main.ts。(这里暂时指定.ts 文件,可能在一些构建工具中不识别,因为那些工具只识别d.ts 文件)
实现自动引入
一个组件默认的构建结果为index.js, style.css
鉴于使用的情况下引入 import { Button } from 'xxx'; 之外还要 import 'xxx/lib/Button/style.css';
使用babel-import-plugin 可以解决按需引入样式问题。
由于我的目标是不使用babel-import-pluing 因此,完成这个效果,只需要在/lib/Button/index.js 文件的最上方引入/lib/Button/style.css即可。
方案
- 使用node fs读写文件。
- 借助vite plugin
使用vite plugin 实现
因为不想用node
由于vite基于rollup,根据rollup 官网文档,我们可以在插件的 generateBundle 钩子中在生成产物前操作文件内容。
代码
/*** 在产物js上导入css*/
function () {return {name: 'auto-import-style',generateBundle(options, bundle) {bundle['index.js'].code = 'import "./style.css";\n' + bundle['index.js'].code;},};
},
npm上也有类似的插件 vite-plugin-libcss
构建vue组件要点
不能将vue依赖打包进代码中,否则会导致组件无法使用。
打包组件的产物js中,最上方应该为 import {} from 'vue'; 这样的代码。
通过配置vite.config.js 下的rollupOptions.external即可:
build: {rollupOptions: {external: ['vue'], // output: {// globals: {// vue: 'Vue', // umd需要// },// },},},
这里注释掉rollupOptions.output.globals 原因是默认构建lib会输入umd 和 es 模块的文件。我构建时会指定 build.lib.formats: ['es'] 就不需要了。
增量构建方案预设
由于现在我看使用vite-plugin-dts 生成d.ts 文件使用的时间过长。先制定一下增量构建的方案。
鉴于在正常开发过程中,始终用master分支作为正式分支。
因此在开发分支中,可以借助git 来对比当前开发分支与master分支的区别
使用node 的child_process 执行命令
git diff HEAD master --stat
可检查当前分支,对比master,哪些文件有变化。
得到控制台输出后,分析产物,确定package.json 中哪些组件有变动。以此仅构建变更过的组件。
vite可能会覆盖lib目录。构建前先保存一版lib目录?还是有官方配置。暂不研究。
vite + vue3 + storybook + ts 搭建组件库记录相关推荐
- 基于 next.js + mdx 搭建组件库文档项目(二) -- mdx 控件封装实现组件的演示与 Props 列表
说明 经过上阶段的配置虽然可以在项目中使用 mdx 语法 来创建页面了,但是我们的组件库有一些定制化的需求:交互式的组件演示.组件 Props 列表展示.这些功能如果可以通过封装来实现,会大大提升开发 ...
- 基于 next.js + mdx 搭建组件库文档项目(一) -- 开发环境搭建
说明 之前使用过 Docz 来作为组件库文档搭建工具,它基于 gatsby , 提供了高度的定制化能力,但是截止 2021-06-22, Docz 停留在 v2.3.1(2020-04-05) 已经一 ...
- 基于vue3的京东nutui组件库的表单校验规则:怎样进行表单验证?怎样只使用指定的某一个规则进行校验呢?
官网: NutUI - 移动端 Vue2.Vue3.小程序 组件库京东风格的轻量级移动端 Vue.React 组件库https://nutui.jd.com/#/component/form 用法: ...
- 用vue搭建组件库的流程
目录 一.项目介绍 二.用脚手架生成vue项目 三.修正项目结构 四.跑通一个demo 五.卡片组件的设计与代码编写 六.测试组件的功能 七.前端模块化 八.webpack打包js文件 九.Gulp打 ...
- StoryBook 开发React组件库文档
StoryBook 开发 React 组件库文档 说明 StoryBook 是一个开源的 UI 组件库构建工具,支持 React.Vue.Angular 等主流开发框架,使用 StoryBook 将获 ...
- Vue3 企业级优雅实战 - 组件库框架 - 4 组件库的 CSS 架构
1 常见的 CSS 架构模式 常见的 CSS 架构模式有很多:OOCSS.ACSS.BEM.SMACSS.ITCSS 等,其中 SMACSS 和 ITCSS 很相似.我在企业级项目中最常使用的是简化版 ...
- vue3.0(第九篇)vue3.0可用的组件库
1.Elemnet UI 推出Element Plus 源码地址 https://github.com/element-plus/element-plus 官方网站 https://element-p ...
- 支持vue3.0+ts 的富文本记录
前言 用过很多的富文本,还是蛮喜欢鹅毛富文本,轻量级, 一般遇到富文本的案例,都会首先想到的是quill 目前vue3.0与react分裂两极,typescript霸占一方,javascript还在坚 ...
- 推荐 8 个支持 Vue3 的前端 UI 组件库,免费开源、漂亮美观,涵盖常用的业务组件
Vue3 正式发布已经快2年了,今年2月也正式变成 Vue 项目的默认版本,今天分享8个优秀的 Vue3 UI 组件库. Element Plus 相关网址:https://www.thosefree ...
最新文章
- 中北大学c语言程序设计作业答案,2016年中北大学软件学院程序设计基础考研复试题库...
- vertx核心类之VertxImpl
- setsockopt()函数使用详解
- 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-01-CNN基础知识点
- 内核函数 系统调用 系统命令 库函数
- Mybatis中 Dao接口和XML文件的SQL如何建立关联
- NumPy快速入门--复制/视图/深拷贝
- ubuntu安装zsh、oh-my-zsh及常用配置
- 五大领域总目标指南_每日干货 | 五大领域 学前社会教育1
- 通过helm在k8s上部署spark(伪集群版)
- sqli-labs Less-11 and Less-12
- 【手势识别】基于matlab k-means聚类手势识别【含Matlab源码 386期】
- 分治法( Divide and Conquer)
- C语言科学计数法介绍和示例
- 知识图谱_数据挖掘主要技术
- centos下使用pngquant批量压缩png图片
- android srgb模式,一加3固件官方更新:加入屏幕边缘防误触和sRGB显示模式功能
- matlab独立t样本检验,matlab与单样本t检验
- ESP8266 AT指令设置及51单片机的控制
- 手把手教你查看常用理财工具
热门文章
- C语言之函数调用06—彩球排列
- rtsp 服务器搭建
- 2022最新PPT模板,免费下载
- linux git 401,git push 提示 401 Unauthorized while accessing https 的原因及解决方法
- 开启Fluter基础之旅五-------ListView 3D滚动、Flipper效果、ListView下拉刷新上拉加载、ListView重排序...
- S32K144之无法debug,复位引脚为低
- python从0到100_python 100_python100天从新手到大师_pythong0~100的质数 - 云+社区 - 腾讯云...
- 常用的英语短语短句(持续更新中)
- 我把华为小米年报放一起,发现华为才是真·手机公司,小米确实不靠卖手机赚钱...
- 年记_心向远方自明朗