Slide 1

Slide 1 text

Using Vue.js in front of Drupal 8 @brian_ward 1

Slide 2

Slide 2 text

Hello, i’m Bri(an) • Twitter: @brian_ward • Drupal: drupal.org/u/briward • Website: briward.com 2 @brian_ward

Slide 3

Slide 3 text

Yeah, well, that's just, like, your opinion, man.

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

It’s finally here(ish)! 8 It’s now easier than ever to get off the island. 5 @brian_ward

Slide 6

Slide 6 text

“But we already have a theme-layer in Drupal?” 6 @brian_ward But we already have a theme-layer in Drupal?

Slide 7

Slide 7 text

Remember, you don’t have to make it fully headless @brian_ward But we already have a theme-layer in Drupal? 7

Slide 8

Slide 8 text

Drupal system Complex user form Interactive feature Pages Listings Game?!

Slide 9

Slide 9 text

benefits? • Flexibility. • Decoupled architecture. • (easily) Upgradable/changeable front-end. • Dedicated/Focused teams. • Happy front-end developers. 9 @brian_ward But we already have a theme-layer in Drupal? What are the

Slide 10

Slide 10 text

So what do we get out of the box? 10 @brian_ward So what do we get out of the box?

Slide 11

Slide 11 text

RESTful Web Services RESTful Web Services exposes entities and other resources as a RESTful web API. Required 11 @brian_ward So what do we get out of the box?

Slide 12

Slide 12 text

Serialization Serialization module provides a service for (de)serializing data to/from formats such as JSON and XML Required 12 @brian_ward So what do we get out of the box?

Slide 13

Slide 13 text

HAL Serializes entities using Hypertext Application Language (HAL) Optional 13 @brian_ward So what do we get out of the box?

Slide 14

Slide 14 text

RESTUI Provides a user interface for managing REST resources. Recommended 14 @brian_ward So what do we get out of the box?

Slide 15

Slide 15 text

3 ways to create a REST API with D8 15 @brian_ward 3 ways to create a REST API with D8

Slide 16

Slide 16 text

16 @brian_ward 3 ways to create a REST API with D8 Using the core RestResources Using View REST exports Create custom REST resources Option #1 Option #2 Option #3

Slide 17

Slide 17 text

Using the core REST resources /node/{node} /entity/block/{block} /comment/{comment} /entity/comment_type/{comment_type} @brian_ward 17 Option #1 Using the core REST resources

Slide 18

Slide 18 text

Demonstration @brian_ward 18 Short Using the core REST resources

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Pros & Cons @brian_ward 20 ✓ Straight out of the box. ✓ Requires almost no setup. ✓ No custom code necessary. - Exposes system information. - Absolutely no flexibility. - Lacks ability to version. - Unable to limit output. Using the core REST resources

Slide 21

Slide 21 text

Using views REST export Views is now in core and also comes bundled with REST support out of the box. 21 @brian_ward Option #2 Using views REST export

Slide 22

Slide 22 text

@brian_ward 22 Demonstration Short Using views REST export

Slide 23

Slide 23 text

23 @brian_ward Pros & Cons ✓ Straight out of the box. ✓ Familiar to developers. ✓ Manageable within the UI. - Returns data with incorrect types. - More flexibility, but still limited in various areas. - Authentication issues. Using views REST export

Slide 24

Slide 24 text

Creating custom REST resources Option #3 (recommended) Being object-oriented by nature, D8 allows us to extend the base ResourceBase class and create our own custom resources. This would be my recommendation. 24 @brian_ward Creating custom rest resources

Slide 25

Slide 25 text

/**
 * Provides a resource to get articles by UUID.
 *
 * @RestResource(
 * id = "articles",
 * label = @Translation("Articles (v1.0)"),
 * uri_paths = {
 * "canonical" = "/api/v1.0/articles/{uuid}"
 * }
 * )
 */
 class ArticleBundleResource extends ResourceBase { } 25 Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Slide 26

Slide 26 text

public function getArticle($uuid) {
 $entity = \Drupal::entityManager()->getStorage(‘node') ->loadByProperties([
 'uuid' => $uuid,
 'type' => 'article'
 ]);
 
 return reset($entity);
 } 26 Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Slide 27

Slide 27 text

public function get($uuid = NULL) {
 if (Uuid::isValid($uuid)) {
 $entity = $this->getArticle($uuid);
 return new ResourceResponse($this->transform($entity)); } else {
 return new ResourceResponse([
 ‘http_code’ => 400, ‘error' => 100,
 'message' => 'The UUID supplied is invalid.'
 ], 400); 
 }
 } 27 Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Slide 28

Slide 28 text

private function transform($entity) {
 return [ 'id' => (int) $entity->nid[0]->value,
 'title' => (string) $entity->title[0]->value, 'published' => (bool) $entity->published[0]->value,
 ]; 
 } 28 Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Slide 29

Slide 29 text

Pros & Cons ✓ Provides most flexibility. ✓ Transformable output. ✓ Easier to manage versions. - Requires reasonable programming knowledge. @brian_ward 29 Creating custom rest resources

Slide 30

Slide 30 text

HATEOAS API Theory HATEOAS is a constraint of the REST application architecture. In a nutshell, it is providing information on how to navigate the site's REST resources dynamically by including hypermedia links with the responses. 30 @brian_ward HATEOAS

Slide 31

Slide 31 text

Content negotiation To put it simply, this is the mechanism for determining what content-type the data will be returned in. 31 @brian_ward HATEOAS

Slide 32

Slide 32 text

Content negotiation 32 @brian_ward HATEOAS ?_format=json Basically, this is the mechanism for determining what content-type the data will be returned in. Ideally, we would want to use an “accept” header.

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Hypermedia controls 34 Provide links to related endpoints so users of your api can easily find their way around your data. @brian_ward HATEOAS

Slide 35

Slide 35 text

private function transform($entity) {
 return [
 'links' => [
 [
 'rel' => 'self',
 'uri' => '/api/v1.0/articles/'.$entity->uuid[0]->value
 ]
 ]
 ]; 
 } 35 Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Slide 36

Slide 36 text

'links' => [
 [
 'rel' => 'self',
 'uri' => '/api/v1.0/articles/'.$entity->uuid[0]->value
 ],
 [
 'rel' => ‘article.comments’,
 'uri' => '/api/v1.0/articles/'.$entity->uuid[0]->value.'/comments'
 ]
 ] Plugin/Rest/Resource/ArticleBundleResource.php 36 @brian_ward

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Versioning 38 @brian_ward As Phil Sturgeon says “There are many wrong ways to version your API”. Don’t get too caught up about this.

Slide 39

Slide 39 text

Authentication 39 @brian_ward • Basic auth • Cookie • oAuth

Slide 40

Slide 40 text

@brian_ward 40 Now that we have created our API, we can play around with it on the front-end. Now we’re ready

Slide 41

Slide 41 text

Introducing Vue.js Vue.js is a MVVM JavaScript library for building modern web interfaces. It provides data-reactive components with a simple and flexible API. @brian_ward 41 Introducing Vue.js

Slide 42

Slide 42 text

Top trending JS framework on Github. @brian_ward Introducing Vue.js 42 First stable version released earlier this month. Evan You is also a core developer on the MeteorJS project & previously a Google employee. Has awesome documentation.

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

View new Vue({ el: '#app' }) Each Vue instance is associated with a DOM element (el). 44 @brian_ward Introducing Vue.js

Slide 45

Slide 45 text

ViewModel 45 @brian_ward new Vue({ /* options */ }) • An object that syncs the Model and the View. • Every Vue instance is a ViewModel. Introducing Vue.js

Slide 46

Slide 46 text

Model new Vue({ data: {} }) An object that is used as data inside a Vue instance will become reactive (Vue instances that are observing our objects will be notified of the changes). @brian_ward 46 Introducing Vue.js

Slide 47

Slide 47 text

var MyComponent = Vue.extend({}) Components 47 @brian_ward Components are simply a convenient way to structure and organise our applications. Optional Introducing Vue.js

Slide 48

Slide 48 text

Browserify & Vueify require('./app.vue') 48 @brian_ward Browserify lets you require('modules') in the browser by bundling up all of your dependencies. Optional Introducing Vue.js

Slide 49

Slide 49 text

this.$http.get(url, callback) VueResource Using the official Vue-Resource plugin, we can request and store our Drupal content as data objects. Recommended 49 @brian_ward Introducing Vue.js

Slide 50

Slide 50 text

router.on(url, callback) Director A tiny and isomorphic URL router for JavaScript Recommended 50 @brian_ward Introducing Vue.js

Slide 51

Slide 51 text

So where does Drupal come in? 51 @brian_ward Introducing Vue.js

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

Great, let’s see that in action! Firstly we will need to create our package.json, HTML & bootstrap JS files. From there we’ll load in our components and interact with our API. @brian_ward 53 Introducing Vue.js

Slide 54

Slide 54 text

{
 "main": "./src/app.js",
 "scripts": {
 "watch": "watchify -v -t vueify -e ./src/app.js -o build/build.js"
 },
 "devDependencies": {
 "vueify": "^1.1.5",
 "watchify": "^3.3.1"
 },
 "dependencies": {
 "director": "^1.2.8",
 "vue": "^0.12.9",
 "vue-resource": "^0.1.11"
 }
 } package.json 54 @brian_ward

Slide 55

Slide 55 text


 
 
 
 
 
 


 
 
 
 
 
 55 index.html @brian_ward

Slide 56

Slide 56 text

/**
 * Boot up the Vue instance with the VueResource plugin.
 */
 var Vue = require(‘vue') 
 Vue.use(require(‘vue-resource’)) var app = new Vue(require('./app.vue')) 56 start.js @brian_ward

Slide 57

Slide 57 text

/**
 * Wire up the router.
 */
 var Router = require('director').Router
 var router = new Router()
 
 router.on(‘/articles/:uuid’, function (uuid) {
 app.view = 'article-view'
 app.params.uuid = uuid
 })
 
 router.init('/') 57 start.js @brian_ward

Slide 58

Slide 58 text


 
 
 58 app.vue @brian_ward

Slide 59

Slide 59 text


 module.exports = {
 el: '#app',
 data: {
 view: '',
 params: {
 uuid: ''
 }
 },
 components: {
 'article-view': require('./views/article-view.vue')
 }
 }
 59 app.vue @brian_ward

Slide 60

Slide 60 text


 



 


 60 article-view.vue @brian_ward

Slide 61

Slide 61 text

61 


 


{{ article.title }}

{{{ article.body }}}

 


 @brian_ward article-view.vue

Slide 62

Slide 62 text


 module.exports = {
 props: ['params'],
 data: function () {
 return {
 article: {}
 }
 },
 ready: function() { var url = '/api/v1.0/articles/' + uuid + '?_format=json';
 this.$http.get(url, function (article) {
 this.$set('article', article)
 })
 } }
 62 @brian_ward article-view.vue

Slide 63

Slide 63 text

And that’s it. By using Drupal 8 and Vue.js we’re able to create a beautiful, maintainable and de-coupled application. https://github.com/briward/examples 63 @brian_ward

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

Useful links 65 @brian_ward • http://vuejs.org • https://en.wikipedia.org/wiki/Model_View_ViewModel • http://browserify.org • https://github.com/vuejs/vueify • http://vuejs.org/guide/components.html • http://www.w3.org/TR/components-intro • http://drupal.org/project/restui • ...how-to-enable-cors-requests-against-drupal-8/ • Phil Sturgeon’s book “Build APIs you won’t hate”.