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.

of

SilverStripe & Vue.js - A case study Slide 1 SilverStripe & Vue.js - A case study Slide 2 SilverStripe & Vue.js - A case study Slide 3 SilverStripe & Vue.js - A case study Slide 4 SilverStripe & Vue.js - A case study Slide 5 SilverStripe & Vue.js - A case study Slide 6 SilverStripe & Vue.js - A case study Slide 7 SilverStripe & Vue.js - A case study Slide 8 SilverStripe & Vue.js - A case study Slide 9 SilverStripe & Vue.js - A case study Slide 10 SilverStripe & Vue.js - A case study Slide 11 SilverStripe & Vue.js - A case study Slide 12 SilverStripe & Vue.js - A case study Slide 13 SilverStripe & Vue.js - A case study Slide 14 SilverStripe & Vue.js - A case study Slide 15 SilverStripe & Vue.js - A case study Slide 16 SilverStripe & Vue.js - A case study Slide 17 SilverStripe & Vue.js - A case study Slide 18 SilverStripe & Vue.js - A case study Slide 19 SilverStripe & Vue.js - A case study Slide 20 SilverStripe & Vue.js - A case study Slide 21 SilverStripe & Vue.js - A case study Slide 22 SilverStripe & Vue.js - A case study Slide 23 SilverStripe & Vue.js - A case study Slide 24 SilverStripe & Vue.js - A case study Slide 25 SilverStripe & Vue.js - A case study Slide 26 SilverStripe & Vue.js - A case study Slide 27 SilverStripe & Vue.js - A case study Slide 28 SilverStripe & Vue.js - A case study Slide 29 SilverStripe & Vue.js - A case study Slide 30 SilverStripe & Vue.js - A case study Slide 31 SilverStripe & Vue.js - A case study Slide 32 SilverStripe & Vue.js - A case study Slide 33 SilverStripe & Vue.js - A case study Slide 34 SilverStripe & Vue.js - A case study Slide 35 SilverStripe & Vue.js - A case study Slide 36 SilverStripe & Vue.js - A case study Slide 37 SilverStripe & Vue.js - A case study Slide 38 SilverStripe & Vue.js - A case study Slide 39 SilverStripe & Vue.js - A case study Slide 40 SilverStripe & Vue.js - A case study Slide 41
Upcoming SlideShare
What to Upload to SlideShare
Next

SilverStripe & Vue.js - A case study

Talk @ StripeCon EU 2018 about our experiences with SilverStripe and Vue.js in a real-world project.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to like this

SilverStripe & Vue.js - A case study

  1. 1. SilverStripe & Vue.js Payload Injection for a hybrid frontend approach StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  2. 2. SilverStripers since 2009 (v2.3.x  ) Small team: 2 1/2 Devs MVP Development for StartUps Our tools of choice: StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  3. 3. Vue.js GitHub Facts A progressive, incrementally­adoptable JavaScript framework for building UI on the web. Version 2.5.17 (228 Releases) 2.617 Commits 193 Contributors ~115k Stars ~16k Forks StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  4. 4. Trivia Developed as Rapid Prototyping Tool at Google Creative Labs Super flexible: Usage from library­ to full stack approach Easy to get started due to a flat learning curve Implements the Reactive Data­Binding Pattern Approx as fast as React when it comes to Rendering 0 prod dependencies! Can be used alongside other libraries or frameworks, e.g. to enhance legacy system (jQuery... cough...) StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  5. 5. Patterns & Features MVVM Virtual DOM Components Directives Filter Computed Properties Lifecycle Hooks Routing Flux/Data­Store implementation ("Vuex") SSR ... StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  6. 6. Vue.js Instance ...with minimal config: new Vue({ el: '#app', data: { message: 'Welcome to StripeCon EU 2018!' } }); <div id="app"> <span>{{ message }}</span> </div> StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  7. 7. Vue.js Instance MVVM implementation with reactive bindings. StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  8. 8. Anatomy A Vue.js App can be considered as composition of components with a clear top­to­bottom hierarchy. Public APIs for component­2­component interaction. StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  9. 9. (Simplified) Instance/Component Data Flow StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  10. 10. Vue.js with Superpowers: Single File Components StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  11. 11. Tooling: CLI, IDEs, Chrome Extension Great CLI for project scaffolding with hot reloading, test setup, ... PlugIns for Atom, VS Code, Sublime, IntelliJ Suite, ... Chrome extension comes in handy for development! StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  12. 12. Getting started # Install CLI npm i -g vue-cli # Lean setup vue init simple my-first-vue-app # Full Nerd-Mode setup vue init webpack my-crazy-vue-app cd my-crazy-vue-app && npm run dev StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  13. 13. So... what about SilverStripe + Vue.js? StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  14. 14. Case Study Social Media Content Platform for FIFA WSC 2018  StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  15. 15. The Team StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  16. 16. Requirements Web Interface for Content Team Form for creating content snippets of types "video", "image" and "infographic" Preview/Streaming and Download funcationality User Roles: "Content Author" and "Admin" Permission­ and Publishing­Process Extended Reporting (Download and Access Stats) Web Interface for MRLs (Media Rights Licensees) Lean UI with rich presentation of content snippets Multiple filter options (by team, category, type, ...) Search functionality International availability StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  17. 17. Early Platform Mockup StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  18. 18. Challenges Asset abstraction with v3.6.5 Clean normalized data structure vs. number of DB queries Frontend data scaffolding on initial request Fast API Hybrid Frontend Approach (MainView as scaffolded SPA, other pages statically via Template Engine) StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  19. 19. Decisions Image Delivery via Cloudinary Video Delivery via AWS S3 (Pseudo­Streaming via Byte­Range Requests) Web App Hosting via Rackspace Cloud SilverStripe Admin UI for Content Team Customized GridField Custom modules for Cloudinary and AWS S3 Uploader HybridSession Module for LoadBalancer support Vue.js SPA for MainView (only) Masonry Grid for content snippets ("Postings") Delivery of most recent data set on initial request ("Payload Injection") Subsequent requests (filtering, update polling, ...) in RESTful manner StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  20. 20. What we wanted Pseudo Hydration: A convenient way to prepare the posting payload for Vue.js on the initial main view request. (SSR/Universal App approach whould have been sexy but over engineered) StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  21. 21. Payload Injection Flow MariaDB        fetch  Interface       JSON­to­DOM Injection       "Pickup" by Vue.js StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  22. 22. Posting Model  Posting  as central  DataObject  with several relations (CLImage, S3File, ....) Raw Query to minimize the load of DB operations Desired document format: - id: number - created: string - type: string - title: string - recommended: boolean - category: string - team: string - previewImage: string Full URL - asset: string Full URL - attachment: string Full URL (optional; e.g. .psd Files) StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  23. 23.  Posting::fetch()  /** * @param array $options * - limit: number, default: 40 * - offset: number, default: 0 * - type: string (see db enum field "Type") * - created: string (date) * - recommended: boolean * - category: string * - team: string * - term: string For free text search (>= 3 chars) * - sortOrder: string (ASC|DESC), default: DESC * - minID: int * * @return array Posting Documents * @throws FetchException */ public static function fetch(array $options = []): array; StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  24. 24. Injecting the payload public function index(SS_HttpRequest $req) { // Get options compliant with interface $opts = $this->extractFetchOptions($req); // Staging the posting payload for DOM injection PayloadInjector::stage([ 'postings' => Posting::fetch($opts); ]); return $this->renderWith('MainView'); } StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  25. 25.  PayloadInjector ... ...collects array data through out request processing. ...normalizes data and converts it to JSON. ...hands it to the renderable data. Basically it's a convenience wrapper for: // Consider $data is everything you have "staged" so far Controller::curr()->customize([ 'Payload' => Convert::array2json($payload); ]); StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  26. 26. Making payload available for Vue.js <!-- MainView.ss --> <% if $Payload %> <script>window.payload = $Payload;</script> <% end_if %> Note:  PayloadInjector  will handle this in v2 StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  27. 27. Making payload available for Vue.js // main-view.js import Vue from 'vue'; // Initial data for Vue instance let data = { showPreview: false }; // Merging injected payload if (typeof payload !== undefined) Object.assign(data, payload); new Vue( el: '#app', data // <--- prepared payload is available through instance data prop ); StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  28. 28. Displaying the payload <!-- MainView.ss --> <div id="#app"> <main class="grid"> <div v-for="posting in postings" v-bind:key="posting.id" class="posting-card"> <h2>{{ posting.title }}</h2> ... </div> </main> </div> StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  29. 29. Subsequent Requests 1. SilverStripe Controller Logic (Action­Mapping, Validation, ...) 2.  Posting::fetch($opts)  with options from Request 3. Delivering Posting Documents as JSON 4. Updating the Vue.js data property and let reactive bindings to it's magic  StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  30. 30. Subsequent Requests // main-view.js new Vue({ el: '#app', data, methods: { fetch(filterOptions) { axios.get('http://localhost:8080/posting', { params: { ...filterOptions } }).then(res => { const { payload } = res.data; // This mutates the postings prop of "data" // and triggers the attached reactive bindings this.postings = payload.postings; }); } } }); StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  31. 31. Validating the HTTP method for action mapping private static $url_handlers = [ 'posting/$id' => [ 'GET' => 'fetchPostings', 'POST' => 'createPosting' ] ]; ...powered by a Trait overloading RequestHandler's protected  findAction()  method. StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  32. 32. Working on v2 StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  33. 33. Hybrid Rendering Pattern proposed at GoogleIO 2018 Check if a crawler is requesting and deliver optimized resources The idea is to use the staged data wrapped via  ArrayData  and  ArrayList  and auto­ use templates with  _static.ss  suffix. StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  34. 34. Hybrid Rendering: Flow StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  35. 35. CQRS Utils Command Query Responsibility Segregation Different models/flows for creating and reading data The idea is to have a conventional relational DB as "Write Database" and another store for prepared documents (e.g. Redis, MongoDB or Elastic) as "Read Database" Step towards the Headless CMS world StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  36. 36. CQRS Utils: Flow StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  37. 37. CQRS Utils: Config # config.yml Posting: extensions: - CQRSExtension('ID', [ 'store' => 'redis', 'db' => 2 ]) // Posting.php; content of $read_payload is considered the "Payload Manifest" private static $read_payload = [ 'ID', 'Title', 'Category' => 'getCategoryLabel', 'Tags' => [ 'required' => false, 'mapping' => 'getTagList' ] ]; StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  38. 38. CQRS Utils:  IPayloadStore  interface IPayloadStore { public function read(string $key): array; public function write(string $key, array $payload); public function delete(string $key); public function info(string $option = null): array; public function getName(): string; } StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  39. 39. Resources  Official Docs: https://vuejs.org/v2/guide Weekly Podcast: https://news.vuejs.org Tutorial: https://laracasts.com/series/learn­vue­2­step­by­step State of Vue Report: https://www.monterail.com/state­of­vuejs­report Cheat Sheet: http://www.vuemastery.com StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  40. 40. https://akryum.github.io/vue­apollo/ StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51
  41. 41. Thanks!    StripeCon EU 18 :: Julian Scheuchenzuber <js@lvl51.de> :: Level51

Talk @ StripeCon EU 2018 about our experiences with SilverStripe and Vue.js in a real-world project.

Views

Total views

235

On Slideshare

0

From embeds

0

Number of embeds

0

Actions

Downloads

0

Shares

0

Comments

0

Likes

0

×