Get asynchronous data in JungleJS, the new Svelte JAMstack library
Tags: jamstack, svelte, junglejs
Published: 2020-07-28 18:14:16

[JungleJS](https://www.junglejs.org/) is a new static site generator that uses Svelte and GraphQL. It also has a handy routing feature akin to NextJS and Sapper, where you can have `src/routes/[slug].svelte` and query for data based on the `slug`. I made this [JungleJS starter site with Storybook and Tailwind CSS](https://github.com/ekafyi/junglejs-storybook-tailwind) so you can get started using it more quickly.

{% github ekafyi/junglejs-storybook-tailwind no-readme %}

At the time of writing, the official [docs](https://www.junglejs.org/docs/config/) and [template](https://github.com/junglejs/template) describe _two data sources_: JSON (whether imported and parsed from local files or written in the JS code) and Markdown files. All well and good if you only need those data sources. But many websites today also get their data from external sources by sending a request to an external API, which is asynchronous in nature.

This is not possible with the current template, so I asked on their Github repo: **Is it possible to fetch data asynchronously in JungleJS?**

{% github https://github.com/junglejs/junglejs/issues/10 %}

They responded that they aimed to have this functionality as a user-facing plugin in the future, and kindly gave the code to run JungleJS asynchronously in the meantime.

To save you all the copy-pasting and server-restarting 😉, I added a simple example and published it to my starter site under the branch `with-async-data`. 

- Code: [JungleJS + Storybook + Tailwind CSS starter with asynchronous data fetching example](https://github.com/ekafyi/junglejs-storybook-tailwind/tree/with-async-data)
- Clone: `git clone -b with-async-data https://github.com/ekafyi/junglejs-storybook-tailwind.git`
- [Deploy with Vercel](https://vercel.com/import/git?s=https%3A%2F%2Fgithub.com%2Fekafyi%2Fjunglejs-storybook-tailwind%2Ftree%2Fwith-async-data)
- [Live Demo](https://junglejs-async-demo.netlify.app)

If you use the Netlify Deploy button or the Github template feature, you’ll get the `master` branch by default. You can run `git checkout with-async-data` to move to the async branch.

## How I made this example

First I modified `app.js` to run asynchronously as advised by [@ConProgramming](https://github.com/ConProgramming), the creator, in the issue’s answer above. I did the same with `build.js`. (Not in the original answer but this is also necessary.)

Next I modified `jungle.config.js`, which previously exported an object, into an asynchronous function as per the answer. Then I added a simple fetch example with the following steps:

- Run `npm i -D node-fetch` (install and save the node-fetch package as dev dependency). You can use eg. `axios` instead of fetch if you want.
- Fetch data from the free [OpenLibrary API](https://openlibrary.org/developers/api). You can replace it with any API you want; simply change the `SAMPLE_FETCH_URL` value.
  - Don’t forget to add the necessary credentials or headers in your request as required by the API.
- Pass the returned data to the `dataSources` in the same format as the existing data source objects example.

```js
// jungle.config.js

// ... other stuff

const fetch = require("node-fetch");

const SAMPLE_FETCH_URL = "https://some-external-api/endpoint";

module.exports = async () => {
  const myResponse = await fetch(SAMPLE_FETCH_URL);
  const myArray = Object.values(await myResponse.json());

  return {
    // .. clientInputOptions etc
    dataSources: [
      {
        format: "json",
        name: "book", // data name as a singleton noun
        items: myArray, // our data as an array
      },
      // ... other data sources
    ],
  };
};
```

Then the data is processed into the GraphQL layer and available to query from our frontend. As I use the name `book` in `jungle.config.js` `dataSources`, I use the plural format `books` to get a list of books via GraphQL query.

```html
<script>
  const QUERY = `
    query {
      books {
        authors {
          name
        }
        cover {
          medium
        }
        title
        url
      }
    }
  `;
  const QUERYRES = {};
  console.log(QUERYRES.books);
</script>
```

The data is available as `QUERYRES.books` and can be used as we normally would in any Svelte application. This is the simplified version:

```html
{#each QUERYRES.books as {authors, cover, subtitle, title, url}}
  <article>
    <img src={cover.medium} alt="" width="180" height="270"/>
    <h3>{`${title}${subtitle ? `: ${subtitle}` : ''}`}</h3>
    <div>{joinAuthorNames(authors)}</div>
  </article>
{/each}
```

To build for production, run `npm run build`. The build is in the `jungle/build` directory, ready to upload/drop to any static site hosting you want. I use [Netlify](https://app.netlify.com), where I can drag and drop the folder and have [my Jungle site](https://junglejs-async-demo.netlify.app/) live in a few seconds. ✨

## My impressions of JungleJS

### 🙂 Like

 I love Jungle’s approach to <abbr title="static site generation">SSG</abbr>. Powered by Svelte, it creates a lean, no-frills, modern JAMstack site with no redundant hydration or run-time tasks. It’s idea for websites where we don’t need complex client-side features and would like more control to add progressive enhancements as we see fit.

- **Effortlessly good SEO:** You can *“View Page Source”* on the page and see our books data rendered as regular HTML, ready for search engines to crawl.
- **Effortlessly good Lighthouse score:** As shown below, it literally loads the HTML, 2 CSS files, 1 bundled JS file, and the images. That’s it.

![screenshot of demo site with DevTools Network tab open showing what assets are loaded](https://dev-to-uploads.s3.amazonaws.com/i/n9frxdmlg7ryqomgapwx.png)

 *This is simply a quick demo. For production, the images should ideally be lazy-loaded, the 2 CSS files combined and/or lazy-loaded, and the JS file deferred for better performance.*

### 🙁 Dislike

Not reallly a “dislike” per se, but given this library is very new, the development experience is still not ideal. For starter there is no live reload, so you have to restart the server to see any change. Also, using GraphQL beyond simple data like in this example may be tricky.

Gatsby, for example, has an integrated GraphQL viewer where we can check our query. They also provide a way to anticipate missing data that would otherwise break the GraphQL query (for example, querying for the optional `subtitle` field would break if none of the books have a `subtitle`).

Until then, feel free to try the starter and hope JungleJS grows into a more mature library. 😃🤞

---

## Bonus Track

{% youtube o1tj2zJ2Wvg %}