ApostropheCMS 3.0: the work begins!
Active development of Apostrophe 3.0 is under way! Our 100% open-source Node.js CMS is on its way to its next long-term support release.
Recently, Brian Gantick and Tom Boutell at P’unk Avenue pair-programmed for three days to get the ball rolling on the most ambitious part of Apostrophe 3.0: gutting the Apostrophe asset pipeline in favor of Webpack, and rebuilding Apostrophe’s admin UI with Vue.
Why rebuild Apostrophe’s admin UI when it works well already? Because we want to make sure the entire developer community feels comfortable contributing. And picking a modern framework like Vue is a great way to accomplish that.
And since then, Tom has labored steadily to discard all of our old-school callback-driven code in favor of JavaScript’s new async and await keywords. Standard in Node 8.x and above, async and await make backend development much more accessible, eliminating a barrier to wider use of Apostrophe.
You can see where we’re going here: it should be as easy as possible to pitch in and help take Apostrophe anywhere the community wants it to go.
For those not familiar with the Apostrophe 3.0 process, please do check out our earlier article on planning for Apostrophe 3.0.
Since then, we’ve firmed up the decision to go with Vue rather than React, because of its lightweight tooling, friendliness to inclusion in projects that aren’t 100% Vue on the front end, and accessibility to new developers. Vue has also achieved significant popularity with enterprise customers who support Apostrophe development — a club which you are cordially invited to join.
So what exactly have we done? Most recently, we’ve:
- Replaced most of apostrophe-assets with an “build” task that leverages Webpack.
- Arrived at a convention for loading Apostrophe’s Vue components and Vue apps. Vue components will be automatically loaded from the
src/apos/components
subdirectory of any Apostrophe module if a user is logged in, and registered globally in Vue as named components such asApostrophePiecesManagerModal
; no need to callpushAsset
in 3.x. - Demonstrated the ability to override which Vue components are usedvia server-side module configuration, without making the Vue code overly strange to read.
- Completely eliminated “moog”, “apos.define”, “apos.create”, etc. on the frontend. Apostrophe’s Vue admin code will feel familiar to Vue developers and it won’t be hard to participate. Thanks to excellent Vue features like dynamic components we can keep the flexibility of our old system while adopting Vue’s patterns.
- Broken down responsibility for different parts of the admin UI between the “admin bar” and “modals” apps. There will also be an app for page settings and an app that’s instantiated for each editable area on the page. We are doing it this way because Vue apps must completely “own” the part of the DOM where they are inserted into the page. And they don’t own most of the content of the page; see the next item.
- Recommitted to keeping Nunjucks in the picture and vastly reducing the amount of JavaScript pushed to the browser for typical site visitors. By default, a logged-out user will receive almost no JavaScript from us,apart from a very lean library similar to the apostrophe-lean-frontend module we’ve already released for those who want a lighter frontend in Apostrophe 2.x. So by all means, just start using that module now. We’re taking this approach because Nunjucks has excellent performance and does a good job generating “plain old web pages…” that is, if you’re not using our apostrophe-headless module, which continues to be the right choice for those building single-page apps.
- Kept the door open to an all-Vue frontend in the future. We’re changing Apostrophe’s rendering pipeline to allow for asynchronous rendering, which means an all-Vue frontend is possible at a future date as server-side rendering matures and proves fast enough for the job. And, it means we’ll likely introduce some async features even with Nunjucks templates, such as “components” that behave much like they do in Rails.
- Chosen not to use Vuex… at least so far! Vue has several well-liked patterns for managing state, depending on the needs of your application. When state is shared between many components with changes coming thick and fast from every direction, and one master “store” of that state makes sense, Vuex is a great way to go. However, for Apostrophe, stores would have to be nested to support stacked modal experiences in several situations. And then the content would almost always turn out to “live” in a single parent modal component anyway. When the state belongs to a single component and child components can communicate their needs well just by passing events to the parent, Vuex is usually considered to be overkill. That’s why we don’t appear to need it — so far at least.
- Embraced two-way data binding. We’re doing neat things like creating our own components that support two-way data binding with
@model
, just like regular form elements do. This will allow us to do great things with apostrophe’s schemas within Vue. - We also decided to create a global Apostrophe “event bus” object,
apos.bus
, to dispatch a handful of events that are of interest to more than one Vue app. For instance, this is how we’ll handle it when the admin bar app (or something else!) wants the modal app to open the “Manage Products” modal. And, we’re using a headless Vue instance as thatbus
object.
More 3.x progress: beyond Vue
In addition to these breakthroughs, there are two more important steps toward 3.x that have already been taken this year:
- Committed to the use of async/await throughout the server-side code of 3.x. This will drastically improve the accessibility of backend Apostrophe development. There will be no APIs based on the old callback convention. Promises will be used only where
async/await
does not cover the territory. For instance, where parallelism is intended you might seePromise.all
or Bluebird’sPromise.map
applied to an array of promises returned byasync
functions. Since Apostrophe usually avoids parallel code when handling a single request, you won’t see this very often. Our philosophy is that high website traffic provides plenty of parallelism already. - Introduced Apostrophe promise events. Promise events solve numerous challenges that face developers seeking to extend Apostrophe. Unlike regular event buses, promise events (“async events” in 3.x) make sure things complete in a predictable order and provide ways to override specific event handlers when subclassing, with a greatly reduced risk of method name collisions. Already in 2.x these are now the strongly preferred way to hook into the lifecycle of a web request in Apostrophe, and writing
callAll
methods has been deprecated. In 3.x promise events will be the only way to fly. Of course they can be implemented with theasync
keyword and awaited with theawait
keyword. - Created apostrophe-lean-frontend, as mentioned earlier. Optional in 2.x, this will be the standard approach on the front end in 3.x. Definitely a good idea to adopt it early.
We still have lots of questions to answer and welcome your input. For instance, we are still deciding on the final approach to Apostrophe’s CSS assets — I suspect we’ll land on shared SASS rather than scoped CSS in Vue components, but that is still up in the air. We also have to choose a cutoff for browser support for editing purposes. Most likely we’ll ship some Babel polyfills to support IE11 — for logged in users only. The “lean frontend” we’ve created for logged-out site visitors can go much farther back.
And of course we welcome your input on the code! You can find our commits to 3.0 so far here. In a separate branch, we’re working through the conversion to async/await. During pair-programming sprints, we’ll directly on the 3.0 branch; between sprints, we’ll be working through pull requests to it.
There is also an extremely minimal test project here, although I should remind you that 3.x is not a usable CMS yet and won’t reach that maturity level for a while. Speaking of which:
2.x is the right version to start projects with now (and well into 2019)
This post wouldn’t be complete without a quick update on Apostrophe 2.x!
Apostrophe 2.x is not going away any time soon. We ourselves have over 50 clients with sites happily running on Apostrophe 2.x, a mature, long-term support platform on which we will be starting new projects ourselves at least through the first half of 2019. In order to plan our development pipeline sensibly, many features of 2.x won’t exist in 3.x right away, especially enterprise features like workflow, localization, and multisite.
The general patterns of frontend and even backend development you master with Apostrophe 2.x will translate easily to 3.x, and there will be a clear upgrade path for your existing projects.
So don’t hesitate to use 2.x and don’t “wait for 3.x.” We’re not waiting either!
Our next sprint
Our next sprint is scheduled for the end of October… and now that we’re back from attending Node+JS Interactive in Vancouver, we’re nearly there!
Speaking of which…
What we learned at Node+JS Interactive
This was our second year sponsoring Node+JS Interactive. Each year we’ve learned a lot about the market and what developers need from an all-Node.js CMS.
This year, the conference was broadened to cover JavaScript development in general and not just Node.js. That brought more frontend developers into the room, many of whom were excited to see a CMS that doesn’t require constant shifting of gears between JavaScript on the front end and PHP on the back end.
Of course, there were feature requests too. The most common being GraphQL support. Apostrophe has a headless module, which we added in response to frequent requests at last year’s conference. That module provides a great REST API to Apostrophe’s pieces and pages.
Clearly developers would like to see GraphQL next, and we look forward to adding support for that.
What’s next
As I mentioned, our next sprint is coming up very soon. We’ll be moving on from the proof of concept stages of Vue support and implementing the nuts and bolts of managing Apostrophe content with Vue. Soon after that, you’ll be able to see the new 3.x designs take shape. To whet your appetite, here’s a wireframe for the new “Manage Images” dialog box: