目标

  • 只按需引入,不依赖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 搭建组件库记录相关推荐

  1. 基于 next.js + mdx 搭建组件库文档项目(二) -- mdx 控件封装实现组件的演示与 Props 列表

    说明 经过上阶段的配置虽然可以在项目中使用 mdx 语法 来创建页面了,但是我们的组件库有一些定制化的需求:交互式的组件演示.组件 Props 列表展示.这些功能如果可以通过封装来实现,会大大提升开发 ...

  2. 基于 next.js + mdx 搭建组件库文档项目(一) -- 开发环境搭建

    说明 之前使用过 Docz 来作为组件库文档搭建工具,它基于 gatsby , 提供了高度的定制化能力,但是截止 2021-06-22, Docz 停留在 v2.3.1(2020-04-05) 已经一 ...

  3. 基于vue3的京东nutui组件库的表单校验规则:怎样进行表单验证?怎样只使用指定的某一个规则进行校验呢?

    官网: NutUI - 移动端 Vue2.Vue3.小程序 组件库京东风格的轻量级移动端 Vue.React 组件库https://nutui.jd.com/#/component/form 用法: ...

  4. 用vue搭建组件库的流程

    目录 一.项目介绍 二.用脚手架生成vue项目 三.修正项目结构 四.跑通一个demo 五.卡片组件的设计与代码编写 六.测试组件的功能 七.前端模块化 八.webpack打包js文件 九.Gulp打 ...

  5. StoryBook 开发React组件库文档

    StoryBook 开发 React 组件库文档 说明 StoryBook 是一个开源的 UI 组件库构建工具,支持 React.Vue.Angular 等主流开发框架,使用 StoryBook 将获 ...

  6. Vue3 企业级优雅实战 - 组件库框架 - 4 组件库的 CSS 架构

    1 常见的 CSS 架构模式 常见的 CSS 架构模式有很多:OOCSS.ACSS.BEM.SMACSS.ITCSS 等,其中 SMACSS 和 ITCSS 很相似.我在企业级项目中最常使用的是简化版 ...

  7. vue3.0(第九篇)vue3.0可用的组件库

    1.Elemnet UI 推出Element Plus 源码地址 https://github.com/element-plus/element-plus 官方网站 https://element-p ...

  8. 支持vue3.0+ts 的富文本记录

    前言 用过很多的富文本,还是蛮喜欢鹅毛富文本,轻量级, 一般遇到富文本的案例,都会首先想到的是quill 目前vue3.0与react分裂两极,typescript霸占一方,javascript还在坚 ...

  9. 推荐 8 个支持 Vue3 的前端 UI 组件库,免费开源、漂亮美观,涵盖常用的业务组件

    Vue3 正式发布已经快2年了,今年2月也正式变成 Vue 项目的默认版本,今天分享8个优秀的 Vue3 UI 组件库. Element Plus 相关网址:https://www.thosefree ...

最新文章

  1. 中北大学c语言程序设计作业答案,2016年中北大学软件学院程序设计基础考研复试题库...
  2. vertx核心类之VertxImpl
  3. setsockopt()函数使用详解
  4. 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-01-CNN基础知识点
  5. 内核函数 系统调用 系统命令 库函数
  6. Mybatis中 Dao接口和XML文件的SQL如何建立关联
  7. NumPy快速入门--复制/视图/深拷贝
  8. ubuntu安装zsh、oh-my-zsh及常用配置
  9. 五大领域总目标指南_每日干货 | 五大领域 学前社会教育1
  10. 通过helm在k8s上部署spark(伪集群版)
  11. sqli-labs Less-11 and Less-12
  12. 【手势识别】基于matlab k-means聚类手势识别【含Matlab源码 386期】
  13. 分治法( Divide and Conquer)
  14. C语言科学计数法介绍和示例
  15. 知识图谱_数据挖掘主要技术
  16. centos下使用pngquant批量压缩png图片
  17. android srgb模式,一加3固件官方更新:加入屏幕边缘防误触和sRGB显示模式功能
  18. matlab独立t样本检验,matlab与单样本t检验
  19. ESP8266 AT指令设置及51单片机的控制
  20. 手把手教你查看常用理财工具

热门文章

  1. C语言之函数调用06—彩球排列
  2. rtsp 服务器搭建
  3. 2022最新PPT模板,免费下载
  4. linux git 401,git push 提示 401 Unauthorized while accessing https 的原因及解决方法
  5. 开启Fluter基础之旅五-------ListView 3D滚动、Flipper效果、ListView下拉刷新上拉加载、ListView重排序...
  6. S32K144之无法debug,复位引脚为低
  7. python从0到100_python 100_python100天从新手到大师_pythong0~100的质数 - 云+社区 - 腾讯云...
  8. 常用的英语短语短句(持续更新中)
  9. 我把华为小米年报放一起,发现华为才是真·手机公司,小米确实不靠卖手机赚钱...
  10. 年记_心向远方自明朗