Using VueJS in front of Drupal 8

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

Transcript of Using VueJS in front of Drupal 8

Using Vue.js in front of Drupal 8

@brian_ward1

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

2 @brian_ward

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

It’s finally here(ish)!8

It’s now easier than ever to get off the island.

5 @brian_ward

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

6 @brian_wardBut we already have a theme-layer in Drupal?

Remember, you don’t have to make it fully headless

@brian_wardBut we already have a theme-layer in Drupal? 7

Drupal system

Complex user form Interactive feature

Pages Listings

Game?!

benefits?• Flexibility. • Decoupled architecture. • (easily) Upgradable/changeable front-end. • Dedicated/Focused teams. • Happy front-end developers.

9 @brian_wardBut we already have a theme-layer in Drupal?

What are the

So what do we get out of the box?

10 @brian_wardSo what do we get out of the box?

RESTful Web ServicesRESTful Web Services exposes entities and

other resources as a RESTful web API.

Required

11 @brian_wardSo what do we get out of the box?

SerializationSerialization module provides a service for (de)serializing data to/from formats such as

JSON and XML

Required

12 @brian_wardSo what do we get out of the box?

HALSerializes entities using Hypertext

Application Language (HAL)

Optional

13 @brian_wardSo what do we get out of the box?

RESTUIProvides a user interface for managing REST

resources.

Recommended

14 @brian_wardSo what do we get out of the box?

3 ways to create a REST API with D8

15 @brian_ward3 ways to create a REST API with D8

16 @brian_ward3 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

Using the core REST resources

/node/{node} /entity/block/{block} /comment/{comment} /entity/comment_type/{comment_type}

@brian_ward17

Option #1

Using the core REST resources

Demonstration

@brian_ward18

Short

Using the core REST resources

Pros & Cons

@brian_ward20

✓ 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

Using views REST exportViews is now in core and also comes bundled with REST

support out of the box.

21 @brian_ward

Option #2

Using views REST export

@brian_ward22

DemonstrationShort

Using views REST export

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

Creating custom REST resourcesOption #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_wardCreating custom rest resources

/** * 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 { }

25Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

public function getArticle($uuid) { $entity = \Drupal::entityManager()->getStorage(‘node') ->loadByProperties([ 'uuid' => $uuid, 'type' => 'article' ]); return reset($entity);

}

26Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

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); } }

27Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

private function transform($entity) { return [ 'id' => (int) $entity->nid[0]->value, 'title' => (string) $entity->title[0]->value, 'published' => (bool) $entity->published[0]->value, ];}

28Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

Pros & Cons✓ Provides most flexibility. ✓ Transformable output. ✓ Easier to manage versions.

- Requires reasonable programming knowledge.

@brian_ward29Creating custom rest resources

HATEOASAPI 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_wardHATEOAS

Content negotiationTo put it simply, this is the mechanism for determining what

content-type the data will be returned in.

31 @brian_wardHATEOAS

Content negotiation

32 @brian_wardHATEOAS

?_format=jsonBasically, this is the mechanism for determining what content-type

the data will be returned in. Ideally, we would want to use an “accept” header.

Hypermedia controls

34

Provide links to related endpoints so users of your api can easily find their way around your data.

@brian_wardHATEOAS

private function transform($entity) { return [ 'links' => [ [ 'rel' => 'self', 'uri' => '/api/v1.0/articles/'.$entity->uuid[0]->value ] ] ];}

35Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward

'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

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.

Authentication

39 @brian_ward

• Basic auth • Cookie • oAuth

@brian_ward40

Now that we have created our API, we can play around with it on the front-end.

Now we’re ready

Introducing Vue.jsVue.js is a MVVM JavaScript library for building modern web

interfaces. It provides data-reactive components with a simple and flexible API.

@brian_ward41Introducing Vue.js

Top trending JS framework on Github.

@brian_wardIntroducing 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.

Viewnew Vue({ el: '#app' })

Each Vue instance is associated with a DOM element (el).

44 @brian_wardIntroducing Vue.js

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

Modelnew 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_ward46Introducing Vue.js

var MyComponent = Vue.extend({})

Components

47 @brian_ward

Components are simply a convenient way to structure and organise our applications.

Optional

Introducing Vue.js

Browserify & Vueifyrequire('./app.vue')

48 @brian_ward

Browserify lets you require('modules') in the browser by bundling up all of your dependencies.

Optional

Introducing Vue.js

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_wardIntroducing Vue.js

router.on(url, callback)

Director

A tiny and isomorphic URL router for JavaScript

Recommended

50 @brian_wardIntroducing Vue.js

So where does Drupal come in?

51 @brian_wardIntroducing Vue.js

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_ward53Introducing Vue.js

{ "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

<!DOCTYPE html> <html> <head> <meta charset=“utf-8"></head> <body> <div id="app"></div> <!-- Load our build script --> <script src="build/build.js"></script> </body> </html>

55index.html @brian_ward

/** * 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'))

56start.js @brian_ward

/** * 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('/')

57start.js @brian_ward

<template> <component is="{{ view }}" class="view" params="{{ params }}" v-transition transition-mode="out-in"> </component> </template>

58app.vue @brian_ward

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

59app.vue @brian_ward

<template> <div class="post full"> <article class="post-content"> <h1 v-text="article.title"></h1> <div v-html="article.body"></div> </article> </div> </template>

60article-view.vue @brian_ward

61

<template> <div class="post full"> <article class="post-content"> <h1>{{ article.title }}</h1> <div>{{{ article.body }}}</div> </article> </div> </template>

@brian_wardarticle-view.vue

<script> 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) }) } } </script>

62 @brian_wardarticle-view.vue

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

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”.