当前位置: 首页 > ops >正文

解决Vditor加载Markdown网页很慢的问题(Vite+JS+Vditor)

1. 引言

在上一篇文章《使用Vditor将Markdown文档渲染成网页(Vite+JS+Vditor)》中,详细介绍了通过Vditor将Markdown格式文档渲染成Web网页的过程,并且实现了图片格式居中以及图片源更换的功能。不过,笔者发现在加载这个渲染Markdown网页的时候特别慢,本文就总结一下这个问题。

2. 详论

2.1 解决方案

经过笔者的调试发现,性能损耗主要是Vditor使用的一个依赖库文件lute.min.js加载很慢,这个文件大概有3.6M大小,并且放在了远端在线资源上。lute.min.js是一个Markdown引擎,Vditor默认是将其放到CDN上,具体使用的就是Cloudflare(传说中的赛博活佛😆)。理论上就是因为资源文件比较大才需要使用CDN,但是因为一些原因Cloudflare在国内的连接速度并不快。所以没办法,这里还是得将这些资源地址改回成域内,除非你有自己的CDN。

在Vditor官方论坛上找了类似的问题1,回帖指出需要按照官方的开发指南2进行CDN参数配置,如下所示:
Vditor官方的开发指南中的CDN参数配置
具体来说,就是在Vditor.preview接口中增加cdn的配置:

Vditor.preview(document.getElementById("md-content"), demoMd, {cdn: window.location.origin,    //配置CDNmarkdown: {toc: false,mark: true, //==高亮显示==footnotes: true, //脚注autoSpace: true, //自动空格,适合中英文混合排版},math: {engine: "KaTeX", //支持latex公式inlineDigit: true, //内联公式可以接数字},hljs: {style: "github", //代码段样式lineNumber: true, //是否显示行号},anchor: 2, // 为标题添加锚点 0:不渲染;1:渲染于标题前;2:渲染于标题后lang: "zh_CN", //中文theme: {current: "light", //light,dark,light,wechat},transform: (html) => {// 使用正则表达式替换图片路径,并添加居中样式及题注return html.replace(/<img\s+[^>]*src="\.\/([^"]+)\.([a-zA-Z0-9]+)"\s*alt="([^"]*)"[^>]*>/g,(match, p1, p2, altText) => {// const newSrc = `${backendUrl}/blogs/resources/images/${postId}/${p1}.${p2}`;const newSrc = `${p1}.${p2}`;const imgWithCaption = `<div style="text-align: center;"><img src="${newSrc}" class="center-image" alt="${altText}"><p class="caption">${altText}</p></div>`;return imgWithCaption;});},
});

同时,还需要进行项目的配置,让这个前端项目能找到托管的CDN资源。根据开发指南的说明,托管的CDN资源不仅仅只有lute.min.js,还有其他资源文件,因此需要将这些文件都拷贝到特定的目录。那么就需要修改项目的配置,增加一个执行拷贝任务的脚本。

2.2 开发环境

不过由于拷贝文件的指令在不同的平台终端是不同的,因此最好引入一个中间件帮助统一一下指令的行为。这里使用Shx,它可以帮助我们在npm环境中跨平台执行类似于Unix样式的指令。在终端安装Shx:

npm install shx --save-dev

修改package.json:

{"name": "my-native-js-app","private": true,"version": "0.0.0","type": "module","scripts": {"copy:vditor": "shx mkdir -p dist && shx cp -r node_modules/vditor/dist/* dist","dev": "vite","build": "vite build --emptyOutDir","preview": "vite preview"},"devDependencies": {"shx": "^0.4.0","vite": "^6.3.5"},"dependencies": {"handlebars": "^4.7.8","vditor": "^3.11.0"}
}

增加的脚本copy:vditor具体就是指令:

npm run copy:vditor

具体意思就是创建目录dist,然后将目录node_modules/vditor/dist中的所有文件复制到这个dist目录中。然后正常执行dev指令:

npm run dev

理论上copy:vditor指令是可以合并到dev指令中的,也就是每次dev之前都执行copy:vditor。不过笔者还是觉得将其作为一次性命令更好,可以让程序启动得更快。

2.3 发布环境

我们知道,如果要正式发布项目的话,就需要先进行构建:

npm run build

然后再发布:

npm run preview

因此拷贝资源操作的脚本可以合并到build这一步中。这里,笔者介绍另外一种配置项目方法,就是使用Vite的配置文件vite.config.js。package.json是Web项目的基础配置文件;vite.config.js则是Vite的配置文件,用于自定义Vite的行为:例如配置服务器端口、代理,插件支持以及环境变量等等。这里就在项目根目录新建一个vite.config.js文件,内容如下:

// vite.config.js
import { defineConfig } from "vite";
import copy from "rollup-plugin-copy";export default defineConfig(() => {return {server: {host: "0.0.0.0", // 绑定所有网络接口port: 8000, // 自定义开发服务器端口open: true, // 自动打开浏览器},build: {rollupOptions: {plugins: [copy({targets: [{ src: "node_modules/vditor/dist/*", dest: "dist/dist" }],hook: "writeBundle", // 在 writeBundle 阶段执行复制操作}),],},},preview: {host: "0.0.0.0", // 绑定所有网络接口port: 8001, // 预览服务器端口open: true, // 自动打开浏览器},};
});

在这里的配置中,server字段和preview字段分别定义了开发模式dev和发布模式preview的网络地址和端口,并且设置执行完成后自动打开默认浏览器。build字段则配置在打包(rollup)代码的时候,通过插件rollup-plugin-copy执行拷贝操作,将目录node_modules/vditor/dist下的所有文件拷贝到dist/dist目录下。当然,插件rollup-plugin-copy需要进行安装:

npm install rollup-plugin-copy --save-dev

3. 结语

笔者这里开发模式和发布模式使用了两种不同的项目配置方法,来拷贝本地资源到特定目录。通过设置域内CDN,解决Vditor加载Markdown网页很慢的问题。理论上应该有更加优雅的方式,但是笔者这里是够用了,暂时不进行进一步研究。其实项目构建配置的问题没必要特意去学,首先还是要思考如何更方便地构建项目,自然而然就会去尝试解决方案,慢慢就学会项目构建配置的技能了。

实现代码


  1. 最近使用 vditor,遇到一个问题,请求 lute.min.js 的 cdn 总是请求不通导致 markdown 用不了怎么处理 ↩︎

  2. Vditor 一款浏览器端的 Markdown 编辑器,支持所见即所得(富文本)、即时渲染(类似 Typora)和分屏预览模式 ↩︎

http://www.xdnf.cn/news/10878.html

相关文章:

  • 二分查找和二分答案(基础)
  • C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
  • 【Doris基础】Apache Doris中的Fragment概念详解
  • 探索NautilusTrader:下一代开源算法交易平台的革命性突破
  • 智能光子系统的多任务优化---案例:基于双贝塞尔曲线的紧凑多模光学波导弯曲
  • Dify:启动 Web 服务的详细指南
  • 爱耕云课时管理系统评测
  • SpringBoot项目打包成war包
  • Linux文件系统:从VFS到Ext4的奇幻之旅
  • Linux中断与异常:内核的事件驱动引擎
  • C++初赛的三讲
  • 【MSCKF】UpdaterSLAM::delayed_init 和 FeatureInitializer::single_triangulation
  • 安全编码规范与标准:对比与分析及应用案例
  • Python(十五)
  • 云服务器宕机或重启后数据会丢失吗?
  • 公司存储文件用什么比较好?
  • 笔记:算法题目中需要处理 int 某个位的三种方法:for、while、to_string
  • 免费开源Umi-OCR,离线使用,批量精准!
  • Qt企业级串口通信实战:高效稳定的工业级应用开发指南
  • leetcode hot100(两数之和、字母异位词分组、最长连续序列)
  • PyTorch--池化层(4)
  • Win11系统不推送24H2/西数SSD无法安装24H2 - 解决方案
  • C++:内存管理
  • Baklib内容中台AI重构智能服务
  • STM32与GD32标准外设库深度对比
  • AI 驱动的案例分流:几分钟内构建并部署
  • 【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(5)
  • C# Onnx 动漫人物人脸检测
  • 英福康INFICON VGC501, VGC502, VGC503 单通道、双通道和三通道测量装置
  • Linux入门(十四)rpmyum