Webpack加载markdown文件内容
前言
本文适合使用create-react-app(下文称之为cra)创建的项目,是react官方脚手架,内部由react-scripts支持;
markdown是一种轻量级的富文本文件类型,按照惯例,加载不同类型的文件,我们需要在webpack中配置对应的loader实现;
因为cra默认是将所有的配置都封装在react-scripts中,默认没有给我们提供对应的修改入口,要是我们修改的话有两个途径:
1、使用eject将webpack的配置释放出来;
2、借助插件重写启动脚本加载自定义配置;
因为eject操作是不可逆的,并且会导致react-scripts后期无法升级,所以我们第2种方法。
我们要借助一个插件(customize-cra)去实现。
实现
1. 安装依赖
yarn add customize-cra react-app-rewired markdown-loader html-loader@1 -D
说明:
- customize-cra 自定义cra配置的插件,提供了很多的工具方法;
- react-app-rewired 替换react-scripts的启动工具;
- markdown-loader 负责将md文件转化成html;
- html-loader 加载转化之后的html(这里的html-loader一定要装版本v1,否则会报错:this.getOptions is not a function;)
2. 修改配置
接下来我们创建或者修改项目根目录下的config-overrides.js
文件,文件名不要随便写;
customize-cra提供的override方法可以允许我们修改配置并返回,当然customize-cra还提供了很多便捷的方法,因为官方没有给出自定义loader的方法,所以我们这次只研究自定义loader的部分;
通过debug查看react-scripts生成的webpack配置,我们可以看到以下的信息,包括loader、plugins、entry等,这里的所有都是可以修改的。
本次的需求是加一个文件类型的解析,我们就需要看看加在什么地方才能生效;
仔细观察上图高亮的两部分:
1、最外层的加载规则,分别配置了parser、js模块、其他文件类型处理;
2、oneOf中处理了除去js文件类型的所有配置,根据oneOf的匹配规则,要是匹配到其中的规则就不会继续向下匹配了。
分析以下:
1、如果将markdown-loader放在标注1的 rules[0]和rules[1] 之间,虽然能解析成功,但是也会匹配下面的oneOf中的规则,最后发现生效的oneOf[9]的规则,所以我们必须要放在oneOf中配置
2、如果放在oneOf的最后,当然还是匹配到了oneOf[9],还是达不到效果,所以必须放在oneOf[9]之前的任意位置即可
根据上面的分析,我们添加配置,我们就将markdown的解析放在oneOf的第一个就行,具体配置如下:
const {override} = require("customize-cra");
module.exports = {
webpack: override(config => {
// 先找到oneOf下面所有的loader
const oneOfLoaders = config.module.rules.find(rule => Array.isArray(rule.oneOf)).oneOf;
// 一定要放到oneOf的最前面,否则没有效果,详细可以查看oneOf的具体作用
// 不放到最前面的话,就会当作media处理,输出的media下面的文件
oneOfLoaders.unshift({
test: /\.md$/,
use: [{
loader: 'html-loader',
}, {
loader: 'markdown-loader',
options: {}
}]
});
return config;
})
};
修改启动脚本
修改package.json启动脚本,加载自定义配置文件,react-app-rewired和react-scripts使用方法一致
{
"scripts": {
"start": "react-app-rewired start"
}
}
加载md文件
然后在文件中直接使用markdown就可以了,使用实例如下:
import React from "react";
import BaseModal from "../BaseModal";
import content from './index.md';
import './index.less';
export default function DisclaimerModal({visible}) {
return (
<BaseModal visible={visible} title="免责声明">
<div className="disclaimer-modal">
<div dangerouslySetInnerHTML={{__html: content}}/>
</div>
</BaseModal>
)
}
总结
上面涉及到两个难点
1、怎么在react-scripts生成的配置中添加loader?
2、特殊文件的loader应该加在什么地方?
常见问题
1、为啥要在代码中写markdown呢?
有时候我们涉及到大段的文案,例如游戏规则等,如果在代码中使用div堆的话还是很慢的,尤其是修改了里面的内容,我们几乎要替换所有的代码;如果使用markdown,大段的文案只需要简单的调一下格式,样式使用通用的标签加样式的形式实现。
2、因为不知名原因导致了webpack启动失败,一直显示Start Delevelop Server…,
需要安装 react-scripts@2.1.8解决;