Share
Embed
Transcript
141 slides
-
Drupal Unhitched The CMS in Decoupled Architectures Drupaldelphia 2018 Drupal
Unhitched / @dirtystylus 1 -
Hi. Mark Llobrera Technology Director, Bluecadet Philadelphia @dirtystylus @bluecadet Drupal
Unhitched / @dirtystylus 2 -
Descriptive, Not Prescriptive I’m not telling you how to do
this stuff. But I hope all of this helps. Drupal Unhitched / @dirtystylus 6 -
3 Things 1. What is a decoupled CMS? Drupal Unhitched
/ @dirtystylus 7 -
3 Things 1. What is a decoupled CMS? 2. Decoupled
Scenarios Drupal Unhitched / @dirtystylus 7 -
3 Things 1. What is a decoupled CMS? 2. Decoupled
Scenarios 3. Decoupling Drupal Drupal Unhitched / @dirtystylus 7 -
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 -
Stop me if you’ve heard this one before Drupal Unhitched
/ @dirtystylus 10 -
CMS (Drupal 8) + Touchscreen Interactive (React) + JS Website
(React) Drupal Unhitched / @dirtystylus 13 -
CMS (Drupal 8) + CMS-rendered Website + Digital Signage (React)
Drupal Unhitched / @dirtystylus 19 -
CMS + CMS-rendered Website + React components Drupal Unhitched /
@dirtystylus 24 -
CMS (Drupal 7) + CMS-rendered Website + Touch Wall (Cinder/C++)
+ 2 Touchscreen Interactives (AngularJS) + iOS / Android Native Applications Drupal Unhitched / @dirtystylus 32 -
Pros —Back and Front End systems are swappable Drupal Unhitched
/ @dirtystylus 40 -
Pros —Back and Front End systems are swappable —Teams can
divide and conquer Drupal Unhitched / @dirtystylus 40 -
Cons —Larger tech stack (Drupal, JS, multiple environments) —Maintenance Drupal
Unhitched / @dirtystylus 41 -
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 -
Start with Content —Getting content ready to travel Drupal Unhitched
/ @dirtystylus 43 -
Start with Content —Getting content ready to travel —NO Presentation
specific names NO Drupal Unhitched / @dirtystylus 43 -
Start with Content —Getting content ready to travel —NO Presentation
specific names NO —Decouple your mind Drupal Unhitched / @dirtystylus 43 -
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 -
HOW?? —Core: RESTful Web Services —Custom Controller —JSON API Drupal
Unhitched / @dirtystylus 47 -
HOW?? —Core: RESTful Web Services —Custom Controller —JSON API —GraphQL
Drupal Unhitched / @dirtystylus 47 -
RESTful Web Services Two basic approaches: —Core RESTful Services Drupal
Unhitched / @dirtystylus 48 -
RESTful Web Services Two basic approaches: —Core RESTful Services —REST
Exports Drupal Unhitched / @dirtystylus 48 -
Core RESTful Services —Core REST Module —REST UI Module https://drupal.org/project/restui
Drupal Unhitched / @dirtystylus 49 -
{ "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 -
{ "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 -
REST Exports —Views! (! old friend) —“Provide a REST Export”
checkbox ✅ Drupal Unhitched / @dirtystylus 53 -
[ { "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 -
Routing mann.season: path: 'api/season' defaults: _controller: \Drupal\mann_api\Controller\Season::api methods: [GET] requirements:
_access: 'TRUE' Drupal Unhitched / @dirtystylus 60 -
… $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 -
Out of the box: /jsonapi/node/[Content Type] for example: /jsonapi/node/author Drupal
Unhitched / @dirtystylus 63 -
{ "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 -
{ "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 -
{ "relationships": { "field_books": { "data": [ { "type": "node--book",
"id": "e8c31c68-4fe5-4046-ab3f-1cb42e1f314f" } ], }, } Drupal Unhitched / @dirtystylus 66 -
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 -
{ "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 -
Installation Note —Download the module (or use drush dl graphql)
Drupal Unhitched / @dirtystylus 71 -
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 -
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 -
Explorer allows you to test out queries Drupal Unhitched /
@dirtystylus 72 -
Simple Query query { nodeQuery { entities { entityId, entityLabel
} } } Drupal Unhitched / @dirtystylus 76 -
{ "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 -
Node Query w/ Types (Author) query { nodeQuery { entities
{ ...on NodeAuthor { entityId title body { value } fieldDisplayName { value } fieldBooks { entity { entityId title } } } } } } Drupal Unhitched / @dirtystylus 78 -
References are Easy(ish) fieldBooks { entity { entityId title }
} Drupal Unhitched / @dirtystylus 79 -
{ "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 -
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 -
Filter by Node Type query { nodeQuery (filter: {conditions: [{
field: "type" value: "author" operator: EQUAL }] } ) { … } } Drupal Unhitched / @dirtystylus 82 -
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 -
{ "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 -
We’ve tried: —Polling for changes (are we there yet?) Drupal
Unhitched / @dirtystylus 86 -
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 -
Enter Progressive Web Applications —CMS to Application communication is a
use case Drupal Unhitched / @dirtystylus 87 -
Enter Progressive Web Applications —CMS to Application communication is a
use case —PWAs have Service Workers and Push Notifications Drupal Unhitched / @dirtystylus 87 -
Web Push API —Gives web applications the ability to receive
messages pushed to them from a server Drupal Unhitched / @dirtystylus 88 -
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 -
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 -
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 -
Fine Print —Limited browser support: ✅ Chrome, ✅ Firefox, "
Safari (coming soon?) Drupal Unhitched / @dirtystylus 89 -
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 -
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 -
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 -
Where to Next? —Two-way communication —Content Authoring via JS Front
End (WordPress and Drupal) Drupal Unhitched / @dirtystylus 91 -
Takeaways —Start with your Content, and make that portable Drupal
Unhitched / @dirtystylus 92 -
Takeaways —Start with your Content, and make that portable —There’s
many different ways to expose your content Drupal Unhitched / @dirtystylus 92 -
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 -
THANK YOU. Mark Llobrera Technology Director, Bluecadet Philadelphia @dirtystylus @bluecadet
Drupal Unhitched / @dirtystylus 94