JungleJS 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 so you can get started using it more quickly.
ekafyi / junglejs-storybook-tailwind
Starter site for JungleJS + Storybook + TailwindCSS
At the time of writing, the official docs and 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?
Is it possible to pass data to dataSources asynchronously? #10
Trying JungleJS for the first time now, good work!
I wonder if it's possible to query data from an external source (eg. fetch
from external API) then pass it to dataSources
items
?
The problem is, it has to be done asynchronously. Is it possible at all to return exports
in jungle.config.js
asynchronously? Or is there any other way to achieve this?
Thanks!
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
- Clone:
git clone -b with-async-data https://github.com/ekafyi/junglejs-storybook-tailwind.git
- Deploy with Vercel
- Live Demo
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, 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. 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.
// 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.
<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:
{#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, where I can drag and drop the folder and have my Jungle site live in a few seconds. āØ
My impressions of JungleJS
š Like
I love Jungleās approach to SSG. 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.
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
Top comments (0)