Howdyjs
是笔者开源的一个JS插件工具库,旧版封装了一些Vue的指令与常用组件。现在将部分Vue指令抽离出来使用原生JS实现,而Vue组件则使用Vue3重构,同时将Document展示站点使用Vite重构。该文章记录重构开发的相关说明。
🔗Link
🌟主要变更
- 新版全面采用
Typescript
- Vue组件部分将使用
Vue3
重构,不向下兼容,有Vue2.X需求的请使用旧版 - 因各组件内的关联性不强,新版的组件库将进行分包发布,可便于按需加载
- 旧版多数包都将功能封装成Vue指令,并默认导出的是Vue指令,现在新版将默认导出原生构造函数,便于跨框架或原生使用,但同时保留了Vue指令封装的使用方式
- 使用
lerna
进行分包管理 - 使用
Rollup
进行组件打包 - 展示站点使用
Vite
搭建
🚀当前包含插件
- @howdyjs/resize
通过拖拽更改元素尺寸插件
- @howdyjs/img-zoom
图片放大插件,支持按组浏览下一张图片
- @howdyjs/size-observer
监听元素尺寸变化插件
- @howdyjs/scroll
自定义滚动条插件
- @howdyjs/to-drag
设置Dom可拖动插件
- @howdyjs/animation-dialog
动画模态框Vue3组件
- @howdyjs/standard-tabs
移动端标签页Vue3组件
- @howdyjs/mouse-menu
自定义右键菜单Vue3组件
- @howdyjs/to-control
拖拽更改元素大小与位置插件
🌈项目架构说明
Vite
综合对比之后,发现采用Vite
基本可以实现当前展示站点的所有功能,而且在开发环境下热更新速度极快,所以新版项目采用了Vite构建开发站点。
由于项目有导入.md文件的需求,而Vite并不能直接使用Webpack的markdown-loader,所以暂时自己写一个简单的markdown-plugin在Vite中使用(最新已有成熟的官方提供的plugin)。
// vite.config.ts
const markdownPlugin = (options: any) => {
return {
name: 'markdown',
transform(code: string, id: string) {
if (!/.md/.test(id)) {
return;
}
const result = marked(code, options);
return `export default ${JSON.stringify(result)}`;
}
};
};
export default {
plugins: [
vue(),
markdownPlugin({
highlight: (code: string) => {
if (code.includes('template')) {
return hljs.highlight('html', code).value;
} else if (code.includes('lang="ts"')) {
return hljs.highlight('typescript', code).value;
} else {
return hljs.highlightAuto(code).value;
}
}
})
]
}
Vite文档地址:vitejs.dev/
Lerna
Lerna是一个项目多包管理工具,虽然当前项目内的组件关联性不强,但也提前先引入了Lerna进行分包管理。
- 执行
npm run bootstrap
命令进行项目初始化. - 执行
npm run publish
命令可快速发包
更多Lerna的用法可参考:Lerna-如何优雅地管理多个npm包 - 知乎 (zhihu.com)
Rollup打包
组件库中各组件最终会使用Rollup进行打包,执行npm run build:pkg
打包各Packages,包含cjs、es和其d.ts文件。
使用nodejs执行rollup打包,代码位于scripts
目录下,build.js为打包初始模板,一个组件会被打包出3种格式:cjs
/esm
/umd
,格式说明参考格式。
其中类型文件则采用原生typescript
的declaration
生成d.ts
文件
打包的时候会自动读取packages
目录,各自单独打包出各格纹文件。
自动生成展示站点Vue路由
使用Vite打包时,Vue路由懒加载是基于Rollup的动态引入插件的,它对我原站点的格式不太适用。而由于展示站点中,各个路由格式是具有一定通用性的,所有采用了一种读取文件目录自动生成路由文件的方式。而在Vite中提供了Glob 导入方式,可以读取到文件目录。
// src/router/index.ts
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
const isHashRouterMode = import.meta.env.VITE_ROUTER_MODE === 'hash';
const packageMain = import.meta.glob('../pages/*/index.vue');
const exampleMain = import.meta.glob('../pages/*/example/*.vue');
const packageMainMap: Record<string, any> = {};
Object.keys(packageMain).map(key => {
const reg = /^.*pages/(.*)/index.*$/;
const pkg = key.replace(reg, (...args) => args[1]);
packageMainMap[pkg] = packageMain[key];
});
const router = createRouter({
history: isHashRouterMode ? createWebHashHistory() : createWebHistory('/howdy/'),
routes: [
{
path: '/',
name: 'home',
component: () => import('../views/home.vue')
},
...Object.keys(packageMainMap).map(pkg => {
const examples = Object.keys(exampleMain).filter(p => p.includes(pkg));
return {
path: `/${pkg}`,
name: `${pkg}`,
redirect: `/${pkg}/readme`,
component: packageMainMap[pkg],
children: [
{
path: `/${pkg}/readme`,
name: `${pkg}-readme`,
component: () => import('../components/PageReadme.vue')
},
...examples.map((example,index) => {
return {
path: `/${pkg}/example${index + 1}`,
name: `${pkg}-example${index + 1}`,
component: exampleMain[example]
};
})
]
};
})
]
});
export default router;
展示Vue文件源代码到页面
展示站点中会将各个Example的Vue源代码文件展示到页面上,再用highlightjs
进行代码高亮显示。
在翻阅官方文档后,Vite在import资源文件时写入?raw
可以将代码源文件直接读取出字符串,类似于webpack
中的raw-loader
功能。但再开发完打包部署后才发现会出现读取失败的情况,最后发现好像是rollup动态导入的问题。
相关ISSUES: Click here
最后暂时在开发启动或打包时直接将相关的Vue文件转换出Markdown文件。在项目中执行npm run vue-to-md
进行转换。相关代码很简单,只是这种方式实现热更新太麻烦,后面再看下怎么采用更合适的方案吧。
const fs = require('fs');
const glob = require('glob');
const classifys = fs.readdirSync('src/pages');
classifys.map(classify => {
fs.mkdirSync(`src/code/${classify}`, { recursive: true });
});
glob('src/pages/**/example/example*.vue', (err, files) => {
if (err) {
throw err;
}
files.map(file => {
const codeFileName = file.replace('pages', 'code').replace('example/', '').replace('vue', 'md');
const code = fs.readFileSync(file, 'utf8');
const output = `\`\`\`vue\n${code}\`\`\``;
fs.writeFileSync(codeFileName, output);
});
});
⚡其他说明
- 新版地址:Howdyjs
- 旧版地址:Howdyjs-old(兼容Vue2,目前不维护了)
- 用的是同一个github仓库,新版参考master分支,旧版参考howdy分支
- 欢迎Star,如果有问题或更好的idea欢迎Issue与PR。