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

Using VueJS in front of Drupal 8

Brian Ward
November 10, 2015

Using VueJS in front of Drupal 8

Learn how to create beautiful, maintainable and de-coupled applications with Drupal 8.

Source code: https://github.com/briward/examples/tree/master/using-vuejs-in-front-of-drupal-8

More: http://briward.com

Brian Ward

November 10, 2015
Tweet

Other Decks in Programming

Transcript

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

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

    But we already have a theme-layer in Drupal? 7
  3. 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
  4. So what do we get out of the box? 10

    @brian_ward So what do we get out of the box?
  5. 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?
  6. 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?
  7. RESTUI Provides a user interface for managing REST resources. Recommended

    14 @brian_ward So what do we get out of the box?
  8. 3 ways to create a REST API with D8 15

    @brian_ward 3 ways to create a REST API with D8
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. /**
 * 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
  15. 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
  16. 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
  17. 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
  18. Pros & Cons ✓ Provides most flexibility. ✓ Transformable output.

    ✓ Easier to manage versions. - Requires reasonable programming knowledge. @brian_ward 29 Creating custom rest resources
  19. 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
  20. 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
  21. 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.
  22. Hypermedia controls 34 Provide links to related endpoints so users

    of your api can easily find their way around your data. @brian_ward HATEOAS
  23. 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
  24. '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
  25. 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.
  26. @brian_ward 40 Now that we have created our API, we

    can play around with it on the front-end. Now we’re ready
  27. 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
  28. 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.
  29. View new Vue({ el: '#app' }) Each Vue instance is

    associated with a DOM element (el). 44 @brian_ward Introducing Vue.js
  30. 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
  31. 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
  32. var MyComponent = Vue.extend({}) Components 47 @brian_ward Components are simply

    a convenient way to structure and organise our applications. Optional Introducing Vue.js
  33. 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
  34. 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
  35. router.on(url, callback) Director A tiny and isomorphic URL router for

    JavaScript Recommended 50 @brian_ward Introducing Vue.js
  36. 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
  37. {
 "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
  38. <!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> 55 index.html @brian_ward
  39. /**
 * 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
  40. /**
 * 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
  41. <template>
 <component is="{{ view }}"
 class="view"
 params="{{ params }}"
 v-transition


    transition-mode="out-in">
 </component>
 </template> 58 app.vue @brian_ward
  42. <script>
 module.exports = {
 el: '#app',
 data: {
 view: '',


    params: {
 uuid: ''
 }
 },
 components: {
 'article-view': require('./views/article-view.vue')
 }
 }
 </script> 59 app.vue @brian_ward
  43. 61 <template>
 <div class="post full">
 <article class="post-content">
 <h1>{{ article.title }}</h1>


    <div>{{{ article.body }}}</div>
 </article>
 </div>
 </template> @brian_ward article-view.vue
  44. <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_ward article-view.vue
  45. 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
  46. 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”.