load_exclusions(); add_filter( 'script_loader_tag', array( $this, 'add_defer_attribute' ), 10, 2 ); } /** * Load exclusion list from options. */ private function load_exclusions() { // Always exclude jQuery core. $this->exclusions = array( 'jquery-core', 'jquery' ); $custom_exclusions = get_option( 'asmith_so_defer_js_exclusions', '' ); if ( ! empty( $custom_exclusions ) ) { $custom = array_map( 'trim', explode( ',', $custom_exclusions ) ); $custom = array_filter( $custom ); $this->exclusions = array_merge( $this->exclusions, $custom ); } } /** * Add defer attribute to script tags. * * @param string $tag The script tag HTML. * @param string $handle The script handle. * @return string */ public function add_defer_attribute( $tag, $handle ) { // Don't defer in admin. if ( is_admin() ) { return $tag; } // Skip excluded handles. if ( in_array( $handle, $this->exclusions, true ) ) { return $tag; } // Skip if already has defer or async. if ( false !== strpos( $tag, ' defer' ) || false !== strpos( $tag, ' async' ) ) { return $tag; } // Skip inline scripts (no src attribute). if ( false === strpos( $tag, ' src=' ) ) { return $tag; } // Add defer attribute. $tag = str_replace( ' src=', ' defer src=', $tag ); return $tag; } }