This project aims to replace PHP with Javascript in WordPress development by using Node.js and Express to consume data from a WordPress database using GraphQL. It uses Relay to fetch the data and deliver it into React components. This repo is the codebase for wordexpress.io, where I will write articles and documentation explaining how it works.
The core of this project revolves around setting up a connection to a WordPress database using Sequelize, defining models from that connection, and then querying those models using GraphQL. I've developed an NPM module, called WordExpress Schema, that takes care of all of this. It's included in this project. I highly suggest you start by reading the documentation.
Regarding build, this project using Webpack, and requires Node V 5.0.0. You might be able to get away with 4.0, but really just tighten up and use 5.0.
Just run npm install
and then npm run startdev
, which will start a Webpack Dev Server wrapped in Browsersync. It should automatically open a browser window pointed at localhost:3000.
To build for production, run npm run build
, which creates a dist
folder in the root directory that contains production-ready code to be deployed to a node server. You can run npm start
which will start the express server using code in the dist
folder. There is an npm run deploy
script that will call a deploy.sh shell script located in the /scripts folder. Mine is not included in this repo, since it contains production server information, and it's specific to my setup.
You'll notice a settings folder, which contains JSON files for development. This is where you can define settings for uploads, WP database connection, and some other things. Change accordingly. For production, create a prod.json file in the same format as dev.json.
This project uses Amazon AWS with an S3 bucket. If you are hosting your media files on the same server as your WP installation, set amazonS3 to false and set the uploads directory accordingly. If you are using S3, set don't include 'wp-content/uploads' to the end of the setting - it will be added for you.
This should be pretty self-explanatory: simply enter in the name of your database, username and password, and host. Make sure these are inside of "private", or else they'll be available on the client (WHICH IS BAD).
##Connecting Your WordPress Database This project uses WordExpress Schema, an NPM package I wrote specifically for this project. WordExpress schema allows you to quickly connect to a WordPress database using your database settings. It provides some out-of-the-box WordPress models (like Post, Postmeta, Terms, etc.) and some queries. For more details, read the documentation. Here is how it's being used in this project.
import { WordExpressDatabase, WordExpressGraphQLSchema } from 'wordexpress-schema';
import { publicSettings, privateSettings } from '../settings/settings';
const { name, username, password, host } = privateSettings.database;
const { amazonS3, uploads } = publicSettings;
const connectionDetails = {
name: name,
username: username,
password: password,
host: host,
amazonS3: amazonS3,
uploadDirectory: uploads
}
const Database = new WordExpressDatabase(connectionDetails);
const ConnQueries = Database.queries;
const Schema = WordExpressGraphQLSchema(ConnQueries, publicSettings);
export default Schema;
When you run npm startdev
for the first time, you'll probably get an error saying "cannot find page-title of undefined." This is probably because you haven't set a landing page in WordPress. By default, the LandingPage component queries a post with the post-name (AKA slug) of "homepage". If you are using a fresh WordPress installation, simply create a page and give it a slug of "homepage." If you are working with an exsiting WordPress database, you can change which page that gets loaded by changing the page query in the LandingPage
component. See below:
export default Relay.createContainer(LandingPage, {
fragments: {
viewer: () => Relay.QL`
fragment on User {
page(post_name:"homepage"){
id,
post_title
post_content
}
}
`,
},
});
Simply change "homepage" to anything you want. Keep in mind that it queries the post-name (AKA slug), not the post-title.
You can use any React component you'd like as a page layout by using a custom field in WordPress. First, in your application add the layout to the Layouts
object in the layouts directory. The Layouts
object stores some basic parameters that the WordpressPage
component will read. It looks like this:
import PostList from '../posts/PostList.js';
import DefaultLayout from './DefaultLayout.js';
const Layouts = {
'Default': {
Component: DefaultLayout,
showPosts: false
},
'PostList': {
Component: PostList,
showPosts: true,
postType: 'post',
limit: 10
}
};
export default Layouts;
Then, simply add a react_layout
custom field to your WordPress page. The value of the field must be the name of the layout in the Layouts
object. Here's how you can add custom fields to a page.
##Playing With GraphQL For experimentation purposes, I've kept the GrapiQL IDE publically available so you can play aroud with querying the WordExpress database. Check it out here.