【vite+vue3.0】基于vite写一个将md文件渲染为js文件的插件
基于vite写一个将md文件渲染为js文件的插件前言尤大是这么描述 Vite 的:「一个基于浏览器原生 ES imports 的开发服务器。利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。针对生产环境则可以把同一份代码用 rollup 打包。」这篇博客笔者想分享编
基于vite写一个将md文件渲染为js文件的插件
前言
尤大是这么描述
Vite
的:
「一个基于浏览器原生 ES imports 的开发服务器。
利用浏览器去解析imports
,在服务器端按需编译返回,完全跳过了打包这个概念,
服务器随起随用。
同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。
针对生产环境则可以把同一份代码用 rollup 打包。」
这篇博客笔者想分享编写Vite
插件【md文件渲染为js文件】的技术栈:md插件源码地址
相关文章
技术栈
VUE3.0
前端主流框架(react,vue,angular)之一,更适合开发灵活度高且复杂的应用vue-router
Vue.js 官方的路由管理器vite
是一个由原生 ESM 驱动的 Web 开发构建工具github-markdown-css
一个轻量级CSS库代替GitHub Markdown文件样式marked
一个 JavaScript 编写的全功能 Markdown 解析和编译器rollup
一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码
vite插件概念
笔者写这篇文章的时候,还没有关于如何编写 Vite
插件的官方文档。所以,目前只能通过阅读 Vite
源代码,来深入了解如何编写插件。
我们需要先来明确一些相关概念,方便后续的工作:
- 开发服务器(dev server):浏览器可以处理 js 文件的 ES 模块导入。
但不能直接处理其他文件类型的 import
。每次浏览器在代码中遇到 import
的时候,会先通过 Vite
的 dev 服务器编译,然后直接提供给浏览器。
比如:*.vue
文件会先在开发服务器编译,再发送给浏览器。
这些 import
可以是 javascript,vue,css 文件。也可以是其他类型的文件,不过需要在 vite
中指定变异工具。
这就是为什么 Vite
开发服务器如此有用 —— 它解决了浏览器的限制。
-
rollup 生产包(rollup production bundle):对于静态内容,在生产版本中没有
vite
开发服务器可用。所以,vite
使用rollup
打包生产环境的代码。 -
自定义块(custom block):有时候,你使用的其他库可以向
vue
文件中添加自定义块,例如<docs>
或<story>
。可以使用 Vite 来制定如何处理自定义块。
创建初始插件
Vite插件
只是一个对象,我们可以先返回一个空对象。
创建一个用作为插件的js文件plugins/md.ts
:
export function md() {
return {}
}
然后,在 vite.config.js
这样使用:
import { md } from "./plugins/md";
export default {
plugins: [md()],
}
细心的小伙伴可能会发现,我们导出了一个函数而不是对象。 这是为了方便以后在插件中添加自定义选项。
比如:想实现指定一个自定义MD文件样式功能,可以这样 viteAutoRoute({ h1_color: 'red' })
开发环境
现在,来使用我们之前创建的那些md文件。
使用 vite
插件的选项configureServer
:
// @ts-nocheck
import path from "path";
import fs from "fs";
import marked from "marked";
const mdToJs = (str) => {
const content = JSON.stringify(marked(str));
return `export default ${content}`;
};
export function md() {
return {
configureServer: [
// 用于开发
async ({ app }) => {
app.use(async (ctx, next) => {
// koa
if (ctx.path.endsWith(".md")) {
ctx.type = "js";
const filePath = path.join(process.cwd(), ctx.path);
ctx.body = mdToJs(fs.readFileSync(filePath).toString());
} else {
await next();
}
});
},
]
};
}
首先,创建一个函数 mdToJs
,其中包含路由 js 文件的所需内容,主要功能是使用marked.js库
将字符串渲染为标准的md文件。然后,我们创建 configureServer
一个数组,用于 vite
dev 服务器中的中间件。
每当 vite
导入 javascript 或者 vue 文件的时候,它都会向该文件发送请求到其 dev 服务器,在必要时进行一些转换,然后以浏览器可以处理的形式发送回去。
当它遇到类似import Intro from "./markdown/intro.md";
,
它会要求文件后缀名为.md
。
因此,我们要做的是拦截该请求并返回我们生成 moduleContent
的主体,并将其 type
声明为 js
。
最后,我们将此 configureServer
数组添加到返回的对象中,以供 Vite
使用。
Vite
看到这一点后,将我们的列表(共1个)中间件与自己的中间件合并。
现在,我们可以就在自己的Markdowm
组件中使用这些使用md文件啦:
<template>
<article class="markdown-body" v-html="content"></article>
</template>
<script lang="ts">
import { ref } from "vue";
export default {
props: {
content: {
type: String,
required: true,
},
},
};
</script>
现在,我们可以运行 yarn dev
来查看路由是怎么工作的, http://localhost:3000/#/doc/intro
。
生产环境
不过,当我们运行 yarn build
它时,它不会使用我们刚刚完成的 configureServer
, 因为在生产环境中它使用 rollup
编译而不是 Vite
的 dev 服务器。
因此,我们需要添加一些其他配置让它其在生产环境中也能正常工作:
// @ts-nocheck
import path from "path";
import fs from "fs";
import marked from "marked";
const mdToJs = (str) => {
const content = JSON.stringify(marked(str));
return `export default ${content}`;
};
export function md() {
return {
// 这块是之前定义的 configureServer 代码
transforms: [
{
// 用于 rollup // 插件
test: (context) => context.path.endsWith(".md"),
transform: ({ code }) => mdToJs(code),
},
],
};
}
在这里,我们使用了 vite
的插件选项 transforms
。这使我们可以定义 rollup
的插件功能。
我们使用带有.md
后缀名的模块,并返回需要的 js 内容。
本质上,它和开发服务器做的是相同的事情。
现在,我们的自动路由在本地开发中和生产环境中都起作用啦。
路由渲染
插件完成后,通过h函数渲染到对应的页面中。
import Intro from "./markdown/intro.md";
import Install from "./markdown/install.md";
import Getstarted from "./markdown/get-started.md";
import { h } from "vue";
import Markdown from "./components/Markdown.vue";
const md = (string) => h(Markdown, { content: string, key: string });
const history = createWebHashHistory();
export const router = createRouter({
history: history,
routes: [
{ path: "/", component: Home },
{
path: "/doc",
component: Doc,
children: [
{ path: "", redirect: "/doc/intro" },
{ path: "intro", component: md(Intro) },
{ path: "get-started", component: md(Getstarted) },
{ path: "install", component: md(Install) },
],
},
],
});
总结
希望大家有了解到 Vite
的工作原理,还有如何编写一些基本的插件。
下面是完整功能代码的地址:
kaite-ui官网页面:kaite-ui官网页面
github开源地址:github开源地址
更多推荐
所有评论(0)