umi插件开发仿dumi项目加载markdown文件实现详解

目录
  • 引言
  • 为什么不能直接展示markdown
    • chainWebpack
    • webpack loader
  • 实现过程
    • 新建插件
    • 新建loader
    • 新建测试文档
    • 运行项目
  • 解决文件加载类型错误
  • webpack ruletype
  • 解决错误

引言

前面章节中我们已经顺利将tsx组件转换为页面展示,但是目前提供的功能和umi的约定式路由功能差不多,接下来我们将实现将markdown文件转换为页面展示。

为什么不能直接展示markdown

我们前面所使用的页面写法都是react组件式写法,umi通过webpack将react组件打包,这是react项目通用的模式。由于webpack不认识markdown文件,所以我们直接引入markdown文件会报错。所以我们只需要让webpack认识markdown,通过自定义loader来加载markdown文件即可。

chainWebpack

umi提供chainWebpack插件api,通过 webpack-chain的方式修改 webpack 配置。

webpack loader

loader是用于webpack解析文件的工具,不同的loader可以解析不同类型的文件,使其解析的内容可被其他模块使用。

我们需要解析markdown文件,那么就需要写一个能认识markdown文件的loader,它的功能就是识别.md文件并将文件内容解析成对象返回给import这个文件的代码使用。

实现过程

新建插件

跟前面一样,我们新建一个插件来处理文件解析:

// /src/features/compile.ts
import type { IApi } from 'umi';
export default (api: IApi) => {
  api.describe({ key: 'domi:compile' });
  api.chainWebpack(async (memo) => {
    const loaderPath = require.resolve('../loaders/markdown/loader.js');
    memo.module
      // 通过链式处理,向`webpack`添加了一条名为`domi-md`的处理规则
      .rule('domi-md')
        // 该规则用于处理`.md`文件
        .test(/\.md$/)
        // 给这个loader取个名字
        .use('md-loader')
        // loader的路径
        .loader(loaderPath)
    return memo;
  });
};

新建loader

接下来创建loader文件,注意这里loader要使用js文件,因为webpack无法直接解析ts类型的loader,第一个入参是文件内容的字符串形式,我们先直接返回。

// /src/loaders/markdown/loader.js
function mdLoader(context) {
    return context
}
module.exports = mdLoader

为什么`dumi`的loader是用`ts`写的?

因为在`dumi`开发环境下,先将`ts`文件转成了`js`,`webpack`在运行时其实还是加载的`js`形式的loader。

dumi: 编译 => 启动umi(webpack) => 开发环境

domi: 启动umi(webpack) => 开发环境

新建测试文档

// /docs/markdown.md
# 我是markdown

运行项目

启动项目可以看到markdown文件已经正确解析到导航栏中了

点开链接一看,啥也没有,报错了

解决文件加载类型错误

看上面的报错信息,意思好像是懒加载的组件元素类型错误,打开请求列表看看加载了什么东西

应该就是这里在加载markdown文件时,只导出了个url链接,我们打开链接看看

这里就返回了markdown内容,看来目前不能直接从页面打开。

我们换一种方式,在jsx中直接导入这个文件看看:

// /docs/index.tsx
import react from 'react'
import md from './markdown.md'
const Home = () => {
    return (<div>hello domi! {md}</div>)
}
export default Home

刷新页面可以看到,import进来的对象确实只是一个地址,那我们直接放个iframe来显示:

// /docs/index.tsx
import react from 'react'
import md from './markdown.md'
const Home = () => {
    return (<>
        <div>hello domi!</div>
        <iframe src={md} />
    </>)
}
export default Home

哈哈终于显示出来了

webpack ruletype

当然上面并不是我们想要的效果,从前面的尝试大概能判断出来是webpack在打包时并没有想我们想象那样能直接导出我们想要的对象。这时候我们就要使用webpack一个配置ruletype,告诉他我们想要将markdown文件import成一个包含正文内容的对象,而不是一个资源地址。

这里webpack将文件视为Resource资源,其将所有 .md 文件都发送到输出目录,并且其路径将被注入到 bundle中,与我们常使用的在jsx中导入图片等一样,具体可参考资源模块 | webpack 中文文档 (docschina.org)

要改变这一默认行为,只需要配置时改变资源类型即可

// /src/features/compile.js
api.chainWebpack(async (memo) => {
    const loaderPath = require.resolve('../loaders/markdown/loader.js');
    memo.module
        .rule('domi-md')
            .test(/\.md$/)
            // 表示文件经过这个loader处理后转换为可导入的js模块
            .type('javascript/auto')
            .use('md-loader')
            .loader(loaderPath)
    return memo;
});

重启后运行,发现又报了另一个错误

解决错误

从报错上看,意思大概是.md文件在经过loader解析后,解析返回值失败,还告诉我们可能需要其他loader来处理返回值。

这个就比较好理解了,因为上面我们指定了经过loader处理后应该返回一个可导出的js模块,而我们目前loader只返回了markdown的正文内容,并不是js数据,所以我们只需要改动以下loader的返回值即可:

// /src/loaders/markdown/loader.js
function mdLoader(content) {
  return `
      const content = '${JSON.stringify(content)}'
      export default { content };
  `
}
module.exports = mdLoader

此时经过loader处理后,将会导出一个带有content属性的对象,再改变一下导入展示的组件:

import react from 'react'
import md from './markdown.md'
const Home = () => {
    return (<div>hello domi! {md.content}</div>)
}
export default Home

重启后可以看到如下所示,此时我们已经成功通过loader加载到markdown文件显示

以上就是umi插件开发仿dumi项目加载markdown文件实现详解的详细内容,更多关于umi插件加载markdown文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 一文详解JavaScript 如何将 HTML 转成 Markdown

    目录 npm script 参数配置 前言: 本篇带来:在 JavaScript 如何将 HTML 转成 Markdown?先收藏,总有一天要用到!! npm 我们主要是借助 Turndown这个库来实现的 npm 安装 npm i turndown es6 import 引入: import TurndownService from 'turndown' CommonJs require 引入: const TurndownService = require('turndown'); 接下来我

  • unified如何处理markdown解析器详解

    目录 unified是什么 unified生态简介 工作原理 Parse Transform Stringify 牛刀小试 环境搭建 处理ESM类型包 最简用法 加载文档meta 一个实际使用例子: unified是什么 unified是用于文档处理的生态系统,核心包提供了文档处理的流程控制,具体功能由生态系统中各个插件提供.例如我们如果需要处理markdown,就需要使用markdown处理相关的插件.当然除了markdwon以外,还提供了处理HTML.JSX等的插件.其良好的扩展能力能让我们

  • glow工具在命令行读取Markdown好物分享

    目录 写在前面 准备工作 Glow的安装和使用 安装 使用 写在最后 写在前面 这篇文章推荐一个由Golang编写的一个命令行工具——Glow,这个CLI工具可以在命令行读取Markdown,Markdown对于码农来说也是非常重要的,几乎所有的文档全部都有Markdown的身影. 笔者热衷于使用命令行,感觉命令行使用起来非常舒爽,有的时候需要阅读Markdown,但是cat命令并没有加粗什么的,展示的Markdown阅读起来也不是很友好,这里推荐Glow来舒适的展示Markdown,效果图如下

  • Vue如何整合mavon-editor编辑器(markdown编辑和预览)

    目录 简介 说明 官网网址 使用编辑功能 代码 使用预览功能 结果展示 简介 说明 本文介绍Vue如何使用markdown编辑器. mavon-editor是目前比较主流的markdown编辑器,本文介绍它的使用方法. 官网网址 https://github.com/hinesboy/mavonEditor 安装mavon-editor依赖 npm install mavon-editor -P 注册mavon-editor编辑器 在main.js中加入如下内容: import mavonEdi

  • Vue3解析markdown并实现代码高亮显示的详细步骤

    目录 具体实现步骤如下: 一.安装依赖库 二.在main.js文件中引入highlight.js及样式并创建一个自定义的全局指令 三.在Vue组件中应用marked解析及实现代码高亮 四.显示效果 Vue实现博客前端,需要实现markdown的解析,如果有代码则需要实现代码的高亮.Vue的markdown解析库有很多,如markdown-it.vue-markdown-loader.marked.vue-markdown等.这些库都大同小异.这里选用的是marked,代码高亮的库选用的是high

  • 一个HTML标签教你实现带动画的抖音LOGO效果

    目录 大家好,我是零一,今天给大家表演 仅用一个HTML标签实现带动画的抖音LOGO,涉及了很多知识点,欢迎交流讨论 先上结果,最终实现效果如下: 还原度应该还可以吧? 抖音Logo结构 想要用CSS来画抖音的Logo,前提要先了解它的构造,一定是一些几何图形的拼接组合,因为之前很多业界大佬已经扒过抖音的Logo的结构了,我就拿来借用一下: 好的,有点复杂,简化一下,其实就是 4 个部分 每个颜色划出来的区域代表一个部分,所以最后是:1/4圆环 + 半圆 + 长条矩形 + 半径略大一些的1/4圆

  • umi插件开发仿dumi项目实现markdown文件转为页面

    目录 引言 处理导入错误 loader返回渲染函数 添加react处理loader 用ts来写loader 改变原来的loader 创建新的loader 配置webpack 引言 前面我们已经成功将.md文件通过import加载到react组件中,并能拿到文件内容进行展示.但是点击markdown的导航链接还是会报错: 这个报错和前面的报错有点相似,只是前面是无法解析链接,这里是无法解析对象. 处理导入错误 在react渲染页面时,是调用一个个渲染函数来渲染页面,我们来对比一下button页和m

  • umi插件开发仿dumi项目加载markdown文件实现详解

    目录 引言 为什么不能直接展示markdown chainWebpack webpack loader 实现过程 新建插件 新建loader 新建测试文档 运行项目 解决文件加载类型错误 webpack ruletype 解决错误 引言 前面章节中我们已经顺利将tsx组件转换为页面展示,但是目前提供的功能和umi的约定式路由功能差不多,接下来我们将实现将markdown文件转换为页面展示. 为什么不能直接展示markdown 我们前面所使用的页面写法都是react组件式写法,umi通过webpa

  • umi插件开发仿dumi项目实现页面布局详解

    目录 实现思路 使用默认项目提供的layout文件 自定义主题 准备工作 主题插件功能 modifyAppData 插件代码 生成layout路由对象 使用同步伪代码来描述上面流程 运行检查 实现思路 上一章我们已经完成/docs目录下文件自动生路由功能,本章我们将在此基础上,实现自动生成页面导航的功能. 使用默认模板提供的layout展示路由切换 使用自定义主题插件 使用默认项目提供的layout文件 在我们创建默认umi项目后,会在/src/layouts下生成一个布局文件: 同时在上一章节

  • PHP框架自动加载类文件原理详解

    描述:公司项目PHP用作中间转发层(接收http请求,用 socket跟c++做通信),由于代码没有用到框架,这些东西自然就是之前的人自己写的.最近需要对这个底层进行优化,于是便看了下这部分的代码. 目的:这块代码的主要作用是把主目录下的所有插件类一次性全部加载进来.当使用尚未被定义的类(class)和接口(interface)时自动去加载.通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类. 实现方法:主要用到PHP函数__autoload() 详细: error_

  • vue 项目常用加载器及配置详解

    本文介绍了vue 项目常用加载器及配置详解,分享给大家,具体如下: 1.安装sass: 1.1 由于sass-loader依赖于node-sass,所以在安装sass-loader的同时还需安装node-sass npm install --save-dev node-sass npm install --save-dev sass-loader 1.2 安装完成后修改 <style>标签: <style lang="scss"></style> 2

  • 基于Vue渲染与插件的加载顺序的问题详解

    Vue实践分享(三)在实际项目的开发过程中,经常会遇到页面还没渲染完成而插件就已经开始加载的问题,这样就会导致显示和功能出错. 可以通过Vue中的nextTick来解决 Vue.nextTick(function() { //widget }); 这样就会在页面渲染完成后再执行nextTick内的插件 以上这篇基于Vue渲染与插件的加载顺序的问题详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: 浅谈Vue的加载顺序探讨 Vue.js学习教程

  • Vue首页界面加载优化实现方法详解

    目录 1.路由懒加载 2.js 资源异步加载 3.图片懒加载 4.组件分包懒加载-在视口才加载 1.路由懒加载 问题: 项目在打包时会将首页与其他页面的资源打包到同一个资源文件,造成首页加载的资源文件过大. 解决方法: 路由懒加载:打包时会将每个路由页面拆分成单独的 js 资源,同时跳转到对应页面才会加载对应路由的 js 资源. { path: "/about", name: "about", component: () => import(/* webpac

  • Android 动态加载 so实现示例详解

    目录 背景 so动态加载介绍 从一个例子出发 so库检索与删除 动态加载so 结束了吗? ELF文件 扩展 总结 背景 对于一个普通的android应用来说,so库的占比通常都是巨高不下的,因为我们无可避免的在开发中遇到各种各样需要用到native的需求,所以so库的动态化可以减少极大的包体积,自从2020腾讯的bugly团队发部关于动态化so的相关文章后,已经过去两年了,相关文章,经过两年的考验,实际上so动态加载也是非常成熟的一项技术了. 但是很遗憾,许多公司都还没有这方面的涉略又或者说不知

  • 详解polyfills如何按需加载及场景示例详解

    目录 前言 青铜时代 火枪时代 webpack添加babel-loader @babel/preset-env @babel/polyfill 配置 useBuiltIns 加入 @babel/plugin-transform-runtime 前言 青铜时代 最使前端头痛的问题,莫过于浏览器兼容性,无论是js,还是css都要考虑浏览器兼容性问题,在webpack出来之前,这无非是一个非常头疼的问题,查到一个兼容性问题,查找很多资料,解决一下,再出来一个问题又要花很长时间解决一下,这无疑要花费很长

  • linecache模块加载和缓存文件内容详解

    linecache模块 接触到linecache这个模块是因为前两天读attrs源码的时候看到内部代码引用了这个模块来模拟一个假文件,带着一脸疑问顺便读了一下这个模块的源码,发现其实也就那么回事儿,代码不多,在这总结一下. linecache模块可以读取文件并将文件内容缓存起来,方便后面多次读取.这个模块原本被设计用来读取Python模块的源代码,所以当一个文件名不在指定路径下的时候,模块会通过搜索路径(search path)来尝试读取文件. 接口 linecache模块的__all__参数其

随机推荐