Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Using VueJS in front of Drupal 8

5,101 views

Published on

Using Drupal 8 and VueJS to create a beautiful, maintainable and de-coupled application.

Published in: Engineering

Using VueJS in front of Drupal 8

  1. 1. Using Vue.jsin front of Drupal 8 @brian_ward1
  2. 2. Hello, i’m Bri(an) • Twitter: @brian_ward • Drupal: drupal.org/u/briward • Website: briward.com 2 @brian_ward
  3. 3. Yeah, well, that's just, like, your opinion, man.
  4. 4. It’s finally here(ish)! 8 It’s now easier than ever to get off the island. 5 @brian_ward
  5. 5. “But we alreadyhave a theme-layer in Drupal?” 6 @brian_wardBut we already have a theme-layer in Drupal?
  6. 6. Remember, you don’thave to make it fully headless @brian_wardBut we already have a theme-layer in Drupal? 7
  7. 7. Drupal system Complex user form Interactive feature Pages Listings Game?!
  8. 8. 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
  9. 9. So what do we get out of the box? 10 @brian_wardSo what do we get out of the box?
  10. 10. RESTful Web Services RESTful Web Services exposes entities and other resources as a RESTful web API. Required 11 @brian_wardSo what do we get out of the box?
  11. 11. Serialization Serialization 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?
  12. 12. HAL Serializes entities using Hypertext Application Language (HAL) Optional 13 @brian_wardSo what do we get out of the box?
  13. 13. RESTUI Provides a user interface for managing REST resources. Recommended 14 @brian_wardSo what do we get out of the box?
  14. 14. 3 waysto create a REST API with D8 15 @brian_ward3 ways to create a REST API with D8
  15. 15. 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
  16. 16. 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
  17. 17. Demonstration @brian_ward18 Short Using the core REST resources
  18. 18. 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
  19. 19. 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
  20. 20. @brian_ward22 Demonstration Short Using views REST export
  21. 21. 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
  22. 22. 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_wardCreating custom rest resources
  23. 23. /**
 * 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
  24. 24. public function getArticle($uuid) {
 $entity = Drupal::entityManager()->getStorage(‘node') ->loadByProperties([
 'uuid' => $uuid,
 'type' => 'article'
 ]);
 
 return reset($entity);
 } 26Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward
  25. 25. 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
  26. 26. 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
  27. 27. Pros & Cons ✓ Provides most flexibility. ✓ Transformable output. ✓ Easier to manage versions. - Requires reasonable programming knowledge. @brian_ward29Creating custom rest resources
  28. 28. 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_wardHATEOAS
  29. 29. Content negotiation To put it simply, this is the mechanism for determining what content-type the data will be returned in. 31 @brian_wardHATEOAS
  30. 30. 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.
  31. 31. Hypermedia controls 34 Provide links to related endpoints so users of your api can easily find their way around your data. @brian_wardHATEOAS
  32. 32. private function transform($entity) {
 return [
 'links' => [
 [
 'rel' => 'self',
 'uri' => '/api/v1.0/articles/'.$entity->uuid[0]->value
 ]
 ]
 ]; 
 } 35Plugin/Rest/Resource/ArticleBundleResource.php @brian_ward
  33. 33. '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
  34. 34. 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.
  35. 35. Authentication 39 @brian_ward • Basic auth • Cookie • oAuth
  36. 36. @brian_ward40 Now that we have created our API, we can play around with it on the front-end. Now we’re ready
  37. 37. 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_ward41Introducing Vue.js
  38. 38. 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.
  39. 39. View new Vue({ el: '#app' }) Each Vue instance is associated with a DOM element (el). 44 @brian_wardIntroducing Vue.js
  40. 40. 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
  41. 41. 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_ward46Introducing Vue.js
  42. 42. var MyComponent = Vue.extend({}) Components 47 @brian_ward Components are simply a convenient way to structure and organise our applications. Optional Introducing Vue.js
  43. 43. 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
  44. 44. 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
  45. 45. router.on(url, callback) Director A tiny and isomorphic URL router for JavaScript Recommended 50 @brian_wardIntroducing Vue.js
  46. 46. So where does Drupal come in? 51 @brian_wardIntroducing Vue.js
  47. 47. 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
  48. 48. {
 "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
  49. 49. <!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
  50. 50. /**
 * 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
  51. 51. /**
 * 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
  52. 52. <template>
 <component is="{{ view }}"
 class="view"
 params="{{ params }}"
 v-transition
 transition-mode="out-in">
 </component>
 </template> 58app.vue @brian_ward
  53. 53. <script>
 module.exports = {
 el: '#app',
 data: {
 view: '',
 params: {
 uuid: ''
 }
 },
 components: {
 'article-view': require('./views/article-view.vue')
 }
 }
 </script> 59app.vue @brian_ward
  54. 54. <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
  55. 55. 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
  56. 56. <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
  57. 57. 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
  58. 58. 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”.

×