Giter Club home page Giter Club logo

eleventy-plugin-mdx's Introduction

Eleventy Plugin - MDX

This plugin adds an mdx template format to 11ty.

Usage

Install:

npm install @jamshop/eleventy-plugin-mdx react react-dom

Note: react and react-dom are peer dependencies. You must include these in your 11ty project.

In your 11ty config:

const mdxPlugin = require("@jamshop/eleventy-plugin-mdx");
module.exports = (eleventyConfig) => {
  eleventyConfig.addPlugin(mdxPlugin);
};

Options

If you're using static rendering, which is highly recommended for MDX, you will not need to configure any options for this plugin. If you do hydrate pages a small JS bundle is added to pages and you'll need to make sure that React and ReactDom are available on the global scope.

To avoid clashes I'm not bundling React by default with the front-end code. I have provided an option includeCDNLinks which, as the name suggest, will include React and ReactDOM via CDN links, if you're not providing your own javascript bundle this might be an easy option for you.

Remember that static rendering doesn't require any javascript on the front-end, CDN links won't be included and are not required for any pages unless the serializeEleventyProps function is exported.

MDX stuff

This plugin should do all the MDX stuff. There is a lot more about that here: https://mdxjs.com/getting-started#syntax. Some key things it should do:

  • Import local modules from javascript and MDX files.
  • Import and export data from MDX.
  • Import components from libraries.

I've been meaning to write some test for all this and more - BTW, pull requests are most welcome.

Front matter and pagination

Front matter is awesome and central to 11ty so I wanted this to work out of the box. You can include front matter in your mdx files, but you can also export a data object similar to other JS templaing language in 11ty. You can even mix and match!

This works:

---
title: AllPages
layout: "page.njk"
pagination:
  data: pages
  size: 1
  alias: file
permalink: "{{ file.slug }}/"
---

<h1>{props.file.title}</h1>

Hello world!

Alternatively you can also do this:

---
title: AllPages
layout: "page.njk"
---

export const data = {
  pagination: {
      data: "pages",
      size: 1,
      alias: "file",
    },
    permalink: (data) => `${data.file.slug}/`
}

<h1>{props.file.title}</h1>

Hello world!

Static rendering vs Hydration

For the most part you will be able to just use MDX and have it render on the server without a single care. This is the happy path and will yield the best results for your users too. I strongly recommend staying on the happy path.

Then there is hydration. A statically rendered React application won't be interactive in the way a client-side application is. When we render it to HTML it becomes dehydrated, we loose all the juicy JavaScript events and fluid statefulness. To 'hydrate' it on the client we need to inject fresh data so that our application comes back to life.

This is complicated because on the server we have access to everything that 11ty knows about. This often called the 'context' and it includes all 11ty data about posts pages etc... we don't have on the client.

That's why, for each mdx page you want to hydrate, you need to export a serializeEleventyProps function. This function is required so that 11ty knows how to serialise the props you need on the page.

For example on this page the server knows the count and title value from front-matter. But since we want the <Counter /> component to be interactive, we need to use the serializeEleventyProps function to tell the client how to serialize these values.

---
title: Eleventy
count: 11
---

import { Counter } from "./counter.js";

<H1>
  {props.title}
</H1>
<Counter start={props.count} />

export const serializeEleventyProps = (props) => ({
  title: props.title,
  count: props.count,
});

You might be thinking we could make a best guess how to serialise these values. However we don't know what props are used in the MDX, and we were to give it all the data in the context the client bundle would be HUGE. Putting the entire context object in the client is a very bad idea, it's best to just tell us what props you need and serializeEleventyProps is the way.

Alternatively, just use static components.

This is not an SPA

Note: These MDX template do not generate single page apps. A bundle is generated for each page.

eleventy-plugin-mdx's People

Contributors

madebymike avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.