你们中的大多数人可能在你们的Gatsby.js站点)中使用过Markdown文件,并且你们已经知道这是一种编写内容的惊人方式。但普通的Markdown是面向基于文本的内容的,当您想要跳出该用例时,它可能会受到限制。mdx,是Markdown的超集,允许我们将jsx直接嵌入到Markdown文件中。听起来很棒,不是吗?在本文中,我们将探索使用Gatsby的MDX的基础知识,包括一些帮助您立即开始使用它的入门技术。
在我们开始之前,您需要有一个Gatsby项目,该项目已经设置好,可以编辑了。如果您需要帮助才能做到这一点,请按照您使用Gatsby v2的第一步》中的步骤操作,然后返回此处。
安装
多亏了Gatsby的不可思议的插件库,),安装过程非常简单!在Gatsby中使用mdx只需要一个插件,即gatsby-plugin-mdx,以及mdx对等依赖项。
现在让我们安装它们,如下所示:
1$ yarn add gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react
让我们还安装gatsby-source-filesystem
,这样我们就可以利用FrontMatter,从本地文件生成Gatsby节点,并在mdx文件中使用导入/导出功能:
1$ yarn add gatsby-source-filesystem
虽然技术上没有要求,但强烈建议您执行此步骤-因为它真正打开了Gatsby的MDX内容的全部潜力!
配置
与所有Gatsby插件一样,我们需要在gatsby-config.js
的plugins
部分添加配置详细信息。
让我们将gatsby-plugin-mdx
和gatsby-source-filesystem
都配置如下:
1[label gatsby-config.js]
2module.exports = {
3 //...siteMetadata, etc
4 plugins: [
5 {
6 resolve: `gatsby-source-filesystem`,
7 options: {
8 name: `pages`,
9 path: `${__dirname}/src/pages/`,
10 },
11 },
12 {
13 resolve: `gatsby-plugin-mdx`,
14 options: {
15 defaultLayouts: {
16 default: require.resolve(`./src/components/layout.js`),
17 },
18 },
19 // ... other plugins
20 ],
21}
注意,我们在defaultLayouts
选项中设置了一个default
键。这将使用我们站点的默认layout.js
组件自动包装所有MDX文件。
<$>[警告]Gatsby-config.js文件已被编辑,因此在继续之前不要忘记重新启动开发环境!<$>
配置选项
gatsby-plugin-mdx
有几个配置选项:
- 扩展名:(字符串数组)设置将作为MDX处理的文件扩展名。我通常将其设置为
[‘.mdx’,‘.md’]
,以便也将普通的Markdown文件作为MDX处理。 - defaultLayout:(Object)当您有多种类型的生成内容,例如博客文章和产品评论时,经常使用该选项。(如上所述,您还可以设置一个
default
键来自动包装所有MDX文件。) - gatsbyRemarkPlugins:(插件对象数组)这允许我们在mdx处理的同时使用各种Gatsby特定的备注plugins。这里经常使用
gatsby-remark-Images
插件。 - markPlugins:(插件对象数组)类似于上述选项,但适用于非Gatsby依赖Remmark plugins.
- rehypePlugins:(插件对象数组)与上面类似,但用于rehype plugins.
- mediaTypes:(字符串数组)设置要处理的媒体类型。(您可能不需要经常使用它。)
有关这些选项用法的完整详细信息,请参阅插件的documentation.这些文档非常棒,我强烈建议您在阅读本文后再看一遍!🔍
基本使用方法
到目前为止,我们的配置已经可以处理我们站点中的所有.mdx
文件。多亏了Gatsby的内置行为,如果我们将它们添加到src/ages/
目录中,它们也会自动变成页面!
现在让我们通过在src/pages/mdx-intro/index.mdx
中创建一个简单的MDX文件来实现这一点。我们将从一些frontmatter和基本的Markdown文本开始,就像一个典型的Markdown博客页面一样:
1[label /src/pages/mdx-intro/index.mdx]
2---
3title: MDX is Magical!
4path: /mdx-intro
5date: 2019-08-25
6---
7
8# Hooray For MDX!
9
10This will be like turbo-charged Markdown!
您可以在浏览器中访问http://localhost:8000/mdx-intro
来查看此新页面。
如果你看过Your First Steps with Gatsby v2这篇文章,你可能会认识到这个页面创建模式,唯一的区别是这是一个MDX文件,而不是Markdown。到目前为止,这并不是什么特别或新的东西。让我们改变这一点!
使用MDX中的组件
MDX的主要功能之一是我们可以直接在Markdown内容中导入和使用JSX组件。
为了演示这一点,让我们在/src/Components/TitleBar.js
中创建一个简单的组件,它将让我们显示一个定制的标题栏。
1[label /src/components/TitleBar.js]
2import React from 'react';
3
4const TitleBar = ({ text, size, bkgdColor }) => (
5 <div
6 style={{
7 margin: '2rem 0',
8 padding: '2rem',
9 backgroundColor: bkgdColor || '#fff',
10 }}
11 >
12 <h2
13 style={{
14 fontSize: size || '18px',
15 margin: 0,
16 }}
17 >
18 {text}
19 </h2>
20 </div>
21);
22
23export default TitleBar;
接下来,让我们更新MDX文件,使其如下所示:
1[label /src/pages/mdx-intro/index.mdx]
2---
3title: MDX is Magical!
4path: /mdx-intro
5date: 2019-08-25
6---
7import TitleBar from "../../components/TitleBar.js";
8
9<TitleBar
10 size={"32px"}
11 bkgdColor={"#4aae9b"}
12 text={props.pageContext.frontmatter.title}
13/>
14
15This will be like turbo-charged Markdown!
这里有两点需要注意:
- 首先,我们刚刚在Markdown内部直接导入并使用了一个Reaction组件!让我们暂时理解这一点,因为这是一个令人难以置信的强大概念。(想象一下带有动画图表和/或动态加载数据、复杂交互等的博客帖子。)
- 其次,您可能已经注意到,我们可以从
pros.pageConext.Frontmatter
访问FrontMatter值。这也是非常有用的!
<$>[警告]重要提示:如果您的MDX文件包含FrontMatter,请始终将任何IMPORT语句放在FrontMatter块之后!
继续在浏览器中查看更新的页面,并尝试编辑size
和bkgdColor
道具以观看其更新。这是一个非常简单的例子,但再次说明:我们使用的是Markdown内部的Reaction组件!很甜蜜,对吧?!
分配布局
如配置部分所述,MDX为我们提供了一种设置自定义布局的简单方法。这些布局便于在我们的MDX文件周围包装其他样式和/或内容。
配置默认布局
我们可以在gatsby-config.js
中设置MDX文件的默认布局,甚至可以设置特定位置的默认布局。看一下这个例子:
1[label gatsby-config.js]
2module.exports = {
3 plugins: [
4 {
5 resolve: `gatsby-source-filesystem`,
6 options: {
7 name: `pages`,
8 path: `${__dirname}/src/pages/`,
9 },
10 },
11 {
12 resolve: `gatsby-source-filesystem`,
13 options: {
14 name: `posts`,
15 path: `${__dirname}/src/blog/`,
16 },
17 },
18 {
19 resolve: `gatsby-plugin-mdx`,
20 options: {
21 defaultLayouts: {
22 posts: require.resolve("./src/components/blog-layout.js"),
23 default: require.resolve("./src/components/layout.js"),
24 },
25 },
26 },
27 ],
28}
在本例中,我们已经配置了我们的站点,以便来自/src/blog
目录的所有MDX文件都将使用blog-layout.js
作为布局/包装器。我们还在这里设置了一个default
配置。
<$>[警告]注意:此行为目前似乎无法正常处理源自ages
目录的MDX文件。(但您仍然可以使用default
布局设置来包装它们,就像我们目前所做的那样。)<$>
手动分配或删除布局
有时,您需要用唯一的布局或根本没有布局来包装特定的MDX文件。这可以通过在我们的MDX文件中使用JavaScript的exportdefault
语法轻松完成,该语法会覆盖任何defaultLayout
设置。我们将在下一节中介绍这一点!
导入其他MDX文件
除了导入/使用JSX组件之外,我们还可以导入和使用其他MDX文件,就像它们是组件一样。(Hint:他们实际上是!)
让我们在组件目录中创建一个新的MDX文件,该文件位于/src/Components/postSignature.mdx
。我们将在MDX页面的底部使用它作为作者的签名。
1[label /src/components/postSignature.mdx]
2##### Thanks for Reading!
3
4*🐊 Al E. Gator | alligator.io | [email protected]*
5
6export default ({ children }) => (
7 <>
8 {children}
9 </>
10)
请注意文件底部的export default
语句。如上一节所述,这就是我们覆盖defaultLayout
配置设置的方法。在本例中,我们将在签名周围导出一个空的<>
包装器。
接下来,让我们将此MDX签名导入到我们的主MDX文件中,该文件位于/src/ages/mdx-troo/index.mdx
:
1[label /src/pages/mdx-intro/index.mdx]
2---
3title: MDX is Magical!
4path: /mdx-intro
5date: 2019-08-25
6---
7import TitleBar from "../../components/TitleBar.js";
8import PostSignature from "../../components/postSignature.mdx";
9
10<TitleBar
11 size={"32px"}
12 bkgdColor={"#4aae9b"}
13 text={props.pageContext.frontmatter.title}
14/>
15
16This is like turbo-charged Markdown!
17
18<PostSignature />
现在,您应该在mdx-Intro
页面的底部看到此签名。太棒了!!😎
GraphQL脚本
多亏了gatsby-plugin-mdx
和gatsby-source-filesystem
的插件组合,我们的MDX页面也可以通过GraphQL查询轻松访问。
我们不会在这上面花太多时间,因为这个功能几乎与以相同的方式查询普通Markdown文件相同。(The唯一的区别是MDX节点位于allMdx
和mdx
中,而不是allMarkdownRemark
和markdownRemark
中。)
下面是一个示例查询,它将获取所有可用MDX文件的正面内容:
1query {
2 allMdx {
3 edges {
4 node {
5 frontmatter {
6 title
7 path
8 date(formatString: "MMMM DD, YYYY")
9 }
10 }
11 }
12 }
13}
提供其他数据
我们还可以通过使用JavaScript的)任何导出的变量都会自动添加到GraphQL模式中,这样我们就可以在GraphQL查询和/或渲染过程中需要时使用它。
以下是一些我们可以添加到MDX页面的Food Truck Review
数据示例:
1export const myReviews = [
2 {
3 name: "Tim's Tacos",
4 overall: 9,
5 variety: 7,
6 price: 8,
7 taste: 9
8 },
9 {
10 name: "Noodleville",
11 overall: 7,
12 variety: 5,
13 price: 6,
14 taste: 8
15 },
16 {
17 name: "Waffle Shack",
18 overall: 6,
19 variety: 5,
20 price: 4,
21 taste: 6
22 },
23];
在文件中的任意位置添加之后,我们可以通过访问allMdx.nodes.exports
来查询GraphQL中的数据,如下所示:
1query MdxExports {
2 allMdx {
3 nodes {
4 exports {
5 myReviews {
6 name
7 overall
8 variety
9 price
10 taste
11 }
12 }
13 }
14 }
15}
这只是一个非常基本的演示,但这个功能可以以令人难以置信的创造性和动态的方式使用。
实战案例
最后,让我们在我们的页面上添加一个有趣而实用的示例。我们将使用上面设置的myReviews
数据来显示动画条形图!
首先,让我们将Recharts库添加到我们的站点。这是一个强大但轻量级的图表库,我经常在我的客户项目中使用。
1$ yarn add recharts
接下来,我们将使用重复图表来创建可重复使用的条形图组件。由于本文不是关于重新图表的文章,因此只需在/src/Components/BarChart.js
处创建一个新文件,并粘贴以下代码:
1[label /src/components/BarChart.js]
2import React, { PureComponent } from 'react';
3import {
4 BarChart,
5 Bar,
6 XAxis,
7 YAxis,
8 CartesianGrid,
9 Tooltip,
10 Legend,
11 ResponsiveContainer,
12} from 'recharts';
13
14const colorsList = ['#008f68', '#6db65b', '#4aae9b', '#dfa612'];
15
16class ExampleChart extends PureComponent {
17 render() {
18 return (
19 <div style={{ width: '100%', height: 350 }}>
20 <ResponsiveContainer>
21 <BarChart data={this.props.data}>
22 <CartesianGrid strokeDasharray="2 2" />
23 <XAxis dataKey="name" />
24 <YAxis type="number" domain={[0, 10]} />
25 <Tooltip />
26 <Legend />
27
28 {this.props.bars.map((bar, i) => (
29 <Bar
30 dataKey={bar}
31 fill={colorsList[i]}
32 key={`bar_${i}`}
33 />
34 ))}
35 </BarChart>
36 </ResponsiveContainer>
37 </div>
38 );
39 }
40}
41
42export default ExampleChart;
现在我们已经设置了一个很好的条形图组件,所以我们只需要导入并在MDX页面中使用它。这是我们的最终版本:
1[label /src/pages/mdx-intro/index.mdx]
2---
3title: MDX is Magical!
4path: /mdx-intro
5date: 2019-08-25
6---
7
8import TitleBar from '../../components/TitleBar';
9import PostSignature from '../../components/postSignature.mdx';
10import BarChart from "../../components/BarChart";
11
12export const myReviews = [
13 {
14 name: "Tim's Tacos",
15 overall: 9,
16 variety: 7,
17 price: 8,
18 taste: 9
19 },
20 {
21 name: "Noodleville",
22 overall: 7,
23 variety: 5,
24 price: 6,
25 taste: 8
26 },
27 {
28 name: "Waffle Shack",
29 overall: 6,
30 variety: 5,
31 price: 4,
32 taste: 6
33 },
34];
35
36<TitleBar
37 text={props.pageContext.frontmatter.title}
38 size={'32px'}
39 bkgdColor={'#4aae9b'}
40/>
41
42This page is built with turbo-charged Markdown!
43
44#### My Food Reviews:
45
46<BarChart
47 data={myReviews}
48 bars={["overall", "variety", "price", "taste"]}
49/>
50
51<PostSignature />
现在,您应该会看到一个看起来很甜美的多色条形图,它以动画形式进入视图,甚至在鼠标悬停时具有动画工具提示。📊👈
我要再说一遍:这一切都在一个Markdown(MDX)页面内!只要想想你可以在短时间内创建的所有有趣的博客帖子和页面……
结论
在这篇介绍MDX和Gatsby的文章中,我们确实谈到了很多!希望它不是太压倒性的,你可以看到,这个组合是快速网站开发的总的游戏规则改变者。
然而,我们只触及了可能性的皮毛。从这里,我建议深入研究Gatsby Docs on MDX.这是一个值得冒险的兔子洞,我保证!🕳🐇