实现
大概讲一下要实现的功能,就两点:
- 组件库能打包并发布npm(作者比较懒,只教打包,npm发布难不倒大家)
- 编写md文档,能在vue项目中显示出来
思路
- 打包vue组件用到rollup构建工具(是一款ESModule打包器,可以理解为简易版webpack,作者懒,可以自行百度了解)
- 想要解析md文档需要自己写loader实现,因为webpack提供的loader不合适做组件库,作者比较懒,不写,拷贝了element-ui的md-loader源码,有兴趣的可以自己手写
开始
搭建项目
搭建项目作者是直接用vue脚手架,vue-cli用的是vue2的版本,脚手架怎么安装自己百度,作者比较懒,这里不教,安装完脚手架vue-cli
之后我们就开始创建项目,先执行下面的指令就会出现以下图片的界面
vue ui
点击左上角,选择项目管理器,来到创建项目这个页面
这里我没有选择ts,需要的可以自己选择,一顿操作下来,项目就创建好了,先跑起来看看
熟悉的界面,接下来开始将md文件解析并放在vue项目中显示出来
md-loader实现渲染出页面
首先在src同级目录下新建一个build文件夹(作者也不知道取什么名字),再新建一个md-loader文件夹
随便在index.js里面写点东西
module.exports = function(source) {
return `
<template>
<div>渲染的md文档</div>
</template>
`;
};
然后来到vue.config.js里面添加一点代码,主要是匹配以.md结尾的文件通过刚刚写的loader处理
const { defineConfig } = require("@vue/cli-service");
const path = require("path");
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack: (config) => {
config.module
.rule("md")
.test(/\.md/)
.use("vue-loader")
.loader("vue-loader")
.end()
.use(path.resolve("./build/md-loader/index.js"))
.loader(path.resolve("./build/md-loader/index.js"))
.end()
},
});
然后我们来到src这个目录,新建一个文件夹docs,里面存放的都是md文档,我们继续随便写点东西,
然后去app.vue引入md文件,注释或删除多余的,将它当做组件去使用
这个时候看看页面,你会发现他显示出来了md-loader返回的
接下来我们去复制element-ui/build文件下的md-loder源码里面的md-loader覆盖我们原来的(他的有代码演示和隐藏展开代码)
接下来我们去看看他们代码里面有没有用到其他包,我们需要安装使用,如下图是我看到的几个包
查看之后发现除了vue-template-compiler其他包都没有,执行以下指令安装
yarn add @vue/component-compiler-utils markdown-it-chain markdown-it-anchor transliteration markdown-it-container -D
安装完成之后重新跑一次项目,发现报错了,检查之后发现还有个包没装
再执行一次安装指令
yarn add markdown-it -D
查看以下项目执行效果,发现我们写在md文档上的文字都能显示出来了,左边的图标是怎么回事呢,看了一下element组件库的文档,发现是他也有的,那我们不管
我们去参考一下element是怎么写演示代码的,路径:examples\docs\zh-CN里面很多md文件,随便打开一个
我们只需要选框中的那一块,复制到我们的md文档,因为我们还没组件,所以改造一下
## 测试测试测试
:::demo 测试`demo`。
```html
<template>
<div>折叠的代码</div>
</template>
\```
:::
啊不会写,上面的代码被砍掉了,加了个\不然他结束
保存看一下效果,发现不是我们想要的效果,看一下控制台发现报错了,原来我们少了一个组件demo-block,这个组件我们去element源码里面复制,路径:\examples\components,把里面的所有文件都复制过来(比较懒,懒得挑,怕少了文件)
新建一个mdConfig文件夹,统一管理md文档的东西
去看一下demo-block文件看到里面还引入其他文件
直接去element拷贝过来
至于Element这个模块,我们要用到我们自己的组件库,在路径:src/components下新建一个
Button
的文件夹和一个index.js
(统一管理我们的组件),Button里面新建一个index.vue
和index.js
三个文件的代码分别是:
Button/index.vue
<template>
<div class="btn">按钮</div>
</template>
<script>
export default {
name:"MyButton"
}
</script>
<style>
</style>
Button/index.js
import Button from "./index.vue"
Button.install = function(Vue) {
Vue.component(Button.name, Button)
}
export default Button
index.js
import Button from "./components/Button/index";
const components = [Button];
const install = function (Vue) {
components.forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default { install, Button, version: "1.0.0" };
修改demo-block指向我们新建的组件库
import Element from '../../components/index';
再到main.js里面全局注册我们的demo-block组件
import DemoBlock from './mdConfig/components/demo-block.vue'
...
Vue.component("demo-block", DemoBlock)
保存执行之后报错了,我们修改一下demo-block.vue组件里面的langConfig,将他里面的this.lang写死成zh-CN
langConfig() {
return compoLang.filter(config => config.lang === "zh-CN")[0]['demo-block'];
},
再去看一下效果发现代码正常能折叠了,还能在线运行,看控制台还有报错,原来是里面还用了element的组件,我这里不管他
rollup打包代码
在根目录新建一个rollup.config.js文件,并下载相关依赖
yarn add rollup rollup-plugin-vue rollup-plugin-terser glob@7.1.4
在package.json增加命令:
"scripts": {
"serve": "vue-cli-service serve",
"build:docs": "vue-cli-service build",
"build": "rollup -c"
},
rollup.config.js
const vue = require("rollup-plugin-vue");
const { terser } = require("rollup-plugin-terser");
module.exports = [
{
input: "./src/components/Button/index.js",
output: [
{
file: "es/button.js",
format: "es",
},
],
plugins: [
vue({
css: true,
compileTemplate: true,
}),
terser(),
],
},
];
先打包一下Button这个组件看一下效果,执行yarn build
;
打包完成会生成一个es/button.js,我们去main.js打印看一下生成的组件是否可用
控制台打印看到我们的对象正常,证明打包成功,但只能打包一个组件,如果需要打包多个,就在数组里面添加多个 利用global可获取所有的组件,通过遍历去改造成数组,以下是改造后的js,想要将所有的组件打包到一个index下要单独打包index.js文件
const vue = require("rollup-plugin-vue");
const { terser } = require("rollup-plugin-terser");
const glob = require("glob");
const path = require("path");
const files = glob.sync(path.join(__dirname, "./src/components/**/*.js"));
const components = files.map((item) => {
let nameArr = item.split("/");
let name = nameArr[nameArr.length - 2];
return {
input: item,
output: [
{
file: `es/${name.toLowerCase()}.js`,
format: "es",
},
],
plugins: [
vue({
css: true,
compileTemplate: true,
}),
terser(),
],
}
});
module.exports = components
修改一下demo-block.vue下的goCodepen,让他的script指向打包后的文件index,
const resourcesTpl = '<scr' + 'ipt src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.js"></scr' + 'ipt>' +
'\n<scr' + `ipt src="http://127.0.0.1:5500/es/index.js"></scr` + 'ipt>';
去mian.js将我们的组件安装上
import MyComponents from "../es/index"
Vue.use(MyComponents)
然后去md文档使用,发现成功了
结尾
后期的样式界面可以自己调整,作者比较懒,就这样吧,功能实现了
至于npm发布需要的话留言,或者百度了解
补充一下package.json代码,避免安装版本问题导致错误
{
"name": "vue-components-demo2",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build:docs": "vue-cli-service build",
"build": "rollup -c"
},
"dependencies": {
"core-js": "^3.8.3",
"glob": "7.1.4",
"rollup": "^3.2.3",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-vue": "5.1.9",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"@vue/component-compiler-utils": "^3.3.0",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.5",
"markdown-it-chain": "^1.3.0",
"markdown-it-container": "^3.0.0",
"sass": "^1.32.7",
"sass-loader": "^12.0.0",
"transliteration": "^2.3.5",
"vue-template-compiler": "^2.6.14"
}
}