Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

transitive-bullshit/react-static-tweets

Repository files navigation

Deprecation Notice

Vercel released react-tweet which is a better maintained version of this library. Please use that instead.


React Static Tweets

Extremely fast static renderer for tweets.

NPM Build Status Prettier Code Formatting

React Static Tweets

Demo

Visit react-static-tweets.vercel.app and append your tweet ID. You can also append /dynamic/<tweetId> if you want to test the non-SSR version.

Why?

Twitter's embedding SDK is horribly slow and inefficient. For embedding tweets on your site (including SSR), this solution is significantly more performant. 🔥

This project takes Vercel's work on static tweet rendering and packages it up into two easy-to-use NPM packages.

Features

  • Fast - 10-100x faster than using Twitter's iframe embedding.
  • 🔥 Solid - Used in production by super.so, react-notion-x, and others.
  • 🚀 Simple - TypeScript + React.

Install

npm install react-static-tweets static-tweets date-fns
# or
yarn add react-static-tweets static-tweets date-fns

Note: this project currently only works with Next.js (see #2 for more info).

Usage

You'll need to pre-fetch tweet data server-side using fetchTweetAst and then render it using the Tweet component.

import React from 'react'
import { fetchTweetAst } from 'static-tweets'
import { Tweet } from 'react-static-tweets'

const tweetId = '1358199505280262150'

export const getStaticProps = async () => {
  try {
    const tweetAst = await fetchTweetAst(tweetId)

    return {
      props: {
        tweetAst
      },
      revalidate: 10
    }
  } catch (err) {
    console.error('error fetching tweet', err)

    throw err
  }
}

export default function Example({ tweetAst }) {
  return <Tweet ast={tweetAst} />
}

Note that Tweet is a React server component, and has been tested with Next.js 13 appDir.

Advanced Usage

If you have multiple tweets and are okay with using client components, then we recommend using the built-in TwitterContextProvider to store a map from tweet ID to tweet AST.

In this example, we're using the client component imports from react-static/tweets/client which use React Context under the hood:

import React from 'react'
import pMap from 'p-map'
import { fetchTweetAst } from 'static-tweets'
import { TweetClient, TwitterContextProvider } from 'react-static-tweets/client'

// NOTE: You'll likely infer your list of tweets by introspecting your page's
// content from a CMS.
const tweetIds = [
  '1358199505280262150',
  '1374492662061953034',
  '1358199505280262150'
  // ...
]

export const getStaticProps = async () => {
  try {
    // Fetch all tweet ASTs statically
    const tweetAsts = await pMap(tweetIds, fetchTweetAst, {
      concurrency: 4
    })

    // Create a map from tweet ID to tweet AST
    const tweetAstMap = tweetIds.reduce((tweetId, map, index) => ({
      ...map,
      [tweetId]: tweetAsts[index]
    }))

    return {
      props: {
        tweetAstMap
      },
      revalidate: 60
    }
  } catch (err) {
    console.error('error fetching tweets', err)

    throw err
  }
}

export default function Example({ tweetAstMap }) {
  return (
    <TwitterContextProvider value={{ tweetAstMap }}>
      {tweetIds.map((tweetId) => (
        <div key={tweetId}>
          {/* 
          There's no need to pass the tweet AST directly if it is provided via TwitterContextProvider. This is nice in situations where you're 
          rendering tweets in deeply nested component trees.
          */}
          <TweetClient id={tweetId} />
        </div>
      ))}
    </TwitterContextProvider>
  )
}

Styles

You'll need to import some CSS styles as well. For Next.js, we recommend you put these in pages/_app:

import 'react-static-tweets/styles.css'

Next.js Config

Add pbs.twimg.com to your next.config.js since we use next/image to load images.

module.exports = {
  images: {
    domains: ['pbs.twimg.com']
  }
}

Next.js Example

Here is an example Next.js project, with the most important code in pages/[tweetId].tsx. You can view this example live on Vercel.

Packages

Package NPM Environment Description
static-tweets NPM Node.js Fetches tweet ASTs.
react-static-tweets NPM Browser + SSR React renderer for tweets given an AST.

Dynamic Client-Side Rendering

react-static-tweets is meant for rendering tweets as efficiently as possible. The Tweet component assumes that you've already pre-fetched tweet AST data ahead of time, most likely during SSR.

Rendering dynamic tweets on the client-side is supported; however, you'll need to wrap fetchTweetAst in an API route since it can't be used from the browser.

You can view an example of this in action via example/pages/dynamic/[tweetId].tsx.

Credit

My main contribution is packaging the Vercel team's excellent work into two isolated packages: static-tweets for server-side fetching of tweet ASTs and react-static-tweets for client-side rendering as well as SSR.

  • Inspired by this demo from the Vercel team
  • And the underlying repo by Luis Alvarez
  • Most of the core code is adapted from Guillermo Rauch's blog
  • Converted the JS codebase to TypeScript
  • Removed styled-jsx because using a flat CSS file (with a .static-tweet class prefix) makes bundling for NPM easier
  • Fixed some minor formatting bugs

License

MIT © Travis Fischer

Support my OSS work by following me on twitter twitter