Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

v2.2.0 #61

Merged
merged 4 commits into from
Apr 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
🚀 A PHP library that aims to help you concentrate on web performance optimization.

- **Package**: [@shinsenter/defer.php](https://www.npmjs.com/package/@shinsenter/defer.php)
- **Version**: 2.0
- **Version**: 2.2.0
- **Author**: Mai Nhut Tan <[email protected]>
- **Copyright**: 2021 AppSeeds <https://code.shin.company/>
- **License**: [MIT](https://raw.githubusercontent.com/shinsenter/defer.php/master/LICENSE)
@@ -125,7 +125,7 @@ $options = [
'manually_add_deferjs' => false,

// URL to defer.js javascript file.
// Default: https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.3.0/dist/defer_plus.min.js
// Default: https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.4.0/dist/defer_plus.min.js
'deferjs_src' => \AppSeeds\DeferConstant::SRC_DEFERJS_CDN,

// URL to javascript contains fixes.
110 changes: 36 additions & 74 deletions assets/helpers.js
Original file line number Diff line number Diff line change
@@ -37,28 +37,11 @@
|--------------------------------------------------------------------------
*/

// Backup jQuery.ready
var _jqueryReady;

// Common texts
var _dataLayer = 'dataLayer';
var _deferClass = 'deferjs';
var _deferPrefix = 'defer-';
var _lazied = 'lazied';
var _dataPrefix = 'data-';
var _media = 'media';

// Common class names
var _classLazied = _deferPrefix + _lazied;
var _classLoaded = _deferPrefix + 'loaded';
var _classLoading = _deferPrefix + 'loading';

// Common attributes
var _attrClassName = 'className';
var _attrDataIgnore = 'data-ignore';

// Common CSS selectors
var _queryTarget = '.' + _classLoading + ':not([' + _attrDataIgnore + ']):not([lazied])';
var _queryTarget = '.defer-loading:not([data-ignore]):not([lazied])';

/*
|--------------------------------------------------------------------------
@@ -77,49 +60,10 @@
*/

function _replaceClass(node, find, replace) {
node[_attrClassName] = (' ' + node[_attrClassName] + ' ').
replace(' ' + find + ' ', ' ' + replace + ' ').trim();
}

function _lazyload() {
defer.dom(_queryTarget, 0, _classLazied, function (node) {
_replaceClass(node, _classLoading, _classLoaded);
}, _options);

[].slice.call(document.querySelectorAll('style[defer]')).
forEach(function(node) {
node[_media] = node.getAttribute(_dataPrefix + _media) || 'all';
});
node.className = ((' ' + node.className + ' ').
replace(' ' + find + ' ', ' ') + replace).trim();
}

function _copyright(_copyText) {
if (console.log) {
console.log(_copyText || [
'Optimized by defer.php',
'(c) 2021 AppSeeds',
'Github: https://code.shin.company/defer.php'
].join('\n'));
}
}

function _boot() {
defer(_lazyload, _delay);
_replaceClass(document.documentElement, 'no-' + _deferClass, _deferClass);
_copyright();
}

/*
|--------------------------------------------------------------------------
| Define helper object
|--------------------------------------------------------------------------
*/

// Check if missing defer feature
if (!defer) {return;}

// Fallback for older versions
window.defer_helper = {'defermedia': _lazyload};

/*
|--------------------------------------------------------------------------
| Fallback for external libraries
@@ -131,29 +75,47 @@
window.ga = window.ga || function () {(window.ga.q = window.ga.q || []).push(arguments)}; window.ga.l = Number(Date());
window[_dataLayer] = window[_dataLayer] || [];

// Fake jQuery.ready, if jQuery loaded
defer(function (jquery) {
if (_jqueryReady) {
return;
}
/*
|--------------------------------------------------------------------------
| Define helper object
|--------------------------------------------------------------------------
*/

jquery = window.jQuery;
_replaceClass(
document.documentElement,
'no-deferjs',
defer ? 'deferjs' : ''
);

if (jquery && jquery.fn) {
_jqueryReady = jquery.fn.ready;
jquery.fn.ready = function (callback) {
defer(function () {_jqueryReady(callback)}, _delay);
}
}
});
// Check if missing defer feature
if (!defer) {
return;
}

/*
|--------------------------------------------------------------------------
| Main
|--------------------------------------------------------------------------
*/


_boot();
// Lazyload all style tags
defer(function() {
[].slice.call(document.querySelectorAll('style[defer]')).
forEach(defer.reveal);
}, _delay);

// Lazyload all media
defer.dom(_queryTarget, _delay, 0, function (node) {
_replaceClass(node, 'defer-loading', 'defer-loaded');
}, _options);

// Copyright
if (console.log) {
console.log([
'Optimized by defer.php',
'(c) 2021 AppSeeds',
'Github: https://code.shin.company/defer.php'
].join('\n'));
}

})(this, document, console);
6 changes: 3 additions & 3 deletions assets/styles.css
Original file line number Diff line number Diff line change
@@ -20,9 +20,9 @@ embed {
}

.defer-faded [lazied]{
transition: opacity 0.3s;
transition: opacity 0.2s;
}

.defer-faded .defer-loading:not([data-ignore]) {
opacity: 0.1!important;
.defer-faded .defer-loading {
opacity: 0.5!important;
}
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
"author": "Mai Nhut Tan <[email protected]>",
"license": "MIT",
"dependencies": {
"@shinsenter/defer.js": "^2.3.0"
"@shinsenter/defer.js": "^2.4.0"
},
"scripts": {
"cleanup": "rm -rf ./node_modules package-lock.json",
2 changes: 1 addition & 1 deletion public/helpers.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion public/lib/defer.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion public/lib/defer_plus.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion public/styles.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 18 additions & 8 deletions src/Defer.php
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ public function __construct(
];

$this->options = new DeferOptions($options ?: []);
$this->options->mergeFromRequest();

$this->fromHtml($html);
}
@@ -176,8 +177,10 @@ public function toHtml()
*/
public function optimize()
{
$dom = $this->document;
$html = $dom->root();
$dom = $this->document;
$html = $dom->root();
$debug = $this->options->debug_mode || $this->options->debug_time;
$isAmp = $dom->isAmpHtml();

// Skip if already _optimized
if ($this->_optimized || empty($html)) {
@@ -188,7 +191,7 @@ public function optimize()
$dom->optimize($this->options);

// Embed defer.js library
if (!$dom->isAmpHtml()) {
if (!$isAmp) {
$node = null;
$lib = $this->deferjs();

@@ -207,23 +210,30 @@ public function optimize()
// Optimize the script tag
if (!empty($node)) {
$node->optimize($this->options);
$lib->cleanHelperTags($this->document);
$lib->cleanHelperTags($dom);

// Debug
if ($debug) {
$node->precede($lib->getDebugJsNode($dom, 'time'));
$node->follow($lib->getDebugJsNode($dom, 'timeLog', 'defer.js finished.'));
$dom->body()->appendWith(($lib->getDebugJsNode($dom, 'timeEnd', 'body finished.')));
}

// Append helper CSS
$node->precede($lib->getHelperCssNode($this->document));
$node->precede($lib->getHelperCssNode($dom));

// Append helper script
$defer_time = $this->options->default_defer_time;
$copy = $this->options->console_copyright;
$node->follow($lib->getHelperJsNode($this->document, $defer_time, $copy));
$node->follow($lib->getHelperJsNode($dom, $defer_time, $copy));

// Append polyfill
$node->follow($lib->getPolyfillNode($this->document));
$node->follow($lib->getPolyfillNode($dom));

// Custom type for deferred script tags
if ($this->options->deferjs_type_attribute != '') {
$dom->body()->appendWith($lib->getCustomDeferTypeNode(
$this->document,
$dom,
$this->options->deferjs_type_attribute
));
}
2 changes: 1 addition & 1 deletion src/Helpers/DeferConstant.php
Original file line number Diff line number Diff line change
@@ -152,7 +152,7 @@ class DeferConstant
// -------------------------------------------------------------------------

// Source files
const SRC_DEFERJS_CDN = 'https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.3.0/dist/defer_plus.min.js';
const SRC_DEFERJS_CDN = 'https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.4.0/dist/defer_plus.min.js';
const SRC_POLYFILL_CDN = 'https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver';
const SRC_DEFERJS_FALLBACK = DEFER_PHP_ROOT . '/public/lib/defer_plus.min.js';
const SCR_DEFERJS_CACHE = DEFER_PHP_ROOT . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR;
21 changes: 21 additions & 0 deletions src/Helpers/DeferJs.php
Original file line number Diff line number Diff line change
@@ -155,6 +155,27 @@ public function getDeferJsNode(DocumentNode $dom)
]);
}

/**
* Return new <script> node with debug information
* @param mixed $method
* @param mixed $label
* @param mixed $message
* @return ElementNode
*/
public function getDebugJsNode(DocumentNode $dom, $method = 'time', $message = '')
{
$label = 'defer.js perf';

if ($message) {
$message = strtr($message, ["'" => "\\'"]);
$message = ";console.info('${label}: ${message}')";
}

$script = "try{console.${method}('${label}')${message}}finally{}";

return $dom->newNode('script', $script);
}

/**
* Return polyfill script node
*
2 changes: 0 additions & 2 deletions src/Helpers/DeferOptimizer.php
Original file line number Diff line number Diff line change
@@ -238,8 +238,6 @@ public static function optimizeElement(ElementNode &$node, DeferOptions &$option
$lazied = $resolver->lazyload();

if ($lazied) {
$node->addClass(DeferConstant::CLASS_DEFER_LOADING);

if (!empty($fallback)) {
$fallback->detach();
$node->follow($fallback);
5 changes: 3 additions & 2 deletions src/Helpers/DeferOptions.php
Original file line number Diff line number Diff line change
@@ -175,7 +175,7 @@ public function forAmp()
*/
public function mergeFromRequest($allows = [])
{
$flags = array_filter($this->defaultOptions(), function ($value) {
$flags = array_filter($this->options, function ($value) {
return is_bool($value);
});

@@ -241,7 +241,7 @@ public function getWellKnown3rd($useCache = true)
* 'manually_add_deferjs' => false,
*
* // URL to defer.js javascript file.
* // Default: https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.3.0/dist/defer_plus.min.js
* // Default: https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@2.4.0/dist/defer_plus.min.js
* 'deferjs_src' => \AppSeeds\DeferConstant::SRC_DEFERJS_CDN,
*
* // URL to javascript contains fixes.
@@ -397,6 +397,7 @@ private function defaultOptions()
'disable' => !empty($_REQUEST[DeferConstant::ARG_NODEFER]),

// Debug optimized tags (instead of optimized HTML)
'debug_time' => false,
'debug_mode' => !empty($_REQUEST[DeferConstant::ARG_DEBUG]),

// Manually add deferjs
1 change: 1 addition & 0 deletions src/Resolvers/DeferResolver.php
Original file line number Diff line number Diff line change
@@ -359,6 +359,7 @@ public function createDataAttr($attr, $placeholder = '')
if ($placeholder != $value) {
$this->node->setAttribute($attr, $placeholder);
$this->node->setAttribute($data_attr, $value);
$this->node->addClass(DeferConstant::CLASS_DEFER_LOADING);
}

return $this;
2 changes: 1 addition & 1 deletion src/Resolvers/IframeResolver.php
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ public function normalize()
}

if (empty($this->node->getAttribute('title'))) {
$this->node->setAttribute('title', basename($src ?: ''));
$this->node->setAttribute('title', basename($src ?: 'blank'));
}

// Browser-level image lazy-loading for the web
5 changes: 1 addition & 4 deletions src/Resolvers/StyleResolver.php
Original file line number Diff line number Diff line change
@@ -119,10 +119,7 @@ public function lazyload()
// Only defer when it is a CSS node
// and "onload" attribute is not provided
$media = $this->node->getAttribute('media');

if (!empty($media)) {
$this->node->setAttribute('data-media', $media);
}
$this->node->setAttribute('data-media', $media ?: 'all');

// Lazyload the style
$this->node->setAttribute('media', DeferConstant::TEMPLATE_LAZY_MEDIA_ATTR);
8 changes: 6 additions & 2 deletions tests/v2/test.php
Original file line number Diff line number Diff line change
@@ -28,11 +28,14 @@
require_once BASE . DS . 'helpers.php';

// Test request arguments
$_REQUEST['nodefer'] = 0;
$_REQUEST['debug'] = 0;
$_REQUEST['nodefer'] = 0;
$_REQUEST['debug'] = 0;
$_REQUEST['debug_time'] = 1;

// New instance
$defer = new AppSeeds\Defer([
'deferjs_src' => dirname(ROOT) . '/defer.js/dist/defer_plus.min.js',

// Library injection
'inline_deferjs' => true,
'default_defer_time' => 200,
@@ -75,6 +78,7 @@
'.header_top_icon_list img',
'.header_logo img',
'.banner img',
'.logo',
],
]);