Successfully reported this slideshow.

Stop Repeating Yourself: Modularized WordPress Development

0

Share

Upcoming SlideShare
Grav CMS
Grav CMS
Loading in …3
×
1 of 46
1 of 46

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Stop Repeating Yourself: Modularized WordPress Development

  1. 1. Stop Repeating Yourself MODULARIZED WORDPRESS DEVELOPMENT #DPA5
  2. 2. Who We Are JIM BARNES Web Applications Programmer 4 years at UCF https://github.com/jmbarne3 JO DICKSON Web Applications Programmer 4 years at UCF https://github.com/cjg89 HEW2016 — #DPA5 SLIDE 2
  3. 3. UCF Web Communications • Part of UCF Marketing • Team of 5 (4 developers, 1 director) • Responsible for development of top-level websites and applications for the university • Develop and maintain sites for various departments, organizations, and colleges HEW2016 — #DPA5 SLIDE 3
  4. 4. HEW2016 — #DPA5 SLIDE 4
  5. 5. Current Theme Development • Most functionality provided for the site is defined in the theme • New themes are based on a generic theme with helper functions for faster development • Contains a base set of PHP functions, CSS and JavaScript that is reproduced with each new theme • Minimal reliance on plugins • Build sites, not themes HEW2016 — #DPA5 SLIDE 5
  6. 6. Current Theme Tools • Abstract classes for custom post types, custom taxonomies and shortcodes • Support for adding custom meta fields to custom post types • Support for quickly adding common configuration items • Useful UI features, like a shortcode WYSIWYG GUI HEW2016 — #DPA5 SLIDE 6
  7. 7. Custom Post Types What You Need • Title • Singular Name • Plural Name • Standard Options • Fields What You Get • Registration Logic • Name Generation • Automatic Shortcode Registration • Metaboxes and Fields HEW2016 — #DPA5 SLIDE 7
  8. 8. ! News " Events # People $ Carousel % Theme Code ! News # People ! News " Events # People % Theme Code % Theme Code % Theme Code % Theme Code # People $ Carousel " Events $ Carousel HEW2016 — #DPA5 SLIDE 8
  9. 9. & Simplified Deployment ' Maximum Customization % Centralization of Code Base ( Reduction in client resources (CSS/JS) ) Little to no plugin bloat Advantages HEW2016 — #DPA5 SLIDE 9
  10. 10. Disadvantages * We Repeat Ourselves + Duplication of Features and Styles , Decentralized Bug Fixes  Data loss on theme change . Not WordPress best practices HEW2016 — #DPA5 SLIDE 10
  11. 11. D.R.Y. Don’t Repeat Yourself HEW2016 — #DPA5 SLIDE 11
  12. 12. WordPress Best Practices Themes • Provide look and feel • Page and post templates • Stylesheet • JavaScript necessary for look and feel Plugins • Provide functionality • Custom Post Types and Taxonomies • Shortcodes • Widgets • APIs HEW2016 — #DPA5 SLIDE 12
  13. 13. Challenges with the “WordPress Way” • Dependency management • Heavy per-site customizations, in bulk • Plugin bloat • Minified asset delivery HEW2016 — #DPA5 SLIDE 13
  14. 14. HEW2016 — #DPA5 SLIDE 14 ( REDUCE Time to Distribute Bug Fixes
  15. 15. HEW2016 — #DPA5 SLIDE 15 / CONSOLIDATE Similar Features and Logic Across Our Themes
  16. 16. HEW2016 — #DPA5 SLIDE 16 0 MODERNIZE Our Codebase
  17. 17. HEW2016 — #DPA5 SLIDE 17 1 STANDARDIZE Plugin Dependency Management For Themes and Other Plugins
  18. 18. HEW2016 — #DPA5 SLIDE 18 2 DISTRIBUTE Resources for Developers and Non-Developers Across Campus
  19. 19. HEW2016 — #DPA5 SLIDE 19 3 PROMOTE Best Practices
  20. 20. How do we stop repeating ourselves? HEW2016 — #DPA5 SLIDE 20
  21. 21. ! News " Events # People $ Carousel % Theme Code ! News # People ! News " Events # People % Theme Code % Theme Code % Theme Code % Theme Code # People $ Carousel " Events $ Carousel HEW2016 — #DPA5 SLIDE 21
  22. 22. ! News " Events # People $ Carousel % Theme Code % Theme Code % Theme Code % Theme Code % Theme Code HEW2016 — #DPA5 SLIDE 22
  23. 23. Separate theme functionality from plugin functionality HEW2016 — #DPA5 SLIDE 23
  24. 24. Theme, or Plugin? • Theme: look and feel • Plugins: content and functionality If the code were to be placed in a theme, and the theme was then switched out, would you miss its functionality? • Yes: plugin code • No: theme code HEW2016 — #DPA5 SLIDE 24
  25. 25. Separation of Concerns (Content vs. Presentation) Theme • Layout • Page and Post Templates • Menu Locations • Sidebars • Presentation-related functions • Styles • Theme specific styles • Overrides for plugin provided markup, specific to theme • Presentation Configuration • Theme mods Plugins • Functionality • Widgets • Shortcodes • Data-related functions • Data Definition • Custom Post Types • Taxonomies • Meta Fields • API Endpoints • Data Configuration • Options HEW2016 — #DPA5 SLIDE 25
  26. 26. Plugin Development Reusability & Portability • Default Styles and Templates • Ability to turn off default CSS and JS when more customization is desired • Customization of look and feel through theme CSS • Default functionality without programming Extensibility • Actions and Filters to allow overriding of default templates • Sass artifacts available in repository for easy overrides • Well documented CSS classes for theme specific overrides HEW2016 — #DPA5 SLIDE 26
  27. 27. Example Plugins UCF News UCF Events HEW2016 — #DPA5 SLIDE 27
  28. 28. Example Plugins HEW2016 — #DPA5 SLIDE 28
  29. 29. Example Plugins HEW2016 — #DPA5 SLIDE 29
  30. 30. Customizing Example – UCF News in a “Masonry” stacked grid layout <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> HEW2016 — #DPA5 SLIDE 30 Displays news content (prints markup) Registers the new layout
  31. 31. <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> Customizing Example – UCF News in a “Masonry” stacked grid layout HEW2016 — #DPA5 SLIDE 31 <?php function news_masonry_template_before( $items, $title, $display_type ) { echo '<div class="news-masonry">'; } ?>
  32. 32. <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> Customizing Example – UCF News in a “Masonry” stacked grid layout HEW2016 — #DPA5 SLIDE 32 <?php function news_masonry_template_title( $items, $title, $display_type ) { echo '<h2>' . $title . '</h2>'; } ?>
  33. 33. <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> Customizing Example – UCF News in a “Masonry” stacked grid layout HEW2016 — #DPA5 SLIDE 33 <?php function news_masonry_template( $items, $title, $display_type ) { ob_start(); foreach ( $items as $item ) { ?> <div class="news-item"> <?php echo $item->title; ?> <?php // other item content… ?> </div> <?php } return ob_get_clean(); } ?>
  34. 34. <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> Customizing Example – UCF News in a “Masonry” stacked grid layout HEW2016 — #DPA5 SLIDE 34 <?php function news_masonry_template_after( $items, $title, $display_type ) { echo '</div>'; } ?>
  35. 35. <?php add_action( 'ucf_news_display_masonry_before', 'news_masonry_template_before', 10, 3 ); add_action( 'ucf_news_display_masonry_title', 'news_masonry_template_title', 10, 3 ); add_action( 'ucf_news_display_masonry', 'news_masonry_template', 10, 3 ); add_action( 'ucf_news_display_masonry_after', 'news_masonry_template_after', 10, 3 ); add_action( 'ucf_news_get_layouts', 'add_masonry_layout', 10, 1 ); ?> Customizing Example – UCF News in a “Masonry” stacked grid layout HEW2016 — #DPA5 SLIDE 35 <?php function add_masonry_layout( $layouts ) { $layouts = array_merge( $layouts, array( 'masonry' => 'Masonry Layout' ) ); return $layouts; } ?>
  36. 36. Plugins We’re Building WordPress Features • Post types and taxonomies • Shortcode WYSIWYG interface • Autocomplete search field for lists of posts by type • Plugin for general utility functions Plugins for Services • UCF search service • Weather data • Map data (map.ucf.edu) • UCF Header (JavaScript brand widget) HEW2016 — #DPA5 SLIDE 36
  37. 37. Plugins We’re Not Building • Meta box and meta field management (Advanced Custom Fields/ACF) • SEO optimization (WordPress SEO/Yoast) • Form management (GravityForms) • And a few others… HEW2016 — #DPA5 SLIDE 37
  38. 38. Modularization of Plugin Functionality Example – Separation of post type and meta field definitions # Person custom post type 4 Advanced Custom Fields (or other meta field manager) % Theme Code • Email field • Phone number field • Address field % Theme Code HEW2016 — #DPA5 SLIDE 38
  39. 39. Utilize a plugin + theme dependency management system HEW2016 — #DPA5 SLIDE 39
  40. 40. Dependency Management • Avoid unnecessary dependencies • Simple plugin detection • SemVer plugin detection – In Development HEW2016 — #DPA5 SLIDE 40
  41. 41. Theme Development • Focused on: • Layout (Templates) • Styling • Content • Dependency Management • Fail gracefully • Handle dependencies through deployment process HEW2016 — #DPA5 SLIDE 41
  42. 42. Yeoman Generators • Allow for quick customization of look and feel • Pick and Choose: • Page templates • Adjust SASS Variables • Create documentation and labels • Use WP CLI to create site, install theme enable plugins HEW2016 — #DPA5 SLIDE 42
  43. 43. Looking Forward Advantages • More effective maintenance and upgrade cycles • More rapid development of new themes • Distributed functionality and standard styles • Increased consistency across sites Challenges • Up front investment of time • Additional responsibilities for documenting and testing • Change in culture – being product driven instead of site driven • Balancing these transitions with the need to get production work done HEW2016 — #DPA5 SLIDE 43
  44. 44. Questions? HEW2016 — #DPA5 SLIDE 44
  45. 45. In Conclusion • D.R.Y. WordPress sites require a different approach to both code and site development as a whole • YMMV! • Code will be available on Github • https://github.com/UCF HEW2016 — #DPA5 SLIDE 45
  46. 46. Resources • WordPress best practices • https://codex.wordpress.org/Theme_Develo pment#Functions_File • https://developer.wordpress.com/themes/ • Dependency Management solutions • https://roots.io/using-composer-with- wordpress/ • http://tgmpluginactivation.com • WordPress hooks, actions and filters • https://codex.wordpress.org/Plugin_API • Separation of Concerns (WP StackExchange) • http://wordpress.stackexchange.com/q/73031 • Theme or Plugin? (WP StackExchange) • http://wordpress.stackexchange.com/a/73038 • Meta field management plugins • https://www.advancedcustomfields.com/ • https://wordpress.org/plugins/cmb2/ • UCF on Github • https://github.com/UCF HEW2016 — #DPA5 SLIDE 46

Editor's Notes

  • Jim
    Welcome to Stop Repeating Yourself – Modularized WordPress Development
    Today we’re going to be talking about our strategies for large-scale WordPress site development, why we’re changing those strategies, and some tools and techniques we’re using to transition to more modularized development.
    #DPA5
  • Both
    Introduce ourselves briefly as web developers for UCF Web Communications (Webcom)
    Maybe note our level of experience with WordPress in general, or other experience that is relevant to the presentation?
  • Jo
    UCF Web Communications, or Webcom, consists of 4 total developers and 1 director
    As part of Webcom, we’re responsible for a large number of top-level websites and applications, as well as many sites for other departments, organizations, and colleges within the university
    Most of these sites run on WordPress
  • Jo
    Webcom currently develops and maintains 36 unique WordPress sites
    Just about all of them are built off of the same core set of code, with various tweaks and customizations
    Several sites from other departments are also built off of our code
  • Jim
    So, what does our code look like?
    According to WordPress best practices, we’re doing it the “wrong way”.

    Back in 2010-2011 when Webcom first started developing custom WordPress themes, a “Generic Theme” was established, which contains a base set of functions, CSS and Javascript
    Theme includes classes for post type and taxonomy registration, as well as helper classes and methods for registering meta fields and meta boxes
    New WordPress themes were originally built by cloning the generic theme repo. We’ve since created a Yeoman generator that simplifies this process.
    Over time, we’ve also incorporated pre-processing tools like Gulp and Sass into our themes.
    With the exception of the handful of plugins we typically use, all site functionality is contained within themes. The theme is considered the backbone of any given site.
  • Jim

    OOP approach to building common features
    Rapid creation of custom meta fields
    Rapid configuration changes
    Useful UI features for users
  • Jim

    Run through the before/after of creating a custom post type.
  • Jim

    Under our current theme development process, themes are treated like individual sites: all layout, styles and functionality and wrapped up in a single package. This can cause a lot of repetitive code across themes, especially if small customizations are needed to certain functional parts of the themes.

    Let’s say we have five websites we need to build and support. The primary website is going to use a (transition) news feed, (transition) events feed, (transition) people custom post type, (transition) carousel, along with (transition) our layout and styles specific to the theme. All of this would be written within the theme code (transition).

    This process would be repeated along the other 4 sites we need to support. (transition) Since each theme has some particular needs for the various functional groups, each code base will be slightly different and the original code base will gradually go out of sync.
  • Jim
    - While our current development process has certain benefits, it comes with several drawbacks.
    Being able to centralize (almost) all site logic and styles within a single repository makes it very easy to deploy site changes, and allows us to heavily customize existing functions and styles without modifying any other sites or code
    However, with the growth of our department and the number of sites we maintain, this development strategy has become a double-edged sword:
    If any piece of logic cloned off of our generic theme breaks, it must be fixed individually in every theme that contains that code.
    It also makes it very time-consuming to update any features that are repeated across multiple themes.
    Our themes are also not good examples of WordPress best practices. Ideally, we’d like to be a resource for well-written WordPress code for other departments, and for the open-source community in general.
  • Jim
    Talk about DRY as it relates to single projects, functions/classes
    Will I use this function more than once?
    Is part of my function repeated in other functions?
    Is the code more understandable split into separate parts?
    Expand the concept of DRY beyond a single project to talk about its implementation across projects
  • Jim
  • Jim
    Regardless, doing things the “WordPress Way” is not as easy as it seems.

    One of the biggest pain points with developing complex sites for WordPress is its lack of integrated dependency management. If you were building, say, a Node project, you’d be able to define a set of dependencies for that project using a packages.json file, and simply run a `npm install` command to download those dependencies. WordPress doesn’t have any built-in way of defining a set of required plugins for a single site—they must all be installed manually. This makes it very difficult to automate deployment of site updates when themes and plugins are separated.

    There are a few third-party solutions to the issue, but none of them quite work for us.

    Composer – has some unideal setbacks, such as requiring all packages to have a composer.json file—this forces you to depend on third-party mirrors of WordPress itself and the public plugin directory (WordPress Packagist) so that dependencies have a composer.json file. Doesn’t account for premium plugins or public plugins not in the official WordPress directory which may not offer Composer support.
    TGM Plugin Activation Library – lack of official MultiSite support (at time of writing)

    Another problem with separating functionality from themes is the necessity for heavy per-site customizations. We are frequently asked to build sites that vary visually and functionally quite a bit from previous projects—we don’t have the luxury of using a single template across most of the sites we build. When you start separating theme logic and plugin logic, you lose the option of “just throwing stuff in your functions.php file”.

    Which leads to the concept of plugin bloat—generally you want to avoid having tons of plugins activated, mostly for performance reasons and to reduce the number of potential sources for bugs. With modularizing out functionality into plugins, it’s very easy to go overboard with the number of required plugins.

    And, finally, because plugins are expected to work “out of the box”, they generally have to include and load their own front-end stylesheets and JavaScript. Ideally, we want to be able to condense most, if not all, of the front-end assets needed for a site into single minified files to reduce HTTP requests.
  • Jim

    Reduce the amount of time it takes to distribute bug fixes
  • Jim

    Consolidate features and logic across sites throughout the university
  • Jim

    Modernize our code base bringing it more inline with current development trends, making it easier to modernize further in the future
  • Jim

    Create a standard plugin dependency method for ensuring sites work as intended when pushed into production
  • Jim

    Distribute our code across campus to developers and non-developers alike.
    Plug and play AND Customizable
  • Jim

    Promote best practices across campus
  • Jim
  • Jim

    Ideally, we want to move away from this…
  • Jim

    And move toward a process like this: where discreet functional code is written into plugins (transition), creating a foundation on which we can build our themes. The specific layout and style still needs to be present (transition).

    However, the individual differences between themes would be reduced to in our theme code by using action hooks and css overrides (transition) reducing the amount of overall code that needs to be maintained between sites (transition).
  • Jo

    Step one: If we want to shift to using plugins as the foundation for site functionality, we need to figure out how to separate theme functionality from plugin functionality for projects moving forward.
  • Jo

    As Jim mentioned earlier, best practices state that themes should provide look and feel, and plugins should provide functionality.

    But it can be challenging to figure out exactly what goes where—especially when WordPress is very forgiving and allows you to put pretty much any plugin-related code in your theme. There’s also a lot of conflicting information online regarding putting code in plugins vs your functions.php file.

    A good way of deciding what functionality goes where is to ask yourself, “if I put this code in a theme, would I miss the functionality after switching themes?”
  • Jo

    This is our hard line between the separation of content vs presentation for our projects moving forward.

    We’ve grouped various common features into more general categories, and this isn’t a total comprehensive list of features, but it covers our most commonly-used WordPress features and functionality.


    This separation of concerns leaves us with a lot of new plugins to develop.
  • Jo

    Obviously, we want these new plugins to work out-of-the-box for non-programmers, but we still need to be able to add theme-specific overrides in an elegant, modular way.

    So, for reusability and portability, we decided that these new plugins that we’re developing would include some default set of styles and templates, but that those default styles could be disabled when more customization is desired via the theme.

    For extensibility, these plugins would heavily utilize actions and filters to allow overriding of default templates. They would also include well-documented Sass partials, which could easily be imported into a theme’s Sass files during development.
  • Jo

    We’re still in the process of developing the feature plugins we want to transition to using, but we do have a few good examples to show off.

    Our UCF News and Events plugins provide shortcodes, widgets, and base functions for displaying content from our news site and university-wide events system.

    The screenshots here show what both plugins would look like out-of-the-box with default styles and markup applied.
  • Jo

    CSS provided by the plugins can be disabled for theme developers that want to include styles for the plugin content within their themes.

    You can see here where we’ve provided an option within the WordPress admin to toggle styles on or off.
  • Jo

    A default layout and styles are provided in each plugin, but new layouts are easy to add via actions and filters.
  • Jo

    To show off how you can use actions and filters, here’s an example that shows how you can extend the UCF News plugin. You can see how we’ve added actions for defining parts of a “layout” (and, by “layout”, we mean the combination of markup and styles for a chunk of content). This code creates a new “layout” for news content called “masonry”, which would probably display news in a stacked grid layout. The masonry layout would be selectable as an option for the news widget and as a possible attribute value for the news shortcode.

    This piece of code defines 5 new actions; the first four are run whenever a particular layout called “masonry” is being used to display news content. The functions passed to those actions, the “news_masonry_template_” functions, would print the markup before the news items, print the news items themselves, and print the markup after the news items, respectively. Each action is generated dynamically by the plugin, based on registered layout IDs.

    The final line of code registers the “masonry” layout in the plugin’s available list of layouts. The “add_masonry_layout” function would push a layout ID and name to an array used by the plugin and return it.
  • Jo

    I mentioned earlier that we have a lot of new plugins to build--in addition to the news and events plugins, we’re planning on building a suite of plugins for stuff that we tend to use frequently in our themes.

    These range from basic WordPress content definitions, like post types and taxonomies, to plugins that replace some of the theme tools we mentioned earlier, like our shortcode GUI, to plugins that integrate with other services we manage, like our search service, weather feed, and campus map.

    By building out plugins like this, particularly for existing services, we gain the added benefit of promoting our centralized data sources, and reducing data duplication across sites.
  • Jo

    But we don’t plan on trying to build *everything* ourselves.

    It’s not in our best interest to re-invent the wheel, especially when other developers have created tools that accomplish much of what we need already.

    We are, however, pretty strict with the third-party plugins we install. Most undergo code reviews and testing by our team before being activated in our production environments.

    Doing this helps us stay ahead of performance issues and potential bugs, and prevents us from wildly activating plugins and ending up with plugin bloat.
  • Jo

    On the last slide, we mentioned using the Advanced Custom Fields plugin. In terms of modularization, ACF is pretty powerful—by defining meta box and meta fields separately from the custom post type plugins we’re building, our custom post types become much more flexible and reusable across sites.

    When you’re creating a new custom post type, it’s easy to think of that post type as the combination of the post type itself and whatever custom meta boxes and fields you assign to it. Generally, one of the biggest reasons for creating a new post type is to be able to save some extra data to those posts that built-in post types aren’t capable of doing.

    However, by using a plugin such as ACF to define meta fields for a post type separately, post type definitions become more reusable and scalable for a larger number of sites.

    For example, one site could utilize a “Person” post type with meta fields for an email address and phone number, while another site could use the same “Person” post type but with a field for the person’s address instead. Both sites would use the same plugins but with different ACF configurations.

    Again, the goal is to find the right balance between reusability and practicality. We’re looking to split out re-usable chunks of logic into plugins where we can, without ending up with too many moving dependencies and parts. *segue to Jim*
  • Jim
  • Jim
  • Jim
  • Jim
  • Jim
  • Both
  • Jo

    In conclusion, developing sites for WordPress in a DRY way requires a different approach to both code and the way you and your team approach site development.

    Ultimately, despite some of the shortcomings of the WordPress ecosystem, it is possible to modularize your code and stop repeating yourself.

    But your mileage may vary! There may be other techniques that work better for you and your team. We hope our experience with transitioning our codebase can provide some helpful insight into how your team approaches WordPress development.

    If you’re interested in the work we’ve done so far, it’ll be available publicly on Github.

    Thank you!
  • Both
  • ×