0.1.0-alpha-4 • Published 3 years ago

@eddev/wp-next v0.1.0-alpha-4

Weekly downloads
-
License
MIT
Repository
-
Last release
3 years ago

ED's Next.js helpers for WordPress integration

This library is intended to support our effort to standardise a WordPress + Next.js approach, alongside a useful Next.js starter template and new WordPress theme template.

Features of this library

  • Automated TypeScript code generation, using the GraphQL schema provided by the WordPress installation, and GraphQL queries which are located in .graphql files in the Next.js app's codebase.
  • A Babel Macro for defining Next.js page types, which includes features which allow for query results to be pre-loaded into each page load and as well as for static generation.
  • Utilities for supporting the use of Gutenberg blocks and WordPress page templates on a Next.js frontend.
  • More to come...

Guide

GraphQL Code Generation

We're using GraphQL Code Generator, which handles the type generation based on schema + queries.

Requirements:

  • yarn add --dev @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-urql
  • yarn add @eddev/wp-next
  • A .env file which contains the endpoint for your site, eg NEXT_PUBLIC_GRAPHQL_ENDPOINT=http://ed-site.local/graphql
  • A codegen.yml file
  • Multiple .graphql files inside src/backend/queries

Your codegen.yml file should look something like this:

overwrite: true
schema: ${NEXT_PUBLIC_GRAPHQL_ENDPOINT}
documents: "src/**/*.graphql"
generates:
  src/backend/queries/index.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-urql"
      - "@eddev/wp-next/graphql-codegen"
    config:
      withHooks: false
      withComponent: false
      flattenGeneratedTypes: true
      preResolveTypes: true
      skipTypename: true
      scalars:
        ContentBlocks: ContentBlocks
hooks:
  afterOneFileWrite:
    - prettier --write

Running yarn generate or npm run generate will generate a file at /src/backend/queries/index.tsx. This file will contain all of the TypeScript types, and query functions, and can be used by your application. The generated file should be committed to your Git repo.

Running Queries

You'll usually run each query as a hook in your components. Using WordPress menus as an example, you might have a query file that looks like this.

# src/backend/queries/menus.graphql
query Menus {
  menus {
    nodes {
      id
      locations
      menuItems {
        nodes {
          title
          path
          label
          target
          childItems {
            nodes {
              title
              label
              path
              target
            }
          }
        }
      }
    }
  }
}
// src/components/global/Menu.tsx
import { MenuLocationEnum, Menus } from "../../backend/queries"

type Props = {
  location: MenuLocationEnum
}

export const Menu = ({ location }: Props) => {
  const [menuResult] = Menus.use({});

  if (!menuResult) return null;

  const menu = menuResult?.data?.menus?.nodes.find((menu) =>
    menu.locations.includes(location)
  )
  
  if (!menu) return null;
  
  return <ul>
    {menu.menuItems.nodes.map((item, key) => (
      <li key={key}>
        <Link href={item.path} passHref>
          <a target={item.target}>{item.label}</a>
        </Link>
      </li>
    ))}
  </ul>
}

Note that in the above example, MenuLocationEnum is automatically generated, and is an enum which contains a list of all of the declared in your WordPress theme with (register_nav_menu)https://developer.wordpress.org/reference/functions/register_nav_menus/. You would use this component like so.

<Menu location={MenuLocationEnum.Main} />

Also in this example, note that we're not checking to see if the query is loading, or if there is an error state. You may want to do this depending on the component, and whether or not the query has been preloaded.

It can also be helpful to write your own hooks which wrap the generated hooks. For example, you could write a useMenu hook which gets the menu data for you.

// src/hooks/useMenu.ts
import { MenuLocationEnum, Menus } from "../backend/queries";

export function useMenu(location: MenuLocationEnum) {
  const [menuResult] = Menus.use({});

  return menuResult?.data?.menus?.nodes.find((menu) =>
    menu.locations.includes(location)
  );
}

Next.js Page Type Definition Macro

To make preloading queries easier, and to help with prop typing for pages, there's a helper function called definePage. This is actually defined as a Babel Macro — while it looks and works just like a function.

The definePage() function follows a chaining pattern, and it abstracts Next.js's getStaticProps and getStaticPaths. Instead exporting a default component, and optional getStaticProps/getStaticPaths, you can write your Next.js page using this chained syntax. Behind the scenes, the macro will actually reorganise your code into Next.js's required structure.

0.1.0-alpha-4

3 years ago

0.1.0-alpha-3

3 years ago

0.1.0-alpha-2

3 years ago

0.1.0-alpha-1

3 years ago

0.0.10

3 years ago

0.0.11

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago