Integrating Vexflow with Gatsby.js
My new blog is built with Gatsby.js and my goal is to make easy to insert sheet music and guitar tab into blog posts. I'm a big fan of the Vexflow Music Notation library and for this post I'm going to explain how I got Vexflow working with Gatsby.
Demo
I struggled a bit with server-side rendering, but eventually got it working! Here's the end result:
Integration Details
There are 3 things I had to do to get Vexflow working with Gatsby.js.
- react-loadable - The Gatsby framework renders everything server-side and Vexflow does not play nicely by default. The Vexflow library depends on 'window' and several other browser features. To work around this issue I used react-loadable to only load my VexflowDemo component on the client-side.
import React from "react";import Loadable from "react-loadable";
export default Loadable({ // this "./VexflowDemo" component loads Vexflow and draws the sheet music loader: () => import("./VexflowDemo"), loading() { return <div>Loading...</div>; },});
-
DOM Node Ref - the Vexflow library takes care of the complex rendering for creating sheet music. It just needs a specific container element to use. The 'ref' feature makes it easy to share the container element with Vexflow without having to hardcode any id values.
-
useEffect Hook - the Vexflow rendering process requires a DOM node reference so we need to make sure the DOM is ready. With React, we can accomplish this using 'useEffect' or 'componentDidMount()'.
Here's a snippet showing how to use 'useEffect' with 'ref':
function VexflowDemo(props) { const notesContainerRef = React.useRef(null);
useEffect(() => { if (notesContainerRef.current !== null) { // this draw() function contains all Vexflow code for rendering the sheet music draw(notesContainerRef.current, props); } });
return <div ref={notesContainerRef} />;}
Check out the full source code for this blog post.