Upload
taylor-lovett
View
927
Download
3
Embed Size (px)
Citation preview
Who Am I?
• My name is Taylor Lovett
• Director of Web Engineering at 10up
• WordPress plugin creator and core contributor
• Open source community member
@tlovett12
https://10up.github.io/Engineering-Best-Practices/
Redis as a Persistent Object Cache
• WP lets you drop in a custom object cache.
• Redis lets you store things in memory for fast read/writes
• Redis offers built in failover features that make it easier to scale than Memcached
https://wordpress.org/plugins/wp-redis/
Page Caching
• Page caching is the act of caching entire rendered HTML pages.
• Pages can be stored in the object cache avoiding database queries entirely
https://wordpress.org/plugins/batcache/
Fragment Caching
• All output involving a database read on the front end should be fragment cached aside from the main WP query.
• For example, generated HTML from a feature post carousel should be cached since it uses a WP_Query
Remote Calls
• Remote blocking calls can be a huge performance bottleneck
• Cache remote calls as long as possible
• Utilize non-blocking remote requests wherever possible
Prime Cache Asynchronously
• Don’t make the user wait for a cache to be primed.
• Re-prime after invalidation
• Cleverly prime cached data asynchronously (cron, non-blocking AJAX, etc.)
https://github.com/10up/Async-Transients
admin-ajax.php
• Admin-ajax.php is for admin use only. It is not cached as aggressively as the front end. Page caching will not work.
Off the Shelf Caching Plugins
• Can be difficult to install and even more difficult to remove.
• Created for the general public and often bloated with features.
• Keep it simple.
Avoid Front End Writes
• Database writes are slow
• Avoid race conditions
• Page caching makes them unreliable.
• If you really need to write data on the front end, use AJAX.
Understand WP_Query Parameters
• 'no_found_rows' => true: Tells WordPress not to pass SQL_CALC_FOUND_ROWS to the database query.
• 'update_post_meta_cache' => false: useful when post meta will not be utilized.
• 'update_post_term_cache' => false: useful when taxonomy terms will not be utilized.
• 'fields' => 'ids': useful when only the post IDs are needed (less typical). Avoids lots of extra preparation.
Understand WP Query Parameters
• ‘posts_per_page’ => ‘…’: Sets the query limit to something other than -1
• ‘post__not_in’: Tells MySQL to run a NOT IN query which is inherently slow. Try to avoid.
Understand WP Query Parameters
new WP_Query( array( 'no_found_rows' => true, 'fields' => 'ids', 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'posts_per_page' => 100, ) );
Autoloading Options
• update_option() and add_option() take a 3rd parameter $autoload.
• If you don’t need an option on every request, specify false for $autoload.
Elasticsearch/ElasticPress
• If you receive a lot of search traffic, use Elasticsearch and ElasticPress.
• Search queries can be very taxing on MySQL
https://github.com/10up/ElasticPress
Use a CDN
• CDN’s enable you to serve static assets from servers closer to your visitors while reducing load on your web server(s).
• CDN recommendation is very unique to each project.
Reduce the Number and Size of HTTP Requests
• Minify JS and CSS files
• Concatenate JS and CSS files
• Optimize images
• HTTP 2?
Maintainable Code Improves Stability
• Easily maintainable and extendible code bases are less susceptible to bugs.
• Bugs in maintainable code are solved quicker
• New features are more easily created in maintainable code.
• Happy engineers are more productive (often overlooked).
Modern PHP Design Patterns
• WordPress core is backwards compatible with PHP 5.2.4.
• Your project does not need to be constrained by incredibly outdated software
• Namespaces, traits, composer, etc.
Don’t Obsess Over MVC PHP
• MVC (model, view, and controller) is a great pattern in many situations.
• WordPress is inherently not object oriented. We find that forcing MVC with tools like Twig ultimately leads to more confusing code that is harder to maintain.
Modern JS Design Patterns
• CommonJS
• ES6-7
• Write modular code with tools like Webpack and Browserify
• React
Feature Plugins
• Group distinct pieces of functionality into plugins as much as possible.
• This separation simplifies deployments and enables you to reuse functionality on other projects.
• Opt-in to functionality through usage of hooks
Documentation• Properly documented code is more quickly fixed and
iterated upon
• Make documentation a part of your code review process
• PHP Documentation Standards: https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/php/
• JS Documentation Standards: https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/javascript/
Wrapping Wrappers
• WordPress has a very rich, easy to use API with ways to create posts, send HTTP requests, create metaboxes, etc.
• Creating wrappers around these core APIs more often than not just results in a layer of confusing code and another library to memorize.
Write Tests
• PHPUnit for PHP
• Core unit testing framework and WP Mock - https://github.com/10up/wp_mock
• Mocha for JavaScript
• Tests improve quality and stability through identification of issues. Decrease regression
Clean Input
if ( ! empty( $_POST['option'] ) ) { update_post_meta( $post_id, 'option_key', true ); } else { delete_post_meta( $post_id, 'option_key' ); }
update_post_meta( $post_id, 'key_name', sanitize_text_field( $_POST['description'] ) );
Secure Output
• Escape data that is printed to the screen
• Escape data as late as possible
• Check out the esc_* functions in the codex.
https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data
Secure Output
<section> <?php echo esc_html( get_post_meta( get_the_ID(), 'key_name', true ) ); ?> </section>
<section class="<?php echo esc_attr( get_post_meta( get_the_ID(), 'key_name', true ) ); ?>"> ... </section>
innerHTML and jQuery Selectors
document.getElementsByClassName( 'class-name' )[0].innerText = textString;
var node = document.createElement( 'div' ); node.innerText = textString; document.getElementsByClassName( 'class-name' )[0].appendChild( node );
jQuery( '.class-name-' + parseInt( index ) );
Nonces
• Ensure intent of important actions (database modifications) by associating them with a nonce
• wp_create_nonce(), wp_verify_nonce(), wp_nonce_field()
Nonces
<form> <?php wp_nonce_field( 'prefix-form-action', 'nonce_field' ); ?> ... </form>
if ( empty( $_POST['nonce_field'] || wp_verify_nonce( $_POST['nonce_field'], 'prefix-form-action' ) { return false; }
Require Strong Passwords
• Weak passwords are one of the most common ways attackers exploit websites.
• Require your users create strong passwords. There are a few great plugins that do this automatically.
Review Every Line of Code
Over 40,000 community plugins• Plugins reviewed before submission
• Plugin revisions not reviewed
• Review guidelines not geared for high traffic
Review Every Line of Code
Thousands of community themes• More stringent review guidelines than
plugins
• Review guidelines not geared for high traffic
• Performance not measured
Understand Your Librarys
• jQuery, Underscores, etc. are helpful tools but should not be used blindly. There is no substitute for a solid understand of JavaScript.
• Encouraging engineers to understand the libraries they are using will improve overall code quality and decrease bugs.
Workflows• Keeping track of code history with version
control is critical.
• Mandate workflow at the start of project to keep everyone on the same page.
• Use descriptive commit messages
• Gitflow: http://nvie.com/posts/a-successful-git-branching-model/
Internal Code Reviews
• Code reviews help ensure performance, security, maintainability, and scalability
• Engineers improve skills by reviewing and receiving reviews.
Q U E S T I O N S ?
@ T L O V E T T 1 2TAY L O R . L O V E T T @ 1 0 U P. C O MTAY L O R L O V E T T. C O M