Tag: JAMstack

Make Jamstack Slow? Challenge Accepted.

“Jamstack is slowwwww.” That’s not something you hear often, right? Especially, when one of the main selling points of Jamstack is performance. But yeah, it’s true that even a Jamstack site can suffer hits to performance just like any other site. 

Don’t think that by choosing Jamstack you no longer have to think about performance. Jamstack can be fast — really fast — but you have to make the right choices. Let’s see if we can spot some of the poor decisions that can lead to a “slow” Jamstack site.

To do that, we’re going to build a really slow Gatsby site. Seems strange right? Why would we intentionally do that!? It’s the sort of thing where, if we make it, then perhaps we can gain a better understanding of what affects Jamstack performance and how to avoid bottlenecks.

We will use continuous performance testing and Google Lighthouse to audit every change. This will highlight the importance of testing every code change. Our site will start with a top Lighthouse performance score of 100. From there, we will make changes until it scores a mere 17. It is easier to do than you might think!

Let’s get started!

Creating our Jamstack site

We are going to use Gatsby for our test site. Let’s start by installing the Gatsby CLI installed:

npm install -g gatsby-cli

We can up a new Gatsby site using this command:

gatsby new slow-jamstack

Let’s cd into the new slow-jamstack project directory and start the development server:

cd slow-jamstack gatsby develop

To add Lighthouse to the mix, we need a Gatsby production build. We can use Vercel to host the site, giving Lighthouse a way to runs its tests. That requires installing the Vercel command-line tool and logging in:

npm install -g vercel-cli vercel

This will create the site in Vercel and put it on a live server. Here’s the example I’ve already set up that we’ll use for testing.

We’ve gotta use Chrome to access directly from DevTools and run a performance audit. No surprise here, the default Gatsby site is fast:

Screenshot of a Lighthouse audit showing a score of 100 out of 100.

A score of 100 is the fastest you can get. Let’s see what we can do to slow it down.

Slow CSS

CSS frameworks are great. They can do a lot of heavy lifting for you. When deciding on a CSS framework use one that is modular or employs CSS-in-JS so that the only CSS you need is what’s loaded.

But let’s make the bad decision to reach for an entire framework just to style a button component. In fact, let’s even grab the heaviest framework while we’re at it. These are the sizes of some popular frameworks:

Framework CSS Size (gzip)
Bootstrap 68kb (12kb)
Bulma 73kb (10kb)
Foundation 30kb (7kb)
Milligram 10kb (3kb)
Pure 17kb (4kb)
SemanticUI 146kb (20kb)
UIKit 33kb (6kb)

Alright, SemanticUI it is! The “right” way to load this framework would be to use a Sass or Less package, which would allow us to choose the parts of the framework we need. The wrong way would be to load all the CSS and JavaScript files in the <head> of the HTML. That’s what we’ll do with the full SemanticUI stylesheet. Plus, we’re going to link up jQuery because it’s a SemanticUI dependency.

We want these files to load in the head so let’s jump into the html.js file. This is not available in the src directory until we run a command to copy over the default from the cache:

cp .cache/default-html.js src/html.js

That gives us html.js in the src directory. Open it up and add the required stylesheet and scripts:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.css"></link> <script src="https://code.jquery.com/jquery-3.1.1.js"></script> <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.js"></script>  

Now let’s push the changes straight to our production URL:

vercel --prod

OK, let’s view the audit…

Screenshot of a Lighthouse report showing a score of 66 out of 100.
Zoikes! A 33% reduction!

We have reduced the speed of the site down to a score of 66. Remember that we are not even using this framework at the moment. All we have done is load the files in the head and that reduced the performance score by one-third. Our Time to Interactive (TTI) jumped from a quick 1.9 seconds to a noticeable 4.9 seconds. And look at the possible savings we could get with from Lighthouse’s recommendations.

Slow marketing dependencies

Next, we are going to look at marketing tags and how these third-party scripts can affect performance. Let’s pretend we work with a marketing department and they want to start measuring traffic with Google Analytics. They also have a Facebook campaign and want to track it as well. 

They give us the details of the scripts that we need to add to get everything working. First, for Google Analytics:

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-4369823-4"></script> <script   dangerouslySetInnerHTML={{ __html: `   window.dataLayer = window.dataLayer || [];   function gtag(){dataLayer.push(arguments);}   gtag('js', new Date());   gtag('config', 'UA-4369823-4');   `}} />

Then for the Facebook campaign:

<script   dangerouslySetInnerHTML={{ __html: `     !function(f,b,e,v,n,t,s)     {if(f.fbq)return;n=f.fbq=function(){n.callMethod?     n.callMethod.apply(n,arguments):n.queue.push(arguments)};     if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';     n.queue=[];t=b.createElement(e);t.async=!0;     t.src=v;s=b.getElementsByTagName(e)[0];     s.parentNode.insertBefore(t,s)}(window, document,'script',     'https://connect.facebook.net/en_US/fbevents.js');     fbq('init', '3180830148641968');     fbq('track', 'PageView');     `}} />  <noscript><img height="1" width="1" src="https://www.facebook.com/tr?id=3180830148641968&ev=PageView&noscript=1"/></noscript>

We’ll place these scripts inside html.js, again in the <head> section, before the closing </head> tag.

Just like before, let’s push to Vercel and re-run Lighthouse:

vercel --prod
Screenshot of a Lighthouse audit showing a score of 51 out of 100.

Wow, the site is already down to 51 and all we’ve done is tack on one framework and a couple of measly scripts. Together, they/ve reduced the score by a whopping 49 points, nearly half of where we started.

Slow images

We haven’t added any images to the site yet but we know we absolutely would in a real-life scenario. We are going to add 100 images to the page. Sure, 100 is a lot for a single page but, then again, we know that images are often the biggest culprits of bloated web pages so we might as well let them shine.

We’ll make things a little worse by hot loading the images directly from https://placeimg.com instead of serving them on our own server.

Let’s crack open index.js and drop this code in, which will loop through 100 instances of images:

const IndexPage = () => {   const items = []   for(var i = 0; i < 100; i++) {     const url = `http://placeimg.com/640/360/any?=$ {i}`     items.push(<img key={i} alt={i} src=https://css-tricks.com/make-jamstack-slow-challenge-accepted/ />)   }      return (     <Layout>       // ...       {items}       // ...     </Layout>   ) }

The 100 images are all different and will all load as the page loads, thereby blocking the rendering. OK, let’s push to Vercel and see what’s up.

vercel --prod
Screenshot of a Lighthouse audit showing a score of 17 out of 100.
That score deserves a sad trombone. 🎺

OK, we now have a very slow Jamstack site. The images are blocking the rendering of the page and the TTI is now a whopping 16.5 seconds. We have taken a very fast Jamstack site and dropped it to a Lighthouse score of 17 — a reduction of 83 points!

Now, you may be think that you would never make these poor decisions when building an app. But you are missing the point. Every choice we make has an impact on performance. It’s a balance and performance does not come free. Even on Jamstack sites.

Making Jamstack fast again

You have seen that we cannot ignore client-side performance when using Jamstack. 

So why do people say that Jamstack is fast? Well, the main advantage of Jamstack — or using static site generators in general — is caching. Static files are cached on the edge reducing Time to First Byte (TTFB).

This is always going to be faster than going to a single-origin web server before generating the page. This is a great feature of Jamstack and gives you a fighting chance to create a page that can hit 100 in Lighthouse. (But, hey, as a side note, remember that great scores aren’t always indicative of an actual user experience.)


See, I told you we could make Jamstack slow! There are also many other things that can slow it down, but hopefully this drives home the point.

While we’re talking about performance, here are a few of my favorite performance articles on here at CSS-Tricks:


The post Make Jamstack Slow? Challenge Accepted. appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,

Settling down in a Jamstack world

One of the things I like about Jamstack is that it’s just a philosophy. It’s not particularly prescriptive about how you go about it. To me, the only real requirement is that it’s based on static (CDN-backed) hosting. You can use whatever tooling you like. Those tools, though, tend to be somewhat new, and new sometimes comes with issues. Some pragmatism from Sean C Davis here:

I have two problems with solving problems using the newest, best tool every time a problem arises.

1. It’s simply not productive. Introducing new processes and tools takes time. Mastery and efficiency are built over time. If we’re trying to run a profitable business, we shouldn’t start from scratch every time.

2. We can’t know everything, all the time. With the rapidity at which we’re seeing new tools, there’s simply no way of knowing the best tool for the job because there’s no way to know all the tools available.

The trick is to settle into some tools you’ve proved that work and then keep using them to increase that level of expertise.

The post Settling down in a Jamstack world appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

5 Myths About Jamstack

Jamstack isn’t necessarily new. The term was officially coined in 2016, but the technologies and architecture it describes have been around well before that. Jamstack has received a massive dose of attention recently, with articles about it appearing in major sites and publications and new Jamstack-focused events, newsletters, podcasts, and more. As someone who follows it closely, I’ve even seen what seems like a significant uptick in discussion about it on Twitter, often from people who are being newly introduced to the concept.

The buzz has also seemed to bring out the criticism. Some of the criticism is fair, and I’ll get to some of that in a bit, but others appear to be based on common myths about the Jamstack that persist, which is what I want to address first. So let’s look at five common myths about Jamstack I’ve encountered and debunk them. As with many myths, they are often based on a kernel of truth but lead to invalid conclusions.

Myth 1: They are just rebranded static sites

Yes, as I covered previously, the term “Jamstack” was arguably a rebranding of what we previously called “static sites.” This was not a rebranding meant to mislead or sell you something that wasn’t fully formed — quite the opposite. The term “static site” had long since lost its ability to describe what people were building. The sites being built using static site generators (SSG) were frequently filled with all sorts of dynamic content and capabilities.

Static sites were seen as largely about blogs and documentation where the UI was primarily fixed. The extent of interaction was perhaps embedded comments and a contact form. Jamstack sites, on the other hand, have things like user authentication, dynamic content, ecommerce, user generated content.

A listing of sites built using Jamstack on Jamstack.org

Want proof? Some well-known companies and sites built using the Jamstack include Smashing Magazine, Sphero, Postman, Prima, Impossible Foods and TriNet, just to name a few.

Myth 2: Jamstack sites are fragile

A Medium article with no byline: The issues with JAMStack: You might need a backend

Reading the dependency list for Smashing Magazine reads like the service equivalent of node_modules, including AlgoliaGoCommerceGoTrueGoTell and a variety of Netlify services to name a few. There is a huge amount of value in knowing what to outsource (and when), but it is amusing to note the complexity that has been introduced in an apparent attempt to ‘get back to basics’. This is to say nothing of the potential fragility in relying on so many disparate third-party services.

Yes, to achieve the dynamic capabilities that differentiate the Jamstack from static sites, Jamstack projects generally rely on a variety of services, both first- or third-party. Some have argued that this makes Jamstack sites particularly vulnerable for two reasons. The first, they say, is that if any one piece fails, the whole site functionality collapses. The second is that your infrastructure becomes too dependent on tools and services that you do not own.

Let’s tackle that first argument. The majority of a Jamstack site should be pre-rendered. This means that when a user visits the site, the page and most of its content is delivered as static assets from the CDN. This is what gives Jamstack much of its speed and security. Dynamic functionality — like shopping carts, authentication, user generated content and perhaps search — rely upon a combination of serverless functions and APIs to work.

Broadly speaking, the app will call a serverless function that serves as the back end to connect to the APIs. If, for example, our e-commerce functionality relies on Stripe’s APIs to work and Stripe is down, then, yes, our e-commerce functionality will not work. However, it’s important to note that the site won’t go down. It can handle the issue gracefully by informing the user of the issue. A server-rendered page that relies on the Stripe API for e-commerce would face the identical issue. Assuming the server-rendered page still calls the back end code for payment asynchronously, it would be no more or less fragile than the Jamstack version. On the other hand, if the server-rendering is actually dependent upon the API call, the user may be stuck waiting on a response or receive an error (a situation anyone who uses the web is very familiar with).

As for the second argument, it’s really hard to gauge the degree of dependence on third-parties for a Jamstack web app versus a server-rendered app. Many of today’s server-rendered applications still rely on APIs for a significant amount of functionality because it allows for faster development, takes advantage of the specific area of expertise of the provider, can offload responsibility for legal and other compliance issues, and more. In these cases, once again, the server-rendered version would be no more or less dependent than the Jamstack version. Admittedly, if your app relies mostly on internal or homegrown solutions, then this may be different.

Myth 3: Editing content is difficult

Kev Quirk, on Why I Don’t Use A Static Site Generator:

Having to SSH into a Linux box, then editing a post on Vim just seems like a ridiculously high barrier for entry when it comes to writing on the go. The world is mobile first these days, like it or not, so writing on the go should be easy.

This issue feels like a relic of static sites past. To be clear, you do not need to SSH into a Linux box to edit your site content. There are a wide range of headless CMS options, from completely free and open source to commercial offerings that power content for large enterprises. They offer an array of editing capabilities that rival any traditional CMS (something I’ve talked about before). The point is, there is no reason to be manually editing Markdown, YAML or JSON files, even on your blog side project. Aren’t sure how to hook all these pieces up? We’ve got a solution for that too!

One legitimate criticism has been that the headless CMS and build process can cause a disconnect between the content being edited and the change on the site. It can be difficult to preview exactly what the impact of a change is on the live site until it is published or without some complex build previewing process. This is something that is being addressed by the ecosystem. Companies like Stackbit (who I work for) are building tools that make this process seamless.

Animated screenshot. A content editor is shown on a webpage with a realtime preview of changes.
Editing a site using Stackbit

We’re not the only ones working on solving this problem. Other solutions include TinaCMS and Gatsby Preview. I think we are close to it becoming commonplace to have the simplicity of WYSIWYG editing on a tool like Wix running on top of the Jamstack.

Myth 4: SEO is Hard on the Jamstack

Kym Ellis, on What the JAMstack means for marketing:

Ditching the concept of the plugin and opting for a JAMstack site which is “just HTML” doesn’t actually mean you have to give up functionality, or suddenly need to know how to code like a front-end developer to manage a site and its content.

I haven’t seen this one pop up as often in recent years and I think it is mostly legacy criticism of the static site days, where managing SEO-related metadata involved manually editing YAML-based frontmatter. The concern was that doing SEO properly became cumbersome and hard to maintain, particularly if you wanted to inject different metadata for each unique page that was generated or to create structured data like JSON-LD, which can be critical for enhancing your search listing.

The advances in content management for the Jamstack have generally addressed the complexity of maintaining SEO metadata. In addition, because pages are pre-rendered, adding sitemaps and JSON-LD is relatively simple, provided the metadata required exists. While pre-rendering makes it easy to create the resources search engines (read: Google) need to index a site, they also, combined with CDNs, making it easier to achieve the performance benchmarks necessary to improve a site’s ranking.

Basically, Jamstack excels at “technical SEO” while also providing the tools necessary for content editors to supply the keyword and other metadata they require. For a more comprehensive look at Jamstack and SEO, I highly recommend checking out the Jamstack SEO Guide from Bejamas.

Myth 5: Jamstack requires heavy JavaScript frameworks

If you’re trying to sell plain ol’ websites to management who are obsessed with flavour-of-the-month frameworks, a slick website promoting the benefits of “JAMstack” is a really useful thing.

– jdietrich, Hacker News

Lately, it feels as if Jamstack has become synonymous with front-end JavaScript frameworks. It’s true that a lot of the most well-known solutions do depend on a front-end framework, including Gatsby (React), Next.js (React), Nuxt (Vue), VuePress (Vue), Gridsome (Vue) and Scully (Angular). This seems to be compounded by confusion around the “J” in Jamstack. While it stands for JavaScript, this does not mean that Jamstack solutions are all JavaScript-based, nor do they all require npm or JavaScript frameworks.

In fact, many of the most widely used tools are not built in JavaScript, notably Hugo (Go), Jekyll (Ruby), Pelican (Python) and the recently released Bridgetown (Ruby). Meanwhile, tools like Eleventy are built using JavaScript but do not depend on a JavaScript framework. None of these tools prevent the use of a JavaScript framework, but they do not require it.

The point here isn’t to dump on JavaScript frameworks or the tools that use them. These are great tools, used successfully by many developers. JavaScript frameworks can be very powerful tools capable of simplifying some very complex tasks. The point here is simply that the idea that a JavaScript framework is required to use the Jamstack is false — Jamstack comes in 460 flavors!

Where we can improve

So that’s it, right? Jamstack is an ideal world of web development where everything isn’t just perfect, but perfectly easy. Unfortunately, no. There are plenty of legitimate criticisms of Jamstack.

Simplicity

Sebastian De Deyne, with Thoughts (and doubts) after messing around with the JAMstack:

In my experience, the JAMstack (JavaScript, APIs, and Markup) is great until is isn’t. When the day comes that I need to add something dynamic–and that day always comes–I start scratching my head.

Let’s be honest: Getting started with the Jamstack isn’t easy. Sure, diving into building a blog or a simple site using a static site generator may not be terribly difficult. But try building a real site with anything dynamic and things start to get complicated fast.

You are generally presented with a myriad of options for completing the task, making it tough to weigh the pros and cons. One of the best things about Jamstack is that it is not prescriptive, but that can make it seem unapproachable, leaving people with the impression that perhaps it isn’t suited for complex tasks.

Tying services together

When you actually get to the point of building those dynamic features, your site can wind up being dependent on an array of services and APIs. You may be calling a headless CMS for content, a serverless function that calls an API for payment transactions, a service like Algolia for search, and so on. Bringing all those pieces together can be a very complex task. Add to that the fact that each often comes with its own dashboard and API/SDK updates, things get even more complex.

This is why I think services like Stackbit and tools like RedwoodJS are important, as they bring together disparate pieces of the infrastructure behind a Jamstack site and make those easier to build and manage.

Overusing frameworks

In my opinion, our dependence on JavaScript frameworks for modern front-end development has been getting a much needed skeptical look lately. There are tradeoffs, as this post by Tim Kadlec recently laid out. As I said earlier, you don’t need a JavaScript framework to work in the Jamstack.

However, the impression was created both because so many Jamstack tools rely on JavaScript frameworks and also because much of the way we teach Jamstack has been centered on using frameworks. I understand the reasoning for this — many Jamstack developers are comfortable in JavaScript frameworks and there’s no way to teach every tool, so you pick the one you like. Still, I personally believe the success of Jamstack in the long run depends on its flexibility, which (despite what I said about the simplicity above) means we need to present the diversity of solutions it offers — both with and without JavaScript frameworks.

Where to go from here

Sheesh, you made it! I know I had a lot to say, perhaps more than I even realized when I started writing, so I won’t bore you with a long conclusion other than to say that, obviously, I have presented these myths from the perspective of someone who believes very deeply in the value of the Jamstack, despite it’s flaws!

If you are looking for a good post about when to and when not to choose Jamstack over server-side rendering, check out Chris Coyier’s recent post Static or Not?.

The post 5 Myths About Jamstack appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Jamstack News!

I totally forgot that the Jamstack Conf was this week but thankfully they’ve already published the talks on the Jamstack YouTube channel. I’m really looking forward to sitting down with these over a coffee while I also check out Netlify’s other big release today: Build Plugins.

These are plugins that run whenever your site is building. One example is the A11y plugin that will fail a build if accessibility failures are detected. Another minifies HTML and there’s even one that inlines critical CSS. What’s exciting is that these build plugins are kinda making complex Gulp/Grunt environments the stuff of legend. Instead of going through the hassle of config stuff, build plugins let Netlify figure it all out for you. And that’s pretty neat.

Also, our very own Sarah Drasner wrote just about how to create your first Netlify Build Plugin. So, if you have an idea for something that you could share with the community, then that may be the best place to start.

Direct Link to ArticlePermalink

The post Jamstack News! appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Angular + Jamstack! (Free Webinar)

(This is a sponsored post.)

It’s easy to think that working with Jamstack means working with some specific set of technologies. That’s how it’s traditionally been packaged for us. Think LAMP stack, where Linux, Apache, MySQL and PHP are explicit tools and languages. or MEAN or MERN or whatever. With Jamstack, the original JAM meant JavaScript, APIs, and Markup. That’s not specific technologies so much as a loose philosophy.

That’s cool, because it means we can bring our own set of favorite technologies, and then figure out how to use that philosophy for the most benefit. That can mean bringing our favorite CMS, favorite build tools, and even favorite front-end frameworks.

That’s the crux of Netlify’s upcoming webinar on using Angular in the Jamstack. They’ll walk through where Angular fits into the Jamstack architecture, how to develop with Angular in the stack, and the benefits of working this way. Plus you get to hang with Tara Z. Manicsic, which is worth it right there.

The webinar is free and scheduled for May 13 at 9:00am Pacific Time.

Direct Link to ArticlePermalink

The post Angular + Jamstack! (Free Webinar) appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Drupal to Jamstack

I’ve been harping for a while that Jamstack doesn’t necessarily mean throwing away your old CMS. In fact, I’d argue that Jamstack is at it’s most powerful when paired with a system that you already know, are comfortable with, and perhaps even like. You’d call that decoupling the front end.

Netlify has a webinar coming up on exactly this, featuring Alex De Winne, who is going to show you a real-world site in a live demo combining Drupal (a classic PHP & MySQL CMS that powers an absolute ton of sites) and Jamstack architecture.

The post Drupal to Jamstack appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

APIs and Authentication on the Jamstack

The first “A” in the Jamstack stands for “APIs” and is a key contributor to what makes working with static sites so powerful. APIs give developers the freedom to offload complexity and provide avenues for including dynamic functionality to an otherwise static site. Often, accessing an API requires validating the authenticity of a request. This frequently manifests in the form of authentication (auth) and can be done either client side or server side depending on the service used and the task being accomplished. 

Given the vast spectrum of protocols available, APIs differ in their individual auth implementations. These auth protocols and implementation intricacies add an additional challenge when integrating APIs into a Jamstack site. Thankfully, there is a method to this madness. Every protocol can be mapped to a specific use case and implementing auth is a matter of understanding this.

To illustrate this best, let’s dive into the various protocols and the scenarios that they’re best suited for.

Summon the protocols

OAuth 2.0 is the general standard by which authentication today follows. OAuth is a fairly flexible authorization framework that constitutes a series of grants defining the relationship between a client and an API endpoint. In an OAuth flow, a client application requests an access token from an authorization endpoint and uses that to sign a request to an API endpoint.

There are four main grant types — authorization code, implicit flow, resource owner credential, and client credentials. We’ll look at each one individually.

Authorization Code Grant 

Of all OAuth grant types, the Authorization Code Grant is likely the most common one. Primarily used to obtain an access token to authorize API requests after a user explicitly grants permission, this grant flow follows a two-step process.

  • First, the user is directed to a consent screen aka the authorization server where they grant the service restricted access to their personal account and data.
  • Once permission has been granted, the next step is to retrieve an access token from the authentication server which can then be used to authenticate the request to the API endpoint.

Compared to other grant types, the Authorization Code Grant has an extra layer of security with the added step of asking a user for explicit authorization. This multi-step code exchange means that the access token is never exposed and is always sent via a secure backchannel between an application and auth server. In this way, attackers can’t easily steal an access token by intercepting a request. Google-owned services, like Gmail and Google Calendar, utilize this authorization code flow to access personal content from a user’s account. If you’d like to dig into this workflow more, check out this blog post to learn more.

Implicit Grant

The Implicit Grant is akin to the Authorization Code Grant with a noticeable difference: instead of having a user grant permission to retrieve an authorization code that is then exchanged for an access token, an access token is returned immediately via the the fragment (hash) part of the redirect URL (a.k.a. the front channel).

With the reduced step of an authorization code, the Implicit Grant flow carries the risk of exposing tokens. The token, by virtue of being embedded directly into the URL (and logged to the browser history), is easily accessible if the redirect is ever intercepted.

Despite its vulnerabilities, the Implicit Grant can be useful for user-agent-based clients like Single Page Applications. Since both application code and storage is easily accessed in client-side rendered applications, there is no safe way to keep client secrets secure. The implicit flow is the logical workaround to this by providing applications a quick and easy way to authenticate a user on the client side. It is also a valid means to navigate CORS issues, especially when using a third-party auth server that doesn’t support cross-origin requests. Because of the inherent risks of exposed tokens with this approach, it’s important to note that access tokens in Implicit Flow tend to be short-lived and refresh tokens are never issued. As a result, this flow may require logging in for every request to a privileged resource.

Resource Owner Credential

In the case of the Resource Owner Credential Grant, resource owners send their username and password credentials to the auth server, which then sends back an access token with an optional refresh token. Since resource owner credentials are visible in the auth exchange between client application and authorization server, a trust relationship must exist between resource owner and client application. Though evidently less secure than other grant types, the Resource Owner Credential grant yields an excellent user experience for first party clients. This grant flow is most suitable in cases where the application is highly privileged or when working within a device’s operating system. This authorization flow is often used when other flows are not viable.

Client Credential

The Client Credentials Grant type is used primarily when clients need to obtain an access token outside of the context of a user. This is suitable for machine to machine authentication when a user’s explicit permission cannot be guaranteed for every access to a protected resource. CLIs, and services running in the back end are instances when this grant type comes in handy. Instead of relying on user login, a Client ID and Secret are passed along to obtain a token which can then be used to authenticate an API request.

Typically, in the Client Credential grant, a service account is established through which the application operates and makes API calls. This way, users are not directly involved and applications can still continue to authenticate requests. This workflow is fairly common in situations where applications want access to their own data, e.g. Analytics, rather than to specific user data.

Conclusion

With its reliance on third party services for complex functionality, a well-architected authentication solution is crucial to maintain the security of Jamstack sites. APIs, being the predominant way to exchange data in the Jamstack, are a big part of that. We looked at four different methods for authenticating API requests, each with its benefits and impacts on user experience.

We mentioned at the start that these four are the main forms of authentication that are used to request data from an API. There are plenty of other types as well, which are nicely outlined on oauth.net. The website as a whole is an excellent deep-dive on not only the auth types available, but the OAuth framework as a whole.

Do you prefer one method over another? Do you have an example in use you can point to? Share in the comments!

The post APIs and Authentication on the Jamstack appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Data-driven Jamstack with Sourcebit

Think of building sites with Gatsby as an hourglass shape.

Gatsby itself is right in the middle. The wide funnel at the top represents the fact that Gatsby can take in data from all sorts of sources. The data could be in markdown files, from a headless CMS or some other API, from a hosted database, or pretty much whatever.

The wide funnel at the bottom represents that the output from Gatsby is static files, so those files can go anywhere. Netlify, GitHub Pages, ZEIT, S3, whatever.

Gatsby does a bunch of neat stuff (just the fact that it’s in React I’m sure is appealing to a wide swath of developers), but it seems to me the secret sauce is how it works with any data source.

If you were going to widen that hourglass shape into a, uhhh, pipe, you’d build a tool that connects arbitrary data sources with arbitrary static site generators. It appears that is what Stackbit is doing with Sourcebit. It has a two-sided plugin model (Sources: e.g. Contentful or Sanity; Targets: e.g. Jekyll or Hugo) with the goal of contacting any data source with any site-building tool that needs that data.

I would think contributors to all projects in both the data source and site builder arenas would be interested in seeing this succeed, including Gatsby.

Direct Link to ArticlePermalink

The post Data-driven Jamstack with Sourcebit appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

How To Create A Headless WordPress Site On The Jamstack

Just this morning, Chris shared a streamlined way to get a static site up and running with Netlify. As it happens, Sarah and I also wrote up a little something that expands that idea where a static site can pull content from WordPress using the REST API.

Using Vue, Nuxt, axios, and Netlify, it’s possible to get both the performance and continuous integration benefits of Jamstack with the powerful publishing and editing features of a CMS. It’s really amazing what pairing different stacks can do these days!

Being a WordPress junkie myself, I learned from a lot from Sarah about setting up a progressive web app and working with a component-driven architecture. She equipped me with several resources, all of which are linked up in the article. There’s even a complete video where Sarah walks through the same steps we followed to set things up for this app.

In other words, it’s worth the estimated 18 minutes it takes to read the article. I hope you walk away with as much as I did getting to work on it.

Direct Link to ArticlePermalink

The post How To Create A Headless WordPress Site On The Jamstack appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Build a dynamic JAMstack app with GatsbyJS and FaunaDB

In this article, we explain the difference between single-page apps (SPAs) and static sites, and how we can bring the advantages of both worlds together in a dynamic JAMstack app using GatsbyJS and FaunaDB. We will build an application that pulls in some data from FaunaDB during build time, prerenders the HTML for speedy delivery to the client, and then loads additional data at run time as the user interacts with the page. This combination of technologies gives us the best attributes of statically-generated sites and SPAs. 

In short…<deep breath>…auto-scaling distributed websites with low latency, snappy user interfaces, no reloads, and dynamic data for everyone!

Heavy backends, single-page apps, static sites 

In the old days, when JavaScript was new, it was mainly only used to provide effects and improved interactions. Some animations here, a drop-down there, and that was it. The grunt work was performed on the backend by Perl, Java, or PHP. 

This changed as time went on: client code became heavier, and JavaScript took over more and more of the frontend until we finally shipped mostly empty HTML and rendered the whole UI in the browser, leaving the backend to supply us with JSON data.

This led to a neat separation of concerns and allowed us to build whole applications with JavaScript, called Single Page Applications (SPAs). The most important advantage of SPAs was the absence of reloads. You could click on a link to change what’s displayed, without triggering a complete reload of the page. This in itself provided a superior user experience. However, SPAs increased the size of the client code significantly; a client now had to wait for the sum of several latencies:

  • Serving latency: retrieving the HTML and JavaScript from the server where the JavaScript was bigger than it used to be 
  • Data loading latency: loading additional data requested by the client
  • Frontend framework rendering latency: once the data is received, a frontend framework like React, Vue, or Angular still has to do a lot of work to construct the final HTML 

A royal metaphor

We can analogize the loading a SPA with the building and delivery of a toy castle. The client needs to retrieve the HTML and JavaScript, then retrieve the data, and then still has to assemble the page. The building blocks are delivered, but they still need to be put together after they’re delivered.

If only there were a way to build the castle beforehand…

Enter the JAMstack

JAMstack applications consist of JavaScript, APIs and Markup. With today’s static site generators like Next.js and GatsbyJS, the JavaScript and Markup parts can be bundled up into a static package and deployed via a Content Delivery Network (CDN) that delivers files to a browser. A CDN geographically distributes the bundles, and other assets, to multiple locations. When a user’s browser fetches the bundle and assets, it can receive them from the closest location on the network, which reduces the serving latency. 

Continuing our toy castle analogy, JAMstack apps are different from SPAs in the sense that the page (or castle) is delivered pre-assembled. We have a lower latency since we receive the castle in one piece and no longer have to build it. 

Making static JAMstack apps dynamic with hydration

In the JAMstack approach, we start with a dynamic application and prerender static HTML pages to be delivered via a speedy CDN. But what if a fully static site is not sufficient and we need to support some dynamic content as the user interacts with individual components, without reloading the entire page? That’s where client-side hydration comes in.

Hydration is the client-side process by which the server-side rendered HTML (DOM) is “watered” by our frontend framework with event handlers and/or dynamic components to make it more interactive. This can be tricky because it depends on reconciling the original DOM with a new virtual DOM (VDOM) that’s kept in memory as the user interacts with the page. If the DOM and VDOM trees do not match, bugs can arise that cause elements to be displayed out of order, or necessitate rebuilding the page.

Luckily, libraries like GatsbyJS and NextJS have been designed so as to minimize the possibility of such hydration-related bugs, handling everything for you out-of-the-box with only a few lines of code. The result is a dynamic JAMstack web application that is simultaneously both faster and more dynamic than the equivalent SPA. 

One technical detail remains: where will the dynamic data come from?

Distributed frontend-friendly databases!

JAMstack apps typically rely on APIs (ergo the “A” in JAM), but if we need to load any kind of custom data, we need a database. And traditional databases are still a performance bottleneck for globally distributed sites that are otherwise delivered via CDN, because traditional databases are only located in one region. Instead of using a traditional database, we’d like our database to be on a distributed network, just like the CDN, that serves the data from a location as close as possible to wherever our clients are. This type of database is called a distributed database. 

In this example, we’ll choose FaunaDB since it is also strongly consistent, which means that our data will be the same wherever my clients access it from and data won’t be lost. Other features that work particularly well with JAMstack applications are that (a) the database is accessed as an API (GraphQL or FQL) and does not require you to open a connection, and (b) the database has a security layer that makes it possible to access both public and private data in a secure way from the frontend. The implications of that are we can keep the low latencies of JAMstack without having to scale a backend, all with zero configuration. 

Let’s compare the process of loading a hydrated static site with the building of the toy castle. We still have lower latencies thanks to the CDN, but also less data since most the site is statically generated and therefore requires less rendering. Only a small part of the castle (or, the dynamic part of the page) needs to be assembled after it has been delivered:

Example app with GatsbyJS & FaunaDB

Let’s build an example application that loads data from FaunaDB at build time and renders it to static HTML, then loads additional dynamic data inside the client browser at run time. For this example, we use GatsbyJS, a JAMstack framework based on React that prerenders static HTML. Since we use GatsbyJS, we can code our website completely in React, generate and deliver the static pages, and then load additional data dynamically at run time. We’ll use FaunaDB as our fully managed serverless database solution. We will build an application where we can list products and reviews. 

Let’s look at an outline of what we have to do to get our example app up and running and then go through every step in detail.

  1. Set up a new database
  2. Add a GraphQL schema to the database
  3. Seed the database with mock-up data
  4. Create a new GatsbyJS project
  5. Install NPM packages
  6. Create the server key for the database
  7. Update GatsbyJS config files with server key and new read-only key
  8. Load the pre-rendered product data at build time
  9. Load the reviews at run time

1. Set up a new database

Before you start, create an account on dashboard.fauna.com. Once you have an account, let’s set up a new database. It should hold products and their reviews, so we can load the products at build-time and the reviews in the browser. 

2. Add a GraphQL schema to the database

Next, we use the server key to upload a GraphQL schema to our database. For this, we create a new file called schema.gql that has the following content:

type Product {   title: String!   description: String   reviews: [Review] @relation }  type Review {   username: String!   text: String!   product: Product! }  type Query {   allProducts: [Product] }

You can upload your schema.gql file via the FaunaDB Console by clicking “GraphQL” on the left sidebar, and then click the “Import Schema” button.

Upon providing FaunaDB with a GraphQL schema, it automatically creates the required collections for the entities in our schema (products and reviews). Besides that, it also creates the indexes that are needed to interact with those collections in a meaningful and efficient manner. You should now be presented with a GraphQL playground where you can test out 

3. Seed the database with mock-up data

To seed our database with products and reviews, we can use the Shell at dashboard.fauna.com: 

To create some data, we’ll use the Fauna Query Language (FQL), after that we’ll continue with GraphQL to build are example application. Paste the following FQL query into the Shell to create three product documents:

Map(   Paginate(Match(Index("allProducts"))),   Lambda("ref", Create(Collection("Review"), {     data: {       username: "Tina",       text: "Good product!",       product: Var("ref")     }   })) );

We can then write a query that retrieves the products we just made and creates a review document for every product document:

Map(   Paginate(Match(Index("allProducts"))),   Lambda("ref", Create(Collection("Review"), {     data: {       username: "Tina",       text: "Good product!",       product: Var("ref")     }   })) ); 

Both types of documents will be loaded via GraphQL. However, there is a significant difference between products and reviews. The former will not change a lot and is relatively static, while the second is user-driven. GatsbyJS allows us to load data in two ways:

  • data that is loaded at build time which will be used to generate the static site. 
  • data that is loaded live at request time as a client visits and interacts with your website. 

In this example, we chose to let the products be loaded at build time, and the reviews to be loaded on-demand in the browser. Therefore, we get static HTML product pages served by a CDN that the user immediately sees. Then, as our user interacts with the product page, we load the data for the reviews. 

4. Create a new GatsbyJS project

The following command creates a GatsbyJS project based on the starter template:

$  npx gatsby-cli new hello-world-gatsby-faunadb $  cd hello-world-gatsby-faunadb

5. Install npm packages

In order to build our new project with Gatsby and Apollo, we need a few additional packages. We can install the packages with the following command: 

 $  npm i gatsby-source-graphql apollo-boost react-apollo

We will use gatsby-source-graphql as a way to link GraphQL APIs into the build process. Using this library, you can make a GraphQL call from which the results will be automagically provided as the properties for your react component. That way, you can use dynamic data to statically generate your application. The apollo-boost package is an easily configurable GraphQL library that will be used to fetch data on the client. Finally, the link between Apollo and React will be taken care of by the react-apollo library.

6. Create the server key for the database

We will create a Server key which will be used by Gatsby to prerender the page. Remember to copy the secret somewhere since we will use it later on. Protect server keys carefully, they can be used to create, destroy, or manage the database to which they are assigned. To create the key we can go to the fauna dashboard and create the key in the security tab. 

7. Update GatsbyJS config files with server and new read-only keys

To add the GraphQL support to our build process, we need to add the following code into our graphql-config.js inside the plugins section where we will insert the FaunaDB server key which we generated a few moments ago. 

{   resolve: "gatsby-source-graphql",   options: {     typeName: "Fauna",     fieldName: "fauna",     url: "https://graphql.fauna.com/graphql",     headers: {       Authorization: "Bearer <SERVER KEY>",     },   }, }

For the GraphQL access to work in the browser, we have to create a key that only has permissions to read data from the collections. FaunaDB has an extensive security layer in which you can define that. The easiest way is to go to the FaunaDB Console at dashboard.fauna.com and create a new role for your database by clicking “Security” in the left sidebar, then “Manage Roles,” then “New Custom Role”:

Call the new custom role ‘ClientRead’ and make sure to add all collections and indexes (these are the collections that were created by importing the GraphQL schema). Then, select Read for each for them. Your screen should look like this:

You have probably noticed the Membership tab on this page. Although we are not using it in this tutorial, it is interesting enough to explain it since it’s an alternative way to get security tokens. In the Membership tab can specify that entities of a collection (let’s say we have a ‘Users’ collection) in FaunaDb are members of a particular role. That means that if you impersonate one of these entities in that collection, the role privileges apply. You impersonate a database entity (e.g. a User) by associating credentials with the entity and using the Login function, which will return a token. That way you can also implement password-based authentication in FaunaDb. We won’t use it in this tutorial, but if that interests you, check the FaunaDB authentication tutorial.

Let’s ignore Membership for now, once you have created the role, we can create a new key with the new role. As before, click “Security”, then “New Key,” but this time select “ClientRead” from the Role dropdown:

Now, let’s insert this read-only key in the gatsby-browser.js configuration file to be able to call the GraphQL API from the browser:

import React from "react" import ApolloClient from "apollo-boost" import { ApolloProvider } from "react-apollo"  const client = new ApolloClient({   uri: "https://graphql.fauna.com/graphql",   request: operation => {     operation.setContext({       headers: {         Authorization: "Bearer <CLIENT_KEY>",       },     })   }, })  export const wrapRootElement = ({ element }) => (   <ApolloProvider client={client}>{element}</ApolloProvider> )

GatsbyJS will render its Router component as a root element. If we want to use the ApolloClient everywhere in the application on the client, we need to wrap this root element with the ApolloProvider component.

8. Load the pre-rendered product data at build time

Now that everything is set up, we can finally write the actual code to load our data. Let’s start with the products we will load at build time.

For this we need to modify src/pages/index.js file to look like this:

import React from "react" import { graphql } from "gatsby" Import Layout from "../components/Layout"  const IndexPage = ({ data }) => (   <Layout>     <ul>       {data.fauna.allProducts.data.map(product => (         <li>{product.title} - {product.description}</li>       ))}     </ul>   </Layout> )  export const query = graphql` {   fauna {     allProducts {       data { _id title description }     }   } } `  export default IndexPage

The exported query will automatically get picked up by GatsbyJS and executed before rendering the IndexPage component. The result of that query will be passed as data prop into the IndexPage component.If we now run the develop script, we can see the pre-rendered documents on the development server on http://localhost:8000/.

 $  npm run develop

9. Load the reviews at run time

To load the reviews of a product on the client, we have to make some changes to the src/pages/index.js: 

import { gql } from "apollo-boost" import { useQuery } from "@apollo/react-hooks" import { graphql } from "gatsby" import React, { useState } from "react" import Layout from "../components/layout"  // Query for fetching at build-time export const query = graphql  ` {    fauna {      allProducts {        data {          _id title description         }       }      }   }   `    // Query for fetching on the client   const GET_REVIEWS = gql   `   query GetReviews($ productId: ID!) {     findProductByID(id: $ productId) {       reviews {          data {            _id username text         }       }     }   } ` const IndexPage = props => {   const [productId, setProductId] = useState(null)   const { loading, data } = useQuery(GET_REVIEWS, {     variables: {       productId     },     skip: !productId,   }) }  export default IndexPage

Let’s go through this step by step.

First, we need to import parts of the apollo-boost and apollo-react packages so we can use the GraphQL client we previously set up in the gatsby-browser.js file.

Then, we need to implement our GET_REVIEWS query. It tries to find a product by its ID and then loads the associated reviews of that product. The query takes one variable, which is the productId.

In the component function, we use two hooks: useState and useQuery

The useState hook keeps track of the productId for which we want to load reviews. If a user clicks a button, the state will be set to the productId corresponding to that button.

The useQuery hook then applies this productId to load reviews for that product from FaunaDB. The skip parameter of the hook prevents the execution of the query when the page is rendered for the first time because productId will be null.

If we now run the development server again and click on the buttons, our application should execute the query with different productIds as expected.

$  npm run develop

Conclusion

A combination of server-side data fetching and client-side hydration make JAMstack applications pretty powerful. These methods enable flexible interaction with our data so we can adhere to different business needs. 

It’s usually a good idea to load as much data at build time as possible to improve page performance. But if the data isn’t needed by all clients, or too big to be sent to the client all at once, we can split things up and switch to on-demand loading on the client. This is the case for user-specific data, pagination, or any data that changes rather frequently and might be outdated by the time it reaches the user.

In this article, we implemented an approach that loads part of the data at build time, and then loads the rest of the data in the frontend as the user interacts with the page. 

Of course, we have not implemented a login or forms yet to create new reviews. How would we tackle that? That is material for another tutorial where we can use FaunaDB’s attribute-based access control to specify what a client key can read and write from the frontend. 

The code of this tutorial can be found in this repo.

The post Build a dynamic JAMstack app with GatsbyJS and FaunaDB appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]