How We Moved From Wordpress to React and Raised $80 Million
TLDR;
Culture Trip’s website used to be a WordPress site. Now it’s a flexible, universal (isomorphic) JavaScript App powered by Next.js, React, MobX and Styled-Components on the front-end that uses WordPress as a semi-headless CMS.
$80 Million got you to click through, didn’t it?
That’s just a knee-jerk reaction from my old days as a marketer.
There is some truth to the title. More like funny timing. I started out at Culture Trip at the end of May 2017 about 6 months after our Series A funding of $20 million.
The transition from our WordPress Site to React started off with me creating our new app to serve our most important company asset and traffic hogger — the article page.
This is roughly the timeline:
- V1 launched sometime around September.
- The rest of the site was migrated progressively thereafter.
- We had a re-brand / redesign at around April — which was easily facilitated thanks to React (and being greenfield)
- Series B — $80 Milion — Apr 24, 2018
- V2 launched around May 11th which also marked most of the transition was complete
As long as my company’s PR execs don’t have a problem with it — I’m sticking to the title. ;-)
However, this is a tech story of my personal journey, and has nothing to do with the $80M…
I will say this though — the transition to this tech stack is what enabled us to deliver a better product to our users.
When I joined Culture Trip, I was brought on to move the website to the latest technologies. Specifically, move our front end from Wordpress to React.
As I started off, as any developer would do, I went over the project source code and even decided to take on a task from the backlog. The task I chose was to change the styles of our article tiles.
Seemed pretty straightforward. So, I opened up the project on my IDE searched for a CSS class or file that corresponds to the aforementioned UI block, but alas I couldn’t find it…
OK, nothing I can’t deal with, I thought to myself, I’ll just open up the site on my browser, find the element I want, and that way I’d find the corresponding CSS declarations, files, and classes.
Oh, was I wrong… As soon as I started making some changes to the file and ran the code again I saw a smorgasbord of CSS breaking. The project was no longer maintainable or scalable.
Every dev probably goes through this, you get on a new project and you start complaining about how bad the legacy code is.
But in reality, these are the constraints and evolution of almost any web project — you need to deliver results, and while doing so, best practices and thoughts of maintainability go out the window.
In order to make our product scalable, we had to change something fast.
To facilitate our change we had to decide on our new front end tech stack, which is not an easy task by itself in today’s JavaScript ecosystem jungle (fun read on this — How it feels to learn JavaScript in 2016).
Why React?
Out of the top 3 front-end libraries/frameworks list, in my view, there are only 3 major contenders: Angular, Vue and React.
Developers, especially front-end devs are very opinionated about their tech stack and chosen libraries, and there are tons of articles and blog posts out there comparing between the different choices, it always leads to a never-ending discussion which is better.
You need to pick the right tool for the job.
I was comfortable moving forward with React.
There are tons of reasons for this choice (like these, these or these) but when I had to explain my choice it boiled down to these points:
- Component-based architecture: anything and everything is a component, lego blocks, you can build every piece by itself and then glue everything together.
- Reusability: Components can be reused anywhere, take your lego block and just stick it somewhere else
- Quick learning curve: Any developer who knows Javascript can start writing components pretty quickly (more on this later).
- Proven at scale: Lots of companies use it (Facebook, Netflix, Twitter, Uber, BBC, Airbnb, Dropbox to name a few…).
- Awesome community: It’s open source, there are many 3rd party libraries and tools out there, also the React team keep on improving the library (version 16 brought a major improvement and they relicensed React to MIT).
- SEO friendly: We can render React server side (one of our key requirements).
- Great developer experience: It’s just fun! (Shameless recruitment plug — want to work with this tech stack? check out our open positions)
The journey…
Before I dive into the code and technical talk, I think it’s important to share my journey on how I like to start something like this. A lot of technical blog posts dive in straight away and miss out on some of their process, which IMHO is one of the hardest parts when approaching any project.
To start off, let’s talk about our product.
Culture Trip’s vision is to bring the world to everyone and in doing so to bring us all closer together.
We are doing this through the creation of content, mostly articles. That is why Culture Trip started off with a Wordpress site, there was a need for a CMS for writers to be able to write and publish content.
So, there I was, enthusiastic and clueless about how to move a Wordpress site to a single page application. All I had to go by were these requirements:
- SEO as a priority
- Fast load time
- Keep the same design (for that point in time)
The question now was where to start?
Research
With today’s abundance of tutorials, articles, videos, and websites you get exposed to a mass of information and it is important to be able to curate your sources, so you can have a reference to them later, you may never know when you might just write a piece yourself… :-)
If you do, how long it’ll take you to actually do it / finish it…
I started writing this article more than 11 months ago, I know this because that’s my baby boy’s age, around when time management became challenging…
But enough about that…
Side Note : I like to use a few tools to help me out with stuff like this. I love the OneTab chrome extension, (also mentioned by Culture Trip’s Product Director , and my friend Ariel Kedem)it just helps bookmark lists of tabs / links easily with timestamps and an option to name collections. So while writing this article I can almost time travel to the exact dates I was researching.
At first, I wanted to understand if it is all possible to get post data out of a WP site.
So as anyone does nowadays, I went to visit uncle Google… I searched for something along these keywords:
- WordPress react
- React on WordPress
- WordPress extract post data as JSON
- WordPress API
And so on…
Here are a few things I found useful:
- Connecting Angular and the WordPress API with wp-api-angular — SitePoint
- How to build React apps on top of the WordPress REST API
- https://github.com/roberth26/wp-react
- Headless WordPress with React
- https://github.com/Automattic/wp-calypso
- DEVELOPING A REST API APP — PART 4: CREATING OUR REACT-POWERED WORDPRESS SITE
Writing this, I can’t really remember all the stuff that I read and processed back then, so I’ll just try and TLDR; my recollection of my researches insights for You:
- Extracting data from WP is possible with WP REST API
- WP REST API has a CLI tool and a JavaScript client (WP-API)
- People have done stuff with Angular and WP REST API
- Using React to render Front End was possible
- Detaching the front end from WP is possible.
So I had my starting point. I understood what was possible and I kind of knew what I want to do. Now it was time to pick the stack and get a POC going…
How I decided on the stack
I’ve worked with React before, but I’ve never implemented server-side rendering. Naturally, working at a start-up, I did what you’re supposed to do in this situation and iterated on my research process:
- Search
- Read
- Try
I went on and dabbled with server-side rendering in React a bit, but back in v15.5.4, it wasn’t all that fun. Then I stumbled upon Next.js… I went through their great tutorial and was really impressed with the pretty simple API, it was (and is) very straightforward and added the great lifecycle hook for SSR: getInitialProps().
NextJS
TLDR;
- Easy setup
- SSR out of the box
- Routing out of the box
- Great developer experience — especially if you already know React
- Growing community
- An established company behind the tech — Zeit
Caveats:
- Understanding when lifecycle hooks get called when you start adding HOC’s and more complicated patterns
- Custom routing outside of what is provided by the framework can get complex
- Am I on the server or on the client? Confusing at first, even later.
- Overwriting Webpack config is a bitch.
I think they say it best on their site: “The React Framework For SEO friendly React…”
It’s simple enough — Next.JS is an opinionated framework, however, not that much.
What I mean is they don’t force you to do anything in a specific way. All they did is add a directory called pages:
The Pages directory is the only thing that Next.JS add — it’s basically the routing.
Then all you do is put all your top-level React components into “pages” folder.
And that’s it you will have routes to those pages that are SSR React:
There are a lot of other neat features that the guys from Zeit added to Next.js out of the box like automatic code splitting, static exports, it’s fully extensible — i.e you can add a custom server; your own next and babel config files; and best of all it’s production-ready out of the box.
Zeit has also a great deployment tool called Now that works with Next.js out of the box.
getInitialProps()
IMO (and for the sake of this post) the core of Next.js is this method. Basically, it’s another React lifecycle hook that runs before componentWillMount and on the server. So any data fetching or business logic you would want to do on the server is what goes on in this method:
MobX
TLDR;
- Simplicity in state management.
- Observable reactive pattern (or change detection): when something happens to data I want to watch -> do something.
- Tooling.
- Declarative and readable
Caveats:
- Unopinionated store structure — you will need to make decisions
- Hidden “magic”
- Using MobX with SSR is a challenge — when and how to hydrate stores
- When some React component doesn’t re-render — annoying to debug (at least in V3.4.1)
I am not going to start ranting about state management in React now, I promise :-).
My relationship with MobX started out in a React Israel Meetup. Someone demoed it in about 20 min, I immediately fell in love with the simplicity he showed.
After the meetup, I ran home and watched a 30 min EggHead tutorial by the creator of MobX: Michel Weststrate.
Back then I was working at a startup in the fin-tech industry. We were working on a complicated platform to hedge companies F/X risks.
If you know anything about finance, and even if you don’t, you can assume there’s a lot of business logic going on there. MobX handled it beautifully.
I liked the response of our tech lead at the time:
Mostly I like the fact that MobX is easy to write, teach, it has much less boilerplate code than Redux and it just works.
I even prefer it to normal React state. (with hooks being all the rage nowadays — I might change my mind soon enough)
Styled Components
TLDR;
- Modularize your CSS into a component
- Easily extendable.
- The full power of JS inside CSS
- Declarative nature
- Themeing
- SSR support
- Auto Prefixing
- Preprocessor like functionality; support nesting, etc.
- VScode / WS plugins
Caveats:
- Putting too much logic into styling
- How to structure Styled Components? One element with only its style or a React component with declarations in the length of an old school CSS file?
- Sometimes shit breaks just because you forgot a semicolon and there is no error or way of knowing even with the tooling.
- Formatting template strings is a bitch — also copy/pasting them inside certain IDE’s is annoying.
- or a React component with declarations in the length of an old school CSS file
This is another love story of mine.
A lot has been said lately about CSS in JS lately, but I’m not going through that rabbit hole.
I think Styled Components is awesome! Kudos to Max Stoiber, Evan Jacobs and everyone else involved in this incredible project!
In my view, the best way to look at Styled Components is as a CSS lego block. It encapsulates the style into a React component and has the benefit of accepting variables.
You can do a lot of cool shit with it.
Again, I like to KISS (Keep It Simple Stupid) and I believe in progressive enhancement.
Here are some Styled Components:
And we add it to the former example:
The best thing about the actual Styled Components is that they are React Components, e.g they accept props.
You can then do a lot of nifty things like this:
const fontSizeMap = {
S: `10px`,
M: `20px`,
};const Header = styled.h1`
font-weight: bold;
font-family: Helvetica;
// pass in a "size" prop to the component:font-size: ${ {(size) => size && fontSizeMap[size] } };
`;// Then we can use it in some component:const DemoStyledComponent = () => (
// pass in the size prop to our component
<Header size={ 'M' }>
Use Styled Componets - They're Awesome!
</Header>
);
WordPress
TLDR;
- WordPress is the defacto majorly used CMS.
- Easy to set up and extend
- PHP based templating system (prior to project Gutenberg)
- Has user roles, permission and authentication built-in.
- Plugin system — you can find a plugin for almost anything.
Caveats
- Clumsy — IMO the whole hook, filter and function system is a bit overly complex and leads to clumsy code.
- WP Engineers — people who only use WP tend to be too confined to the WP ecosystem, and sometimes are missing basic web development knowledge.
- Extending themes may cause a very big overhead.
- A lot of WP wizardry.
I guess I can’t sum up this post without saying a few words about WordPress…
WordPress and I have had a love/hate relationship for about 18 years now… I recall using version 3 point something.
Bottom line, WordPress is a great tool and a great CMS. If all you have are dozens of people — it’s a great choice. At Culture Trip, we have over 300 freelance creators working on the WP Admin side. So, at scale, it gets a bit messy. The code is hard to maintain and it is hard to push massive product changes.
That’s why we chose this approach to decoupling WordPress from out front-end.
Bringing it all together
Let’s recap… We have our stack: Next.js, React, MobX, Styled-Component, WordPress, back end REST API. We know what we want to achieve and we know where to start — The article page.
As I’ve demonstrated in theNext.js
section, you can see how we would fetch data from WP and render it.
So, it works like this:
- A client enters an article page.
- Our Next.js (node) server calls our BE API with the URL address the client entered (something like
sitePath/articles/some-slug
). - Back end REST server returns a response with the post content and metadata to Next.
- Next.js uses the response to SSR the HTML needed for the client.
- The client browser renders the HTML and bootstraps the JS.
After the clients’ browser loaded all of our JS — All user interactions on the client side are now handled with React & MobX.
This is a simplification of what is actually going on today, but I hope it helps illustrate my point enough. Because, I have not touched a lot of our challenges, like handling 3rd party scripts, hydrating stores, caching, a/b tests, etc. I think I have enough for a whole series of posts.
Conclusion
What did we cover in this post?
- My journey, research, and workflow.
- Why I chose to use React for CT’s front-end.
- Basics of
Next.js
,MobX
andStyled-Component
. - Connecting WordPress to our modern front-end stack.
This post is a culmination of almost 2 years of work. It’s funny when I look back at old code snippets, how they started out and how they morphed along this timeframe is staggering. When I searched for old code, I felt like Indiana Jones — doing archeological code digging.
What can you take with you? what is in it for you?
I hope I was able to be clear enough on why you would care about switching a WP site to have a React front-end and why we had to make the change at Culture Trip.
For us, as a company, this decision was what enabled us to move more quickly, hire more talent and build new awesome features, which could not have been achievable with our old stack.
I hope this post will give you enough information to do the same if you want to.
Thoughts about the future.
With Wordpress coming out with Gutenberg soon and rewriting wordpress.com
to work with Node.js (project Calypso), there might not be a reason to go down the route we did.
However, this post could just serve a guide to the murky waters which used to run in this river before.
I hope I was able to cover enough grounds in this post, it is definitely a long one. Being this is one of my first posts, I hope I was able to convey my thoughts well enough. If I wasn’t able to, or you have some constructive criticism, I’ll be happy to know in the comments.
If you’ve enjoyed this post, please give me some claps and a follow!
Also would love to know if you’d like to read any of my future post ides..
Ideas for future posts:
1. Deep dive into Mobx / Next / Styled-components
2. How the component structure was planned — pictures/images/diagrams
3. React SSR (or complex next.js) code examples.
4. Evolution of components.
5. Scaling the project.