├── VERSION ├── cache └── .gitignore ├── languages └── defer-wordpress.pot ├── public ├── lib │ └── .gitignore ├── css │ └── defer-wordpress-public.css ├── partials │ └── defer-wordpress-public-display.php ├── index.php ├── js │ └── defer-wordpress-public.js └── class-defer-wordpress-public.php ├── .docker ├── data │ └── .gitignore ├── wordpress │ └── .gitignore ├── .gitignore └── docker-compose.yml ├── .dist ├── .gitignore ├── blacklist.txt └── deploy.sh ├── admin ├── icon.jpg ├── donate.png ├── partials │ ├── update-note.php │ └── defer-wordpress-admin-display.php ├── js │ └── defer-wordpress-admin.js ├── index.php ├── css │ └── defer-wordpress-admin.css └── class-defer-wordpress-admin.php ├── .github └── FUNDING.yml ├── .editorconfig ├── .gitignore ├── index.php ├── package.json ├── includes ├── index.php ├── class-defer-wordpress-activator.php ├── class-defer-wordpress-i18n.php ├── class-defer-wordpress-deactivator.php ├── class-defer-wordpress-loader.php └── class-defer-wordpress.php ├── uninstall.php ├── composer.json ├── .php-cs-fixer.php ├── README.md ├── defer-wordpress.php ├── README.txt ├── LICENSE └── composer.lock /VERSION: -------------------------------------------------------------------------------- 1 | 3.0.0 2 | -------------------------------------------------------------------------------- /cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /languages/defer-wordpress.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/lib/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /.docker/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /.docker/wordpress/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /.docker/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !docker-compose.yml 4 | -------------------------------------------------------------------------------- /.dist/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !VERSION 4 | !deploy.sh 5 | !blacklist.txt -------------------------------------------------------------------------------- /admin/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shinsenter/defer-wordpress/HEAD/admin/icon.jpg -------------------------------------------------------------------------------- /admin/donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shinsenter/defer-wordpress/HEAD/admin/donate.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: shinsenter 2 | patreon: appseeds 3 | custom: ['https://www.paypal.me/shinsenter'] 4 | -------------------------------------------------------------------------------- /public/css/defer-wordpress-public.css: -------------------------------------------------------------------------------- 1 | /** 2 | * All of the CSS for your public-facing functionality should be 3 | * included in this file. 4 | */ -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /admin/partials/update-note.php: -------------------------------------------------------------------------------- 1 |
2 |

3 | 💡 Tip for defer.js: 4 | 💯 Feel free to leave all the options at their default settings. The plugin will take care of optimizing your website. 5 | View plugin settings here.
6 |

7 |
8 | -------------------------------------------------------------------------------- /public/partials/defer-wordpress-public-display.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | wp-config.php 3 | wp-content/advanced-cache.php 4 | wp-content/backup-db/ 5 | wp-content/backups/ 6 | wp-content/blogs.dir/ 7 | wp-content/cache/ 8 | wp-content/upgrade/ 9 | wp-content/uploads/ 10 | wp-content/mu-plugins/ 11 | wp-content/wp-cache-config.php 12 | wp-content/plugins/hello.php 13 | /.htaccess 14 | /license.txt 15 | /readme.html 16 | /sitemap.xml 17 | /sitemap.xml.gz 18 | .DS_Store 19 | .php_cs.cache 20 | composer.phar 21 | /.old/ 22 | /vendor/ 23 | /node_modules/ -------------------------------------------------------------------------------- /admin/js/defer-wordpress-admin.js: -------------------------------------------------------------------------------- 1 | !function(e,n){var i=Function(),o=(n.log||i).bind(n);"object"==typeof e.chrome&&-1==e.navigator.userAgent.indexOf("Trident/")&&o("%c shinsenter %c defer.js ","font-size:16px;background:#2a313c;padding:2px;border-radius:4px 0 0 4px;color:#fff","font-size:16px;background:#e61e25;padding:2px;border-radius:0 4px 4px 0;color:#fff"),o(["This page was optimized with defer.js","(c) 2024 Mai Nhut Tan ","Wordpress: https://wordpress.org/plugins/shins-pageload-magic/","Github: https://code.shin.company/defer.js/"].join("\n"))}(window,console) -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shinsenter/defer-wordpress", 3 | "description": "🚀 A PHP library that focuses on minimizing payload size of HTML document and optimizing processing on the browser when rendering the WordPress page.", 4 | "homepage": "https://code.shin.company/defer-wordpress#readme", 5 | "author": "Mai Nhut Tan ", 6 | "license": "GPL-2.0", 7 | "dependencies": { 8 | "@shinsenter/defer.js": "^3.8.0" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://code.shin.company/defer-wordpress.git" 13 | }, 14 | "bugs": { 15 | "url": "https://code.shin.company/defer-wordpress/issues" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /admin/index.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | -------------------------------------------------------------------------------- /includes/index.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | // If uninstall not called from WordPress, then exit. 20 | if (!defined('WP_UNINSTALL_PLUGIN')) { 21 | exit; 22 | } 23 | -------------------------------------------------------------------------------- /.docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | 3 | services: 4 | mariadb: 5 | image: mariadb:10.5 6 | volumes: 7 | - "./data:/var/lib/mysql" 8 | environment: 9 | MYSQL_ROOT_PASSWORD: somewordpress 10 | MYSQL_DATABASE: wordpress 11 | MYSQL_USER: wordpress 12 | MYSQL_PASSWORD: wordpress 13 | wordpress: 14 | container_name: defer-wp 15 | hostname: defer-wp-test 16 | depends_on: 17 | - mariadb 18 | image: shinsenter/wordpress:php${PHP_VERSION:-8.3} 19 | ports: 20 | - "8000:80" 21 | volumes: 22 | - "./wordpress/:/var/www/html" 23 | - "../:/var/www/html/wp-content/plugins/defer-wordpress" 24 | environment: 25 | WORDPRESS_DB_HOST: mariadb:3306 26 | WORDPRESS_DB_USER: wordpress 27 | WORDPRESS_DB_PASSWORD: wordpress 28 | WORDPRESS_DB_NAME: wordpress 29 | -------------------------------------------------------------------------------- /public/js/defer-wordpress-public.js: -------------------------------------------------------------------------------- 1 | (function( $ ) { 2 | 'use strict'; 3 | 4 | /** 5 | * All of the code for your public-facing JavaScript source 6 | * should reside in this file. 7 | * 8 | * Note: It has been assumed you will write jQuery code here, so the 9 | * $ function reference has been prepared for usage within the scope 10 | * of this function. 11 | * 12 | * This enables you to define handlers, for when the DOM is ready: 13 | * 14 | * $(function() { 15 | * 16 | * }); 17 | * 18 | * When the window is loaded: 19 | * 20 | * $( window ).load(function() { 21 | * 22 | * }); 23 | * 24 | * ...and/or other possibilities. 25 | * 26 | * Ideally, it is not considered best practise to attach more than a 27 | * single DOM-ready or window-load handler for a particular page. 28 | * Although scripts in the WordPress core, Plugins and Themes may be 29 | * practising this, we should strive to set a better example in our own work. 30 | */ 31 | 32 | })( jQuery ); 33 | -------------------------------------------------------------------------------- /.dist/blacklist.txt: -------------------------------------------------------------------------------- 1 | .* 2 | .dist 3 | .docker 4 | *Test*.php 5 | composer.* 6 | node_modules/ 7 | package-lock.json 8 | package.json 9 | README.md 10 | sonar-* 11 | test/ 12 | Test/ 13 | tests/ 14 | Tests/ 15 | VERSION 16 | 17 | vendor/**/.editorconfig 18 | vendor/**/.git 19 | vendor/**/.gitattributes 20 | vendor/**/.github 21 | vendor/**/.gitignore 22 | vendor/**/.php_cs* 23 | vendor/**/.phpstorm.meta.php 24 | vendor/**/.scrutinizer 25 | vendor/**/*.dist 26 | vendor/**/*.md 27 | vendor/**/*.neon 28 | vendor/**/*.txt 29 | vendor/**/*.xml 30 | vendor/**/*.yml 31 | vendor/**/changelog* 32 | vendor/**/changes* 33 | vendor/**/composer.* 34 | vendor/**/contributing* 35 | vendor/**/demo 36 | vendor/**/doc 37 | vendor/**/dockerfile 38 | vendor/**/Dockerfile 39 | vendor/**/docs 40 | vendor/**/example 41 | vendor/**/examples 42 | vendor/**/faq* 43 | vendor/**/history* 44 | vendor/**/package-lock.json 45 | vendor/**/package.json 46 | vendor/**/phpunit.* 47 | vendor/**/readme* 48 | vendor/**/README* 49 | vendor/**/sonar-project.properties 50 | vendor/**/test 51 | vendor/**/tests 52 | vendor/**/travis 53 | vendor/**/upgrade* 54 | vendor/**/upgrading* 55 | 56 | defer.php/.docker/ 57 | defer.php/assets/ 58 | defer.php/public/lib/ 59 | -------------------------------------------------------------------------------- /includes/class-defer-wordpress-activator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * Fired during plugin activation. 21 | * 22 | * This class defines all code necessary to run during the plugin's activation. 23 | * 24 | * @since 1.0.0 25 | * 26 | * @author Mai Nhut Tan 27 | */ 28 | class Defer_Wordpress_Activator 29 | { 30 | /** 31 | * Short Description. (use period). 32 | * 33 | * Long Description. 34 | * 35 | * @since 2.0 36 | */ 37 | public static function activate() 38 | { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /includes/class-defer-wordpress-i18n.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * Define the internationalization functionality. 21 | * 22 | * Loads and defines the internationalization files for this plugin 23 | * so that it is ready for translation. 24 | * 25 | * @since 1.0.0 26 | * 27 | * @author Mai Nhut Tan 28 | */ 29 | class Defer_Wordpress_i18n 30 | { 31 | /** 32 | * Load the plugin text domain for translation. 33 | * 34 | * @since 2.0 35 | */ 36 | public function load_plugin_textdomain() 37 | { 38 | load_plugin_textdomain( 39 | 'defer-wordpress', 40 | false, 41 | dirname(dirname(plugin_basename(__FILE__))) . '/languages/' 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /includes/class-defer-wordpress-deactivator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * Fired during plugin deactivation. 21 | * 22 | * This class defines all code necessary to run during the plugin's deactivation. 23 | * 24 | * @since 1.0.0 25 | * 26 | * @author Mai Nhut Tan 27 | */ 28 | class Defer_Wordpress_Deactivator 29 | { 30 | /** 31 | * Short Description. (use period). 32 | * 33 | * Long Description. 34 | * 35 | * @since 2.0 36 | */ 37 | public static function deactivate() 38 | { 39 | delete_option(DEFER_WP_PLUGIN_NAME . 'version'); 40 | } 41 | 42 | public static function resetOptions() 43 | { 44 | if (class_exists('AppSeeds\Defer')) { 45 | $defer = defer_wp_instance([]); 46 | $options = $defer->optionArray(); 47 | 48 | foreach ($options as $key => $value) { 49 | delete_option(DEFER_WP_PLUGIN_PREFIX . $key); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /.dist/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | alias sed=$(which gsed) 5 | 6 | # git checkout master 7 | # git fetch --all 8 | # git reset --hard origin/master 9 | # git pull 10 | 11 | rm -Rf vendor 12 | base_dir="$(pwd)" 13 | build_dir=$base_dir/.dist/build 14 | 15 | echo 16 | echo $base_dir 17 | 18 | # Install modules 19 | composer pull 20 | 21 | # Prepare 22 | plugin_url=https://plugins.svn.wordpress.org 23 | plugin_name=shins-pageload-magic 24 | plugin_svn=$plugin_url/$plugin_name 25 | plugin_dir=$build_dir/$plugin_name 26 | black_list=$base_dir/.dist/blacklist.txt 27 | 28 | version=`head -n 1 $base_dir/VERSION` 29 | echo "Deploy version ${version} ${build_dir}" 30 | sed -i "s/\(Version:\s\+\).\+$/\\1${version}/" $base_dir/defer-wordpress.php 31 | sed -i "s/'DEFER_WP_PLUGIN_VERSION', '.*'/'DEFER_WP_PLUGIN_VERSION', '${version}'/" $base_dir/defer-wordpress.php 32 | 33 | if [[ ! -e $plugin_dir ]]; then 34 | echo "Clone from $plugin_svn" 35 | rm -Rf $build_dir 36 | mkdir -p $plugin_dir 37 | svn co --depth immediates $plugin_svn $plugin_dir 38 | svn co --depth infinity $plugin_svn/assets $plugin_dir/assets 39 | svn co --depth infinity $plugin_svn/trunk $plugin_dir/trunk 40 | fi 41 | echo "" 42 | 43 | # ------------------------------------------------------------------------------ 44 | echo "Copy from source" 45 | cd $plugin_dir 46 | svn rm --force trunk/* 47 | 48 | cd $base_dir 49 | rsync -aHxW --delete --exclude-from=${black_list/$base_dir/.} ./ ${plugin_dir/$base_dir/.}/trunk/ 50 | mv $plugin_dir/trunk/defer-wordpress.php $plugin_dir/trunk/$plugin_name.php 51 | # composer fixer .dist 52 | echo "" 53 | 54 | # ------------------------------------------------------------------------------ 55 | echo "Release $version" 56 | cd $plugin_dir 57 | svn add --force trunk/* 58 | svn stat 59 | svn ci -m "Release $version" --username=shinsenter 60 | echo "" 61 | 62 | # ------------------------------------------------------------------------------ 63 | echo "Add new tag $version" 64 | svn up --force tags/$version 65 | if [[ -e $plugin_dir ]]; then 66 | svn rm --force tags/$version 67 | rm -Rf tags/$version 68 | fi 69 | echo "" 70 | 71 | # ------------------------------------------------------------------------------ 72 | echo "Tagging version $version" 73 | svn cp trunk tags/$version 74 | svn ci -m "Tagging version $version" --username=shinsenter 75 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shinsenter/defer-wordpress", 3 | "description": "🚀 A WordPress plugin that focuses on minimizing payload size of HTML document and optimizing processing on the browser when rendering the WordPress page.", 4 | "type": "project", 5 | "license": "GPL-2.0", 6 | "authors": [ 7 | { 8 | "name": "Mai Nhut Tan", 9 | "email": "shin@shin.company", 10 | "homepage": "https://code.shin.company", 11 | "role": "Owner" 12 | } 13 | ], 14 | "support": { 15 | "issues": "https://code.shin.company/defer-wordpress/issues", 16 | "source": "https://code.shin.company/defer-wordpress" 17 | }, 18 | "funding": [ 19 | { 20 | "type": "github", 21 | "url": "https://code.shin.company/defer-wordpress/stargazers" 22 | }, 23 | { 24 | "type": "paypal", 25 | "url": "https://www.patreon.com/appseeds" 26 | }, 27 | { 28 | "type": "patreon", 29 | "url": "https://www.patreon.com/shinsenter" 30 | } 31 | ], 32 | "scripts": { 33 | "fixer": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix --show-progress=dots --verbose --ansi", 34 | "pull": [ 35 | "rm -rf ./cache/*/ ./vendor/ ./node_modules/ ./composer.lock ./package-lock.json", 36 | "composer clearcache --ansi", 37 | "composer update -o -a -n --no-dev --prefer-dist --ansi", 38 | "npm i --prod --ansi", 39 | "rm -rf ./public/lib/*", 40 | "cp -p ./node_modules/@shinsenter/defer.js/dist/*.js ./public/lib/" 41 | ], 42 | "deploy": [ 43 | "bash ./.dist/deploy.sh" 44 | ] 45 | }, 46 | "config": { 47 | "classloader-suffix": "ShinSenterDeferWordpress", 48 | "preferred-install": "dist", 49 | "optimize-autoloader": true, 50 | "sort-packages": true, 51 | "platform": { 52 | "php": "7.2" 53 | }, 54 | "allow-plugins": { 55 | "dangoodman/composer-for-wordpress": true 56 | } 57 | }, 58 | "require": { 59 | "php": ">=7.2", 60 | "shinsenter/defer.php": "^2.5", 61 | "symfony/polyfill-mbstring": "<=1.22.0", 62 | "dangoodman/composer-for-wordpress": "^2.0" 63 | }, 64 | "require-dev": { 65 | "friendsofphp/php-cs-fixer": ">=2" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /admin/css/defer-wordpress-admin.css: -------------------------------------------------------------------------------- 1 | #toplevel_page_defer-wordpress { 2 | display: none; 3 | } 4 | 5 | #toplevel_page_defer-wordpress img { 6 | width: 16px; 7 | height: 16px; 8 | } 9 | 10 | .toplevel_page_defer-wordpress .wrap { 11 | padding: 0.5rem; 12 | word-wrap: break-word; 13 | } 14 | 15 | .toplevel_page_defer-wordpress .wrap * { 16 | box-sizing: border-box; 17 | max-width: 100%; 18 | } 19 | 20 | .toplevel_page_defer-wordpress .wrap h1 { 21 | margin-bottom: 1rem; 22 | } 23 | 24 | .toplevel_page_defer-wordpress .wrap h2 { 25 | padding: 8px 12px; 26 | margin: 0; 27 | line-height: 1.4; 28 | } 29 | 30 | .toplevel_page_defer-wordpress .wrap img { 31 | display: inline-block; 32 | } 33 | 34 | .toplevel_page_defer-wordpress .wrap .deferjs-icon { 35 | width: 28px; 36 | height: 28px; 37 | vertical-align: top; 38 | } 39 | 40 | .toplevel_page_defer-wordpress .wrap p { 41 | line-height: 1.5; 42 | } 43 | .toplevel_page_defer-wordpress .wrap code { 44 | font-size: smaller; 45 | line-height: inherit; 46 | } 47 | 48 | .toplevel_page_defer-wordpress .wrap pre code { 49 | display: block; 50 | line-height: 1.5; 51 | } 52 | 53 | .toplevel_page_defer-wordpress .wrap tr { 54 | border-bottom: 1px #f0f0f0 solid; 55 | } 56 | 57 | .toplevel_page_defer-wordpress .wrap fieldset textarea, 58 | .toplevel_page_defer-wordpress .wrap fieldset input[type="text"], 59 | .toplevel_page_defer-wordpress .wrap fieldset input[type="number"] { 60 | width: 100% 61 | } 62 | 63 | .toplevel_page_defer-wordpress .wrap fieldset textarea { 64 | font-size: smaller; 65 | } 66 | 67 | .toplevel_page_defer-wordpress .wrap fieldset .help { 68 | font-size: smaller; 69 | color: #555; 70 | } 71 | 72 | .toplevel_page_defer-wordpress .wrap fieldset .help.notice { 73 | font-size: smaller; 74 | color: rgb(255, 123, 0); 75 | } 76 | 77 | .toplevel_page_defer-wordpress .wrap .submit { 78 | padding: 0; 79 | } 80 | 81 | .toplevel_page_defer-wordpress .wrap .donate { 82 | text-align: center; 83 | } 84 | 85 | .toplevel_page_defer-wordpress .wrap .donate>* { 86 | display: inline-block; 87 | vertical-align: middle; 88 | margin: 0 0.5em; 89 | } 90 | 91 | @media screen and (min-width: 760px) { 92 | .toplevel_page_defer-wordpress .wrap .main { 93 | width: 70%; 94 | float: left; 95 | padding-right: 2rem; 96 | } 97 | .toplevel_page_defer-wordpress .wrap .side { 98 | margin-top: 0; 99 | margin-left: 70%; 100 | } 101 | } -------------------------------------------------------------------------------- /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | $header = <<<'EOF' 20 | 🚀 A WordPress plugin that focuses on minimizing payload size of HTML document 21 | and optimizing processing on the browser when rendering the WordPress page. 22 | (c) 2021-2024 SHIN Company 23 | 24 | PHP Version >=7.2 25 | 26 | @category Web_Performance_Optimization 27 | @package defer-wordpress 28 | @author Mai Nhut Tan 29 | @copyright 2021-2024 SHIN Company 30 | @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 31 | @link https://code.shin.company/defer-wordpress 32 | @see https://code.shin.company/defer-wordpress/blob/master/README.md 33 | EOF; 34 | 35 | $rules = [ 36 | '@PhpCsFixer' => true, 37 | 'concat_space' => ['spacing' => 'one'], 38 | 'header_comment' => ['header' => $header, 'comment_type' => 'PHPDoc'], 39 | 'increment_style' => ['style' => 'post'], 40 | 'no_superfluous_phpdoc_tags' => false, 41 | 'phpdoc_summary' => true, 42 | 'phpdoc_to_comment' => false, 43 | 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], 44 | 45 | 'multiline_whitespace_before_semicolons' => [ 46 | 'strategy' => 'no_multi_line', 47 | ], 48 | 49 | 'phpdoc_align' => ['align' => 'vertical'], 50 | 51 | 'binary_operator_spaces' => [ 52 | 'default' => 'single_space', 53 | 'operators' => [ 54 | '||' => 'align_single_space_minimal', 55 | 'or' => 'align_single_space_minimal', 56 | '=' => 'align_single_space_minimal', 57 | '=>' => 'align_single_space_minimal', 58 | '<=>' => 'align_single_space_minimal', 59 | ], 60 | ], 61 | 62 | 'visibility_required' => [ 63 | 'elements' => ['method', 'property'], 64 | ], 65 | ]; 66 | 67 | $finder = \PhpCsFixer\Finder::create() 68 | ->in(__DIR__) 69 | ->name('*.php') 70 | ->exclude('.dist') 71 | ->exclude('.docker') 72 | ->exclude('.github') 73 | ->exclude('cache') 74 | ->exclude('node_modules') 75 | ->exclude('vendor') 76 | ->ignoreDotFiles(false) 77 | ->ignoreVCS(true); 78 | 79 | return (new \PhpCsFixer\Config()) 80 | ->setFinder($finder) 81 | ->setRules($rules) 82 | ->setIndent(' ') 83 | ->setLineEnding("\n") 84 | ->setUsingCache(false); 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # defer-wordpress 2 | 3 | 🚀 Unleash the power of cutting edge WordPress optimization tech. 💯 SEO-Optimized and 🎯 Effortlessly User-Friendly! 4 | 5 | Download: [https://wordpress.org/plugins/shins-pageload-magic/](https://wordpress.org/plugins/shins-pageload-magic/) 6 | 7 | ![GitHub](https://img.shields.io/github/license/shinsenter/defer-wordpress.svg) 8 | [![Post an issue](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://code.shin.company/defer-wordpress/issues) 9 | ![GitHub issues](https://img.shields.io/github/issues-raw/shinsenter/defer-wordpress.svg) 10 | ![GitHub Release Date](https://img.shields.io/github/release-date/shinsenter/defer-wordpress.svg) 11 | 12 | ⚡️ Experience lightning-fast load times with our native, blazingly quick lazy loader. ✅ Backward compatible with legacy browsers (IE9+). 💯 SEO-optimized. 🧩 Lazy-load everything. 13 | 14 | This plugin empowers you to optimize a wide range of elements, including images, videos, audio, iframes, stylesheets, and JavaScript, for a seamless user experience. 15 | 16 | Leveraging tips from seasoned web experts and harnessing the latest web technologies for resource lazy-loading, this plugin ensures your website operates at peak efficiency, providing your visitors with a lightning-fast browsing experience. 17 | 18 | If you find this plugin valuable, please consider leaving a [5-star review (⭐️⭐️⭐️⭐️⭐️)](https://wordpress.org/support/plugin/shins-pageload-magic/reviews/?filter=5#new-post) to support my efforts. 19 | 20 | ## What People Love 21 | 22 | - ⚡️ Native API, blazingly fast performance 23 | - 👍 Support for legacy browsers (IE9+) 24 | - 🥇 SEO-friendly optimization 25 | - ✅ Incredibly easy to use 26 | - 💯 No dependencies, no jQuery required 27 | - 🤝 Works seamlessly with your favorite frameworks 28 | - 🧩 Utilizes [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) for optimized CPU usage 29 | - 🏞 Supports responsive images with `srcset` and `sizes` attributes 30 | 31 | 💡 Tip: For optimal results, consider disabling optimization features from other plugins (e.g., lazy-loading, HTML minification, JS minification). 32 | 33 | We recommend using this plugin alongside another page-caching solution for best performance. 34 | 35 | ![Scoring 100/100 in Google PageSpeed Test](https://ps.w.org/shins-pageload-magic/assets/screenshot-1.jpg) 36 | 37 | ## Browser support 38 | 39 | This plugin also works perfectly on popular browsers, including Internet Explorer 9 and later. 40 | 41 | - 🖥 IE9+ / Microsoft EDGE 42 | - 🖥 Firefox 4+ 43 | - 🖥 Safari 3+ 44 | - 🖥 Chrome 45 | - 🖥 Opera 46 | - 📱 Android 4+ 47 | - 📱 iOS 3.2+ 48 | 49 | ## Powered by defer.js, defer.php 50 | 51 | [defer.js](https://code.shin.company/defer.js) 52 | 🥇 A super small, super efficient library that helps you lazy load almost everything like images, video, audio, iframes as well as stylesheets, and JavaScript. 53 | 54 | [defer.php](https://code.shin.company/defer.php) 55 | 🚀 A PHP library that focuses on minimizing payload size of HTML document and optimizing processing on the browser when rendering the web page. 56 | 57 | 58 | ## Support my activities 59 | 60 | If you find this plugin useful, consider donating via [PayPal](https://www.paypal.me/shinsenter) or open an issue on [Github](https://github.com/shinsenter/defer-wordpress/issues/new). 61 | 62 | Your support helps keep this plugin maintained and improved for the community. 63 | 64 | --- 65 | 66 | Released under the [GNU General Public License v2 license](https://code.shin.company/defer-wordpress/blob/master/LICENSE). 67 | 68 | Copyright (c) 2024 Mai Nhut Tan <[shin@shin.company](mailto:shin@shin.company)> 69 | -------------------------------------------------------------------------------- /public/class-defer-wordpress-public.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * The public-facing functionality of the plugin. 21 | * 22 | * Defines the plugin name, version, and two examples hooks for how to 23 | * enqueue the public-facing stylesheet and JavaScript. 24 | * 25 | * @author Mai Nhut Tan 26 | */ 27 | class Defer_Wordpress_Public 28 | { 29 | /** 30 | * The ID of this plugin. 31 | * 32 | * @since 2.0 33 | * 34 | * @var string the ID of this plugin 35 | */ 36 | private $plugin_name; 37 | 38 | /** 39 | * The version of this plugin. 40 | * 41 | * @since 2.0 42 | * 43 | * @var string the current version of this plugin 44 | */ 45 | private $version; 46 | 47 | /** 48 | * Initialize the class and set its properties. 49 | * 50 | * @since 2.0 51 | * 52 | * @param string $plugin_name the name of the plugin 53 | * @param string $version the version of this plugin 54 | */ 55 | public function __construct($plugin_name, $version) 56 | { 57 | $this->plugin_name = $plugin_name; 58 | $this->version = $version; 59 | } 60 | 61 | /** 62 | * Register the stylesheets for the public-facing side of the site. 63 | * 64 | * @since 2.0 65 | */ 66 | public function enqueue_styles() 67 | { 68 | /* 69 | * This function is provided for demonstration purposes only. 70 | * 71 | * An instance of this class should be passed to the run() function 72 | * defined in Defer_Wordpress_Loader as all of the hooks are defined 73 | * in that particular class. 74 | * 75 | * The Defer_Wordpress_Loader will then create the relationship 76 | * between the defined hooks and the functions defined in this 77 | * class. 78 | */ 79 | 80 | wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/defer-wordpress-public.css', [], $this->version, 'all'); 81 | } 82 | 83 | /** 84 | * Register the JavaScript for the public-facing side of the site. 85 | * 86 | * @since 2.0 87 | */ 88 | public function enqueue_scripts() 89 | { 90 | /* 91 | * This function is provided for demonstration purposes only. 92 | * 93 | * An instance of this class should be passed to the run() function 94 | * defined in Defer_Wordpress_Loader as all of the hooks are defined 95 | * in that particular class. 96 | * 97 | * The Defer_Wordpress_Loader will then create the relationship 98 | * between the defined hooks and the functions defined in this 99 | * class. 100 | */ 101 | 102 | wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/defer-wordpress-public.js', ['jquery'], $this->version, false); 103 | } 104 | 105 | public function init() 106 | { 107 | ob_start('defer_wp_ob'); 108 | } 109 | 110 | public function shutdown() 111 | { 112 | $final = ''; 113 | $levels = ob_get_level(); 114 | 115 | for ($i = 0; $i < $levels; $i++) { 116 | $final .= ob_get_clean(); 117 | } 118 | 119 | echo $final; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /includes/class-defer-wordpress-loader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * Register all actions and filters for the plugin. 21 | * 22 | * Maintain a list of all hooks that are registered throughout 23 | * the plugin, and register them with the WordPress API. Call the 24 | * run function to execute the list of actions and filters. 25 | * 26 | * @author Mai Nhut Tan 27 | */ 28 | class Defer_Wordpress_Loader 29 | { 30 | /** 31 | * The array of actions registered with WordPress. 32 | * 33 | * @since 2.0 34 | * 35 | * @var array the actions registered with WordPress to fire when the plugin loads 36 | */ 37 | protected $actions; 38 | 39 | /** 40 | * The array of filters registered with WordPress. 41 | * 42 | * @since 2.0 43 | * 44 | * @var array the filters registered with WordPress to fire when the plugin loads 45 | */ 46 | protected $filters; 47 | 48 | /** 49 | * Initialize the collections used to maintain the actions and filters. 50 | * 51 | * @since 2.0 52 | */ 53 | public function __construct() 54 | { 55 | $this->actions = []; 56 | $this->filters = []; 57 | } 58 | 59 | /** 60 | * Add a new action to the collection to be registered with WordPress. 61 | * 62 | * @since 2.0 63 | * 64 | * @param string $hook the name of the WordPress action that is being registered 65 | * @param object $component a reference to the instance of the object on which the action is defined 66 | * @param string $callback the name of the function definition on the $component 67 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 68 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. 69 | */ 70 | public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) 71 | { 72 | $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args); 73 | } 74 | 75 | /** 76 | * Add a new filter to the collection to be registered with WordPress. 77 | * 78 | * @since 2.0 79 | * 80 | * @param string $hook the name of the WordPress filter that is being registered 81 | * @param object $component a reference to the instance of the object on which the filter is defined 82 | * @param string $callback the name of the function definition on the $component 83 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 84 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1 85 | */ 86 | public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) 87 | { 88 | $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args); 89 | } 90 | 91 | /** 92 | * Register the filters and actions with WordPress. 93 | * 94 | * @since 2.0 95 | */ 96 | public function run() 97 | { 98 | foreach ($this->filters as $hook) { 99 | add_filter($hook['hook'], [$hook['component'], $hook['callback']], $hook['priority'], $hook['accepted_args']); 100 | } 101 | 102 | foreach ($this->actions as $hook) { 103 | add_action($hook['hook'], [$hook['component'], $hook['callback']], $hook['priority'], $hook['accepted_args']); 104 | } 105 | } 106 | 107 | /** 108 | * A utility function that is used to register the actions and hooks into a single 109 | * collection. 110 | * 111 | * @since 2.0 112 | * 113 | * @param array $hooks the collection of hooks that is being registered (that is, actions or filters) 114 | * @param string $hook the name of the WordPress filter that is being registered 115 | * @param object $component a reference to the instance of the object on which the filter is defined 116 | * @param string $callback the name of the function definition on the $component 117 | * @param int $priority the priority at which the function should be fired 118 | * @param int $accepted_args the number of arguments that should be passed to the $callback 119 | * 120 | * @return array the collection of actions and filters registered with WordPress 121 | */ 122 | private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) 123 | { 124 | $hooks[] = [ 125 | 'hook' => $hook, 126 | 'component' => $component, 127 | 'callback' => $callback, 128 | 'priority' => $priority, 129 | 'accepted_args' => $accepted_args, 130 | ]; 131 | 132 | return $hooks; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /defer-wordpress.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | // If this file is called directly, abort. 20 | if (!defined('WPINC')) { 21 | exit; 22 | } 23 | 24 | /* 25 | * The plugin bootstrap file 26 | * 27 | * @wordpress-plugin 28 | * Plugin Name: A faster website! (aka defer.js) 29 | * Plugin URI: https://wordpress.org/plugins/shins-pageload-magic/ 30 | * Description: 💯 Latest web technologies in website optimization by experienced web experts. 🔰 Very easy to use. 31 | * Version: 3.0.0 32 | * Author: Mai Nhut Tan 33 | * Author URI: https://code.shin.company/ 34 | * License: GPL-2.0+ 35 | * License URI: http://www.gnu.org/licenses/gpl-2.0.txt 36 | * Text Domain: defer-wordpress 37 | * Domain Path: /languages 38 | */ 39 | 40 | /* 41 | * Defines currently plugin version. 42 | * Includes defer.php library 43 | */ 44 | if (!defined('DEFER_WP_PLUGIN_VERSION')) { 45 | define('DEFER_WP_PLUGIN_BASE', plugin_basename(__FILE__)); 46 | define('DEFER_WP_PLUGIN_NAME', 'defer-wordpress'); 47 | define('DEFER_WP_PLUGIN_VERSION', '3.0.0'); 48 | define('DEFER_WP_PLUGIN_PREFIX', DEFER_WP_PLUGIN_NAME . '_'); 49 | 50 | define('DEFER_WP_PLUGIN_HOOK', 'plugin_action_links_' . DEFER_WP_PLUGIN_BASE); 51 | define('DEFER_WP_PLUGIN_DESC_HOOK', 'network_admin_plugin_action_links_' . DEFER_WP_PLUGIN_BASE); 52 | 53 | define('DEFER_WP_SETTINGS', admin_url('admin.php?page=' . DEFER_WP_PLUGIN_NAME)); 54 | 55 | define('DEFER_WP_CACHE_DIR', __DIR__ . '/cache'); 56 | define('DEFER_WP_CACHE_EXP', 600); 57 | 58 | define('DEFER_WP_SRC_DEFERJS_CDN', __DIR__ . '/public/lib/defer_plus.min.js'); 59 | define('DEFER_WP_SRC_POLYFILL_CDN', plugin_dir_url(__FILE__) . 'public/lib/polyfill.min.js'); 60 | 61 | define('DEFER_WP_HOMEPAGE', 'https://shinsenter.github.io/defer.js'); 62 | define('DEFER_WP_PLUGIN_URL', 'https://wordpress.org/plugins/shins-pageload-magic/'); 63 | define('DEFER_WP_PAYPAL', 'https://www.paypal.me/shinsenter'); 64 | define('DEFER_WP_PATREON', 'https://www.patreon.com/appseeds'); 65 | define('DEFER_WP_RATING', 'https://wordpress.org/support/plugin/shins-pageload-magic/reviews/?filter=5#new-post'); 66 | define('DEFER_SOURCE_HOMEPAGE', 'https://code.shin.company/defer.js'); 67 | 68 | require_once __DIR__ . '/vendor/autoload.php'; 69 | } 70 | 71 | /** 72 | * The code that runs during plugin activation. 73 | * This action is documented in includes/class-defer-wordpress-activator.php. 74 | */ 75 | function activate_defer_wordpress() 76 | { 77 | require_once plugin_dir_path(__FILE__) . 'includes/class-defer-wordpress-activator.php'; 78 | Defer_Wordpress_Activator::activate(); 79 | } 80 | 81 | /** 82 | * The code that runs during plugin deactivation. 83 | * This action is documented in includes/class-defer-wordpress-deactivator.php. 84 | */ 85 | function deactivate_defer_wordpress() 86 | { 87 | require_once plugin_dir_path(__FILE__) . 'includes/class-defer-wordpress-deactivator.php'; 88 | Defer_Wordpress_Deactivator::deactivate(); 89 | } 90 | 91 | register_activation_hook(__FILE__, 'activate_defer_wordpress'); 92 | register_deactivation_hook(__FILE__, 'deactivate_defer_wordpress'); 93 | 94 | /** 95 | * The core plugin class that is used to define internationalization, 96 | * admin-specific hooks, and public-facing site hooks. 97 | */ 98 | require plugin_dir_path(__FILE__) . 'includes/class-defer-wordpress.php'; 99 | 100 | // Version check 101 | if (!function_exists('defer_wp_update_note')) { 102 | function defer_wp_update_note() 103 | { 104 | include plugin_dir_path(__FILE__) . 'admin/partials/update-note.php'; 105 | 106 | // Update the version 107 | update_option(DEFER_WP_PLUGIN_NAME . 'version', DEFER_WP_PLUGIN_VERSION); 108 | } 109 | } 110 | 111 | if (!function_exists('defer_wp_instance')) { 112 | function defer_wp_instance($options) 113 | { 114 | static $defer; 115 | 116 | if (!isset($defer) && class_exists('AppSeeds\Defer')) { 117 | $defer = new \AppSeeds\Defer(); 118 | } 119 | 120 | if ($defer instanceof \AppSeeds\Defer && !empty($options)) { 121 | try { 122 | $defer->options()->setOption($options)->backup(); 123 | } catch (\Exception $e) { 124 | if (defined('WP_DEBUG') && WP_DEBUG == true) { 125 | throw $e; 126 | } 127 | } 128 | } 129 | 130 | return $defer; 131 | } 132 | } 133 | 134 | if (!function_exists('defer_wp_ob')) { 135 | function defer_wp_ob($buffer) 136 | { 137 | // if the doctype is not html then return the content immediately 138 | foreach (headers_list() as $header) { 139 | if (preg_match('/Content-Type:/i', $header)) { 140 | if (false === strstr(strtolower($header), 'html')) { 141 | return $buffer; 142 | } 143 | 144 | // end the loop 145 | break; 146 | } 147 | } 148 | 149 | $output = false; 150 | 151 | try { 152 | $admin = new Defer_Wordpress_Admin(DEFER_WP_PLUGIN_NAME, DEFER_WP_PLUGIN_VERSION); 153 | $defer = defer_wp_instance($admin->get_settings()); 154 | $output = $defer->fromHtml($buffer)->toHtml(); 155 | } catch (\Exception $e) { 156 | $output = false; 157 | } 158 | 159 | return $output ?: $buffer; 160 | } 161 | } 162 | 163 | /** 164 | * Begins execution of the plugin. 165 | * 166 | * Since everything within the plugin is registered via hooks, 167 | * then kicking off the plugin from this point in the file does 168 | * not affect the page life cycle. 169 | * 170 | * @since 2.2.0 171 | */ 172 | function run_defer_wordpress() 173 | { 174 | $plugin = new Defer_Wordpress(); 175 | $plugin->run(); 176 | 177 | add_filter('wp_lazy_loading_enabled', '__return_false'); 178 | 179 | if (DEFER_WP_PLUGIN_VERSION !== get_option(DEFER_WP_PLUGIN_NAME . 'version', '')) { 180 | add_action('admin_notices', 'defer_wp_update_note'); 181 | } 182 | } 183 | 184 | run_defer_wordpress(); 185 | -------------------------------------------------------------------------------- /includes/class-defer-wordpress.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * PHP Version >=7.2 9 | * 10 | * @category Web_Performance_Optimization 11 | * @package defer-wordpress 12 | * @author Mai Nhut Tan 13 | * @copyright 2021-2024 SHIN Company 14 | * @license https://code.shin.company/defer-wordpress/blob/master/LICENSE GPL-2.0 15 | * @link https://code.shin.company/defer-wordpress 16 | * @see https://code.shin.company/defer-wordpress/blob/master/README.md 17 | */ 18 | 19 | /** 20 | * The core plugin class. 21 | * 22 | * This is used to define internationalization, admin-specific hooks, and 23 | * public-facing site hooks. 24 | * 25 | * Also maintains the unique identifier of this plugin as well as the current 26 | * version of the plugin. 27 | * 28 | * @since 1.0.0 29 | * 30 | * @author Mai Nhut Tan 31 | */ 32 | class Defer_Wordpress 33 | { 34 | /** 35 | * The loader that's responsible for maintaining and registering all hooks that power 36 | * the plugin. 37 | * 38 | * @since 2.0 39 | * 40 | * @var Defer_Wordpress_Loader maintains and registers all hooks for the plugin 41 | */ 42 | protected $loader; 43 | 44 | /** 45 | * The unique identifier of this plugin. 46 | * 47 | * @since 2.0 48 | * 49 | * @var string the string used to uniquely identify this plugin 50 | */ 51 | protected $plugin_name; 52 | 53 | /** 54 | * The current version of the plugin. 55 | * 56 | * @since 2.0 57 | * 58 | * @var string the current version of the plugin 59 | */ 60 | protected $version; 61 | 62 | /** 63 | * Define the core functionality of the plugin. 64 | * 65 | * Set the plugin name and the plugin version that can be used throughout the plugin. 66 | * Load the dependencies, define the locale, and set the hooks for the admin area and 67 | * the public-facing side of the site. 68 | * 69 | * @since 2.0 70 | */ 71 | public function __construct() 72 | { 73 | $this->plugin_name = DEFER_WP_PLUGIN_NAME; 74 | $this->version = DEFER_WP_PLUGIN_VERSION; 75 | 76 | $this->load_dependencies(); 77 | $this->set_locale(); 78 | $this->define_admin_hooks(); 79 | $this->define_public_hooks(); 80 | } 81 | 82 | /** 83 | * Run the loader to execute all of the hooks with WordPress. 84 | * 85 | * @since 2.0 86 | */ 87 | public function run() 88 | { 89 | $this->loader->run(); 90 | } 91 | 92 | /** 93 | * The name of the plugin used to uniquely identify it within the context of 94 | * WordPress and to define internationalization functionality. 95 | * 96 | * @since 1.0.0 97 | * 98 | * @return string the name of the plugin 99 | */ 100 | public function get_plugin_name() 101 | { 102 | return $this->plugin_name; 103 | } 104 | 105 | /** 106 | * The reference to the class that orchestrates the hooks with the plugin. 107 | * 108 | * @since 1.0.0 109 | * 110 | * @return Defer_Wordpress_Loader orchestrates the hooks of the plugin 111 | */ 112 | public function get_loader() 113 | { 114 | return $this->loader; 115 | } 116 | 117 | /** 118 | * Retrieve the version number of the plugin. 119 | * 120 | * @since 1.0.0 121 | * 122 | * @return string the version number of the plugin 123 | */ 124 | public function get_version() 125 | { 126 | return $this->version; 127 | } 128 | 129 | /* 130 | |-------------------------------------------------------------------------- 131 | | Wordpress functions 132 | |-------------------------------------------------------------------------- 133 | */ 134 | 135 | /** 136 | * Load the required dependencies for this plugin. 137 | * 138 | * Include the following files that make up the plugin: 139 | * 140 | * - Defer_Wordpress_Loader. Orchestrates the hooks of the plugin. 141 | * - Defer_Wordpress_i18n. Defines internationalization functionality. 142 | * - Defer_Wordpress_Admin. Defines all hooks for the admin area. 143 | * - Defer_Wordpress_Public. Defines all hooks for the public side of the site. 144 | * 145 | * Create an instance of the loader which will be used to register the hooks 146 | * with WordPress. 147 | * 148 | * @since 2.0 149 | */ 150 | private function load_dependencies() 151 | { 152 | /** 153 | * The class responsible for orchestrating the actions and filters of the 154 | * core plugin. 155 | */ 156 | require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-defer-wordpress-loader.php'; 157 | 158 | /** 159 | * The class responsible for defining internationalization functionality 160 | * of the plugin. 161 | */ 162 | require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-defer-wordpress-i18n.php'; 163 | 164 | /** 165 | * The class responsible for defining all actions that occur in the admin area. 166 | */ 167 | require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-defer-wordpress-admin.php'; 168 | 169 | /** 170 | * The class responsible for defining all actions that occur in the public-facing 171 | * side of the site. 172 | */ 173 | require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-defer-wordpress-public.php'; 174 | 175 | $this->loader = new Defer_Wordpress_Loader(); 176 | } 177 | 178 | /** 179 | * Define the locale for this plugin for internationalization. 180 | * 181 | * Uses the Defer_Wordpress_i18n class in order to set the domain and to register the hook 182 | * with WordPress. 183 | * 184 | * @since 2.0 185 | */ 186 | private function set_locale() 187 | { 188 | $plugin_i18n = new Defer_Wordpress_i18n(); 189 | 190 | $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain'); 191 | } 192 | 193 | /** 194 | * Register all of the hooks related to the admin area functionality 195 | * of the plugin. 196 | * 197 | * @since 2.0 198 | */ 199 | private function define_admin_hooks() 200 | { 201 | $plugin_admin = new Defer_Wordpress_Admin($this->get_plugin_name(), $this->get_version()); 202 | 203 | $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles'); 204 | $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts'); 205 | $this->loader->add_action('admin_menu', $plugin_admin, 'register_menu'); 206 | $this->loader->add_action('admin_init', $plugin_admin, 'register_options'); 207 | $this->loader->add_filter(DEFER_WP_PLUGIN_HOOK, $plugin_admin, 'register_menu_plugin_options'); 208 | $this->loader->add_filter(DEFER_WP_PLUGIN_DESC_HOOK, $plugin_admin, 'register_menu_plugin_options'); 209 | } 210 | 211 | /** 212 | * Register all of the hooks related to the public-facing functionality 213 | * of the plugin. 214 | * 215 | * @since 2.0 216 | */ 217 | private function define_public_hooks() 218 | { 219 | $plugin_public = new Defer_Wordpress_Public($this->get_plugin_name(), $this->get_version()); 220 | 221 | if (!(defined('WP_CLI') && WP_CLI) && !$this->is_ajax() && !is_admin() && !$this->is_wplogin()) { 222 | $this->loader->add_action('init', $plugin_public, 'init', -1); 223 | $this->loader->add_action('shutdown', $plugin_public, 'shutdown', 100000); 224 | } 225 | } 226 | 227 | /** 228 | * Detect login page. 229 | * 230 | * @since 2.0 231 | */ 232 | private function is_wplogin() 233 | { 234 | $incl_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, ABSPATH); 235 | 236 | return (in_array($incl_path . 'wp-login.php', get_included_files()) 237 | || in_array($incl_path . 'wp-register.php', get_included_files())) 238 | || (isset($_GLOBALS['pagenow']) && 'wp-login.php' === $GLOBALS['pagenow']) 239 | || '/wp-login.php' == $_SERVER['PHP_SELF']; 240 | } 241 | 242 | private function is_ajax() 243 | { 244 | if ( 245 | !empty($_SERVER['HTTP_X_REQUESTED_WITH']) 246 | && 'xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) 247 | ) { 248 | return true; 249 | } 250 | 251 | if ( 252 | empty($_SERVER['HTTP_ACCEPT']) 253 | || false === strstr(strtolower($_SERVER['HTTP_ACCEPT']), 'html') 254 | ) { 255 | return true; 256 | } 257 | 258 | return false; 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | === A faster website! (aka defer.js) === 2 | Contributors: shinsenter 3 | Donate link: https://www.paypal.me/shinsenter 4 | Tags: lazyload,optimize,pagespeed,performance,defer.js 5 | Requires at least: 4.0 6 | Tested up to: 6.6.1 7 | Stable tag: 3.0.0 8 | Requires PHP: 7.2 9 | License: GPLv2 or later 10 | License URI: https://code.shin.company/defer-wordpress/blob/master/LICENSE 11 | 12 | 🚀 Unleash the power of cutting edge WordPress optimization tech. 💯 SEO-Optimized and 🎯 Effortlessly User-Friendly! 13 | 14 | == Description == 15 | 16 | ⚡️ Experience lightning-fast load times with our native, blazingly quick lazy loader. ✅ Backward compatible with legacy browsers (IE9+). 💯 SEO-optimized. 🧩 Lazy-load everything. 17 | 18 | This plugin empowers you to optimize a wide range of elements, including images, videos, audio, iframes, stylesheets, and JavaScript, for a seamless user experience. 19 | 20 | Leveraging tips from seasoned web experts and harnessing the latest web technologies for resource lazy-loading, this plugin ensures your website operates at peak efficiency, providing your visitors with a lightning-fast browsing experience. 21 | 22 | If you find this plugin valuable, please consider leaving a [5-star review (⭐️⭐️⭐️⭐️⭐️)](https://wordpress.org/support/plugin/shins-pageload-magic/reviews/?filter=5#new-post) to support my efforts. 23 | 24 | ### What People Love 25 | 26 | - ⚡️ Native API, blazingly fast performance 27 | - 👍 Support for legacy browsers (IE9+) 28 | - 🥇 SEO-friendly optimization 29 | - ✅ Incredibly easy to use 30 | - 💯 No dependencies, no jQuery required 31 | - 🤝 Works seamlessly with your favorite frameworks 32 | - 🧩 Utilizes [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) for optimized CPU usage 33 | - 🏞 Supports responsive images with `srcset` and `sizes` attributes 34 | 35 | 💡 Tip: For optimal results, consider disabling optimization features from other plugins (e.g., lazy-loading, HTML minification, JS minification). 36 | 37 | We recommend using this plugin alongside another page-caching solution for best performance. 38 | 39 | ![Scoring 100/100 in Google PageSpeed Test](https://raw.githubusercontent.com/shinsenter/defer.js/master/docs/assets/scores.jpg) 40 | 41 | ### Browser support 42 | 43 | This plugin also works perfectly on popular browsers, including Internet Explorer 9 and later. 44 | 45 | - 🖥 IE9+ / Microsoft EDGE 46 | - 🖥 Firefox 4+ 47 | - 🖥 Safari 3+ 48 | - 🖥 Chrome 49 | - 🖥 Opera 50 | - 📱 Android 4+ 51 | - 📱 iOS 3.2+ 52 | 53 | ### Powered by defer.js, defer.php 54 | 55 | [defer.js](https://code.shin.company/defer.js) 56 | 🥇 A super small, super efficient library that helps you lazy load almost everything like images, video, audio, iframes as well as stylesheets, and JavaScript. 57 | 58 | [defer.php](https://code.shin.company/defer.php) 59 | 🚀 A PHP library that focuses on minimizing payload size of HTML document and optimizing processing on the browser when rendering the web page. 60 | 61 | #### Key features 62 | 63 | - [x] Embed [defer.js](https://code.shin.company/defer.js) plugin 64 | - [x] Normalize DOM elements 65 | - [x] Fix missing meta tags 66 | - [x] Fix missing media attributes 67 | - [x] Preconnect to required origins 68 | - [x] Preload key requests 69 | - [x] Prefetch key requests 70 | - [x] Browser-level image lazy-loading for the web 71 | - [x] Lazy-load offscreen and hidden iframes 72 | - [x] Lazy-load offscreen and hidden videos 73 | - [x] Lazy-load offscreen and hidden images 74 | - [x] Lazy-load CSS background images 75 | - [x] Reduce the impact of JavaScript 76 | - [x] Defer non-critical CSS requests 77 | - [x] Defer third-party assets 78 | - [x] Add fallback `