Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Drupaldelphia 2018: Drupal Unhitched: The CMS in Decoupled Architectures

Drupaldelphia 2018: Drupal Unhitched: The CMS in Decoupled Architectures

dirtystylus

April 27, 2018
Tweet

More Decks by dirtystylus

Other Decks in Technology

Transcript

  1. Descriptive, Not Prescriptive I’m not telling you how to do

    this stuff. But I hope all of this helps. Drupal Unhitched / @dirtystylus 6
  2. 3 Things 1. What is a decoupled CMS? 2. Decoupled

    Scenarios Drupal Unhitched / @dirtystylus 7
  3. 3 Things 1. What is a decoupled CMS? 2. Decoupled

    Scenarios 3. Decoupling Drupal Drupal Unhitched / @dirtystylus 7
  4. What is a decoupled CMS? —An architecture for websites and

    applications where the CMS is not used to render the user- facing site or application. Drupal Unhitched / @dirtystylus 9
  5. CMS (Drupal 8) + Touchscreen Interactive (React) + JS Website

    (React) Drupal Unhitched / @dirtystylus 13
  6. CMS (Drupal 7) + CMS-rendered Website + Touch Wall (Cinder/C++)

    + 2 Touchscreen Interactives (AngularJS) + iOS / Android Native Applications Drupal Unhitched / @dirtystylus 32
  7. Pros —Back and Front End systems are swappable —Teams can

    divide and conquer Drupal Unhitched / @dirtystylus 40
  8. Cons —Larger tech stack (Drupal, JS, multiple environments) —Maintenance —For

    websites you lose built-in functionality of CMS: menus/routing/accessibility/SEO Drupal Unhitched / @dirtystylus 41
  9. Start with Content —Getting content ready to travel —NO Presentation

    specific names NO Drupal Unhitched / @dirtystylus 43
  10. Start with Content —Getting content ready to travel —NO Presentation

    specific names NO —Decouple your mind Drupal Unhitched / @dirtystylus 43
  11. Start with Content —Getting content ready to travel —NO Presentation

    specific names NO —Decouple your mind —Content in many forms/faces Drupal Unhitched / @dirtystylus 43
  12. { "nid": [ { "value": 1 } ], "uuid": [

    { "value": "3036ea2d-7502-4c64-8bc6-2e9ee3a0f897" } ], "vid": [ { "value": 1 } ], "langcode": [ { "value": "en" } ], "type": [ { "target_id": "book", "target_type": "node_type", "target_uuid": "a3c32842-68b2-46fd-b70e-d6ed9e71ee2d" } ], "revision_timestamp": [ { "value": "2018-04-23T18:10:59+00:00", "format": "Y-m-d\\TH:i:sP" } ], "revision_uid": [ { "target_id": 1, "target_type": "user", "target_uuid": "a7484c09-d013-402e-b070-46c0d84a7b28", "url": "/user/1" } ], "revision_log": [], "status": [ { "value": true } ], "title": [ { "value": "The Fifth Season" } ], "uid": [ { "target_id": 1, "target_type": "user", "target_uuid": "a7484c09-d013-402e-b070-46c0d84a7b28", "url": "/user/1" } ], "created": [ { "value": "2018-04-23T18:10:29+00:00", "format": "Y-m-d\\TH:i:sP" } ], "changed": [ { "value": "2018-04-23T18:10:59+00:00", "format": "Y-m-d\\TH:i:sP" } ], "promote": [ { "value": true } ], "sticky": [ { "value": false } ], "default_langcode": [ { "value": true } ], "revision_translation_affected": [ { "value": true } ], "path": [ { "alias": null, "pid": null, "langcode": "en" } ], "body": [ { "value": "<p>Part one of the Broken Earth trilogy.</p>\r\n", "format": "basic_html", "processed": "<p>Part one of the Broken Earth trilogy.</p>", "summary": "" } ] } Drupal Unhitched / @dirtystylus 51
  13. { "nid": [ { "value": 1 } ], "type": [

    { "target_id": "book", "target_type": "node_type", "target_uuid": "a3c32842-68b2-46fd-b70e-d6ed9e71ee2d" } ], "title": [ { "value": "The Fifth Season" } ], "body": [ { "value": "<p>Part one of the Broken Earth trilogy.</p>\r\n", "format": "basic_html", "processed": "<p>Part one of the Broken Earth trilogy.</p>", "summary": "" } ] } Drupal Unhitched / @dirtystylus 52
  14. REST Exports —Views! (! old friend) —“Provide a REST Export”

    checkbox ✅ Drupal Unhitched / @dirtystylus 53
  15. [ { "title": "Kim Stanley Robinson", "body": "<p>Author of the

    <em>Mars</em> trilogy and <em>New York 2140</em>.</p>\r\n", "field_books": [ "2" ] }, { "title": "N. K. Jemisin", "body": "<p>Hugo Award-winning author of the Broken Earth trilogy.</p>\r\n", "field_books": [ "1" ] } ] Drupal Unhitched / @dirtystylus 57
  16. … $a_query = \Drupal::entityQuery('node'); $a_query->condition('status', 1); $a_query->condition('type', 'event'); $entity_ids =

    $a_query->execute(); $events = Node::loadMultiple($entity_ids); foreach ($events as $event) { $item['id'] = (int) $event->nid->value; $date = $event->field_event_date->value; $item['date'] = $date; $item['title'] = $event->title->value; $item['display_title'] = $event->field_display_title->value; $image_data = MediaAssetService::getMediaPathSingle($event, 'field_featured_image'); $item['image'] = urldecode($image_data['image']); $item['image_relative'] = urldecode($image_data['image_relative']); $data[] = $item; } $response = new JsonResponse(['data' => $data]); return $response; … Drupal Unhitched / @dirtystylus 61
  17. { "data": [ { "type": "node--author", "id": "88223a76-278d-4fc6-9945-0bdb56cc78d3", "attributes": {

    "nid": 2, "body": { "value": "<p>Winner of the Hugo Award.</p>\r\n", "format": "basic_html", "processed": "<p>Winner of the Hugo Award.</p>", "summary": "" }, "field_display_name": { "value": "N. K. Jemisin", "format": "basic_html", "processed": "N. K. Jemisin" } }, "relationships": { "field_books": { "data": [ { "type": "node--book", "id": "e8c31c68-4fe5-4046-ab3f-1cb42e1f314f" } ], }, } ], } Drupal Unhitched / @dirtystylus 64
  18. { "attributes": { "nid": 2, "body": { "value": "<p>Winner of

    the Hugo Award.</p>\r\n", "format": "basic_html", "processed": "\<p>Winner of the Hugo Award.</p>", "summary": "" }, "field_display_name": { "value": "N. K. Jemisin", "format": "basic_html", "processed": "N. K. Jemisin" } }, } Drupal Unhitched / @dirtystylus 65
  19. { "relationships": { "field_books": { "data": [ { "type": "node--book",

    "id": "e8c31c68-4fe5-4046-ab3f-1cb42e1f314f" } ], }, } Drupal Unhitched / @dirtystylus 66
  20. Relationships are complicated /jsonapi/node/[Content Type]?include=[Field Name] for example (we want

    field_books): /jsonapi/node/author?include=field_books Drupal Unhitched / @dirtystylus 67
  21. { "included": [ { "type": "node--book", "id": "e8c31c68-4fe5-4046-ab3f-1cb42e1f314f", "attributes": {

    "nid": 1, "title": "The Fifth Season", "body": { "value": "<p>Part one of the Broken Earth trilogy.</p>\r\n", "format": "basic_html", "processed": "<p>Part one of the Broken Earth trilogy.</p>", "summary": "" } }, } } Drupal Unhitched / @dirtystylus 68
  22. Installation Note —Download the module (or use drush dl graphql)

    —Run composer require webonyx/graphql-php at root level (error otherwise) Drupal Unhitched / @dirtystylus 71
  23. Installation Note —Download the module (or use drush dl graphql)

    —Run composer require webonyx/graphql-php at root level (error otherwise) —Enable the module Drupal Unhitched / @dirtystylus 71
  24. { "data": { "nodeQuery": { "entities": [ { "entityId": "1",

    "entityLabel": "The Fifth Season" }, { "entityId": "2", "entityLabel": "New York 2140" }, { "entityId": "3", "entityLabel": "N. K. Jemisin" }, { "entityId": "4", "entityLabel": "Kim Stanley Robinson" } ] } } } Drupal Unhitched / @dirtystylus 77
  25. Node Query w/ Types (Author) query { nodeQuery { entities

    { ...on NodeAuthor { entityId title body { value } fieldDisplayName { value } fieldBooks { entity { entityId title } } } } } } Drupal Unhitched / @dirtystylus 78
  26. { "data": { "nodeQuery": { "entities": [ {}, {}, {

    "entityId": "3", "title": "N. K. Jemisin", "body": { "value": "<p>Hugo Award-winning author of the Broken Earth trilogy.</p>\r\n" }, "fieldDisplayName": { "value": "N. K. Jemisin" }, "fieldBooks": [ { "entity": { "entityId": "1", "title": "The Fifth Season" } } ] }, { "entityId": "4", "title": "Kim Stanley Robinson", "body": { "value": "<p>Author of the <em>Mars</em> trilogy and <em>New York 2140</em>.</p>\r\n" }, "fieldDisplayName": { "value": "Kim Stanley Robinson" }, "fieldBooks": [ { "entity": { "entityId": "2", "title": "New York 2140" } } ] } ] } } } Drupal Unhitched / @dirtystylus 80
  27. query { nodeQuery { entities { ...on NodeAuthor { entityId

    title body { value } fieldDisplayName { value } fieldBooks { entity { entityId title } } } ...on NodeBook { entityId title body { value } } } } } Drupal Unhitched / @dirtystylus 81
  28. Filter by Node Type query { nodeQuery (filter: {conditions: [{

    field: "type" value: "author" operator: EQUAL }] } ) { … } } Drupal Unhitched / @dirtystylus 82
  29. query { nodeQuery (filter: {conditions: [{ field: "type" value: "author"

    operator: EQUAL }] } ) { entities { ...on NodeAuthor { entityId title body { value } fieldBooks { entity { title body { value } } } } } } } Drupal Unhitched / @dirtystylus 83
  30. { "data": { "nodeQuery": { "entities": [ { "entityId": "3",

    "title": "N. K. Jemisin", "body": { "value": "<p>Hugo Award-winning author of the Broken Earth trilogy.</p>\r\n" }, "fieldBooks": [ { "entity": { "title": "The Fifth Season", "body": { "value": "<p>Part one of the Broken Earth trilogy.</p>\r\n" } } } ] }, Drupal Unhitched / @dirtystylus 84
  31. We’ve tried: —Polling for changes (are we there yet?) —NodeJS

    (get a server in the middle, maybe Socket I/O) Drupal Unhitched / @dirtystylus 86
  32. Enter Progressive Web Applications —CMS to Application communication is a

    use case —PWAs have Service Workers and Push Notifications Drupal Unhitched / @dirtystylus 87
  33. Web Push API —Gives web applications the ability to receive

    messages pushed to them from a server Drupal Unhitched / @dirtystylus 88
  34. Web Push API —Gives web applications the ability to receive

    messages pushed to them from a server —Requires a subscription to be activated, but once allowed, the subscription is saved by the browser Drupal Unhitched / @dirtystylus 88
  35. Web Push API —Gives web applications the ability to receive

    messages pushed to them from a server —Requires a subscription to be activated, but once allowed, the subscription is saved by the browser —You can pass “messages”, but fundamentally you are passing data for your app or website to interpret as you see fit Drupal Unhitched / @dirtystylus 88
  36. Web Push API —Gives web applications the ability to receive

    messages pushed to them from a server —Requires a subscription to be activated, but once allowed, the subscription is saved by the browser —You can pass “messages”, but fundamentally you are passing data for your app or website to interpret as you see fit —Browsers handle pushing the data through Service Workers, so a third party is not required Drupal Unhitched / @dirtystylus 88
  37. Fine Print —Limited browser support: ✅ Chrome, ✅ Firefox, "

    Safari (coming soon?) Drupal Unhitched / @dirtystylus 89
  38. Fine Print —Limited browser support: ✅ Chrome, ✅ Firefox, "

    Safari (coming soon?) —Spec is considered experimental, so it may change in the future Drupal Unhitched / @dirtystylus 89
  39. Fine Print —Limited browser support: ✅ Chrome, ✅ Firefox, "

    Safari (coming soon?) —Spec is considered experimental, so it may change in the future —Great for kiosks, but in the wild, you can’t guarantee that a user will subscribe Drupal Unhitched / @dirtystylus 89
  40. Fine Print —Limited browser support: ✅ Chrome, ✅ Firefox, "

    Safari (coming soon?) —Spec is considered experimental, so it may change in the future —Great for kiosks, but in the wild, you can’t guarantee that a user will subscribe —Sockets for non-web-based projects (Cinder/C++, Unity) Drupal Unhitched / @dirtystylus 89
  41. Where to Next? —Two-way communication —Content Authoring via JS Front

    End (WordPress and Drupal) Drupal Unhitched / @dirtystylus 91
  42. Takeaways —Start with your Content, and make that portable —There’s

    many different ways to expose your content Drupal Unhitched / @dirtystylus 92
  43. Takeaways —Start with your Content, and make that portable —There’s

    many different ways to expose your content —You can do this! Drupal Unhitched / @dirtystylus 92