DEV Community

Cover image for WordPress - Minify CSS, HTML, JS files using PHP
Deepak Singh
Deepak Singh

Posted on

WordPress - Minify CSS, HTML, JS files using PHP

As web developers or designers, we all have an enemy which is called Site Speed. There are so many ways to speed up your web page, we are going to discuss one of those ways. Minifying HTML, CSS & JavaScript.

Minifying means removing redundant or unnecessary data such as spacing, well-named variables, and comments.

The minified version of the code [HTML, CSS, JavaScript] is 48% smaller in general. In some cases, minification can reduce the file size by as much as 60%. For example, there's a 176 kb difference between the original and minified version of the jQuery/JavaScript library.

It reduces web page load times and bandwidth usage on websites and improves website speed and accessibility.

So, we are going to minify WordPress using a simple PHP function. Add below codes to your functions.php, if you are using a child theme add inside child-theme/functions.php.

Step One Create a Class:

class WP_HTML_Compression{
    protected $wp_compress_css = true;
    protected $wp_compress_js = true;
    protected $wp_info_comment = true;
    protected $wp_remove_comments = true;
    protected $html;
    public function __construct($html)
    {
        if (!empty($html)) {
            $this->wp_parseHTML($html);
        }
    }
    public function __toString()
    {
        return $this->html;
    }
    protected function wp_bottomComment($raw, $compressed)
    {
        $raw = strlen($raw);
        $compressed = strlen($compressed);
        $savings = ($raw - $compressed) / $raw * 100;
        $savings = round($savings, 2);
        return '<!--HTML compressed, size saved ' . $savings . '%. From ' . $raw . ' bytes, now ' . $compressed . ' bytes-->';
    }
    protected function wp_minifyHTML($html)
    {
        $pattern = '/<(?<script>script).*?<\/script\s*>|<(?<style>style).*?<\/style\s*>|<!(?<comment>--).*?-->|<(?<tag>[\/\w.:-]*)(?:".*?"|\'.*?\'|[^\'">]+)*>|(?<text>((<[^!\/\w.:-])?[^<]*)+)|/si';
        preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
        $overriding = false;
        $raw_tag = false;
        $html = '';
        foreach ($matches as $token) {
            $tag = (isset($token['tag'])) ? strtolower($token['tag']) : null;
            $content = $token[0];
            if (is_null($tag)) {
                if (!empty($token['script'])) {
                    $strip = $this->wp_compress_js;
                } else if (!empty($token['style'])) {
                    $strip = $this->wp_compress_css;
                } else if ($content == '<!--wp-html-compression no compression-->') {
                    $overriding = !$overriding;
                    continue;
                } else if ($this->wp_remove_comments) {
                    if (!$overriding && $raw_tag != 'textarea') {
                        $content = preg_replace('/<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->/s', '', $content);
                    }
                }
            } else {
                if ($tag == 'pre' || $tag == 'textarea') {
                    $raw_tag = $tag;
                } else if ($tag == '/pre' || $tag == '/textarea') {
                    $raw_tag = false;
                } else {
                    if ($raw_tag || $overriding) {
                        $strip = false;
                    } else {
                        $strip = true;
                        $content = preg_replace('/(\s+)(\w++(?<!\baction|\balt|\bcontent|\bsrc)="")/', '$1', $content);
                        $content = str_replace(' />', '/>', $content);
                    }
                }
            }
            if ($strip) {
                $content = $this->wp_removeWhiteSpace($content);
            }
            $html .= $content;
        }
        return $html;
    }
    public function wp_parseHTML($html)
    {
        $this->html = $this->wp_minifyHTML($html);
        if ($this->wp_info_comment) {
            $this->html .= "\n" . $this->wp_bottomComment($html, $this->html);
        }
    }
    protected function wp_removeWhiteSpace($str)
    {
        $str = str_replace("\t", ' ', $str);
        $str = str_replace("\n",  '', $str);
        $str = str_replace("\r",  '', $str);
        $str = str_replace(" This function requires postMessage and CORS (if the site is cross domain).", '', $str);
        while (stristr($str, '  ')) {
            $str = str_replace('  ', ' ', $str);
        }
        return $str;
    }
 }
Enter fullscreen mode Exit fullscreen mode

Step Two call the functions:

function wp_html_compression_finish($html)
 {
    return new WP_HTML_Compression($html);
 }
 function wp_wp_html_compression_start()
 {
    ob_start('wp_html_compression_finish');
 }
Enter fullscreen mode Exit fullscreen mode

Final step call Wp hook:

add_action('get_header', 'wp_wp_html_compression_start');
Enter fullscreen mode Exit fullscreen mode

All to getherL

class WP_HTML_Compression{
    protected $wp_compress_css = true;
    protected $wp_compress_js = true;
    protected $wp_info_comment = true;
    protected $wp_remove_comments = true;
    protected $html;
    public function __construct($html)
    {
        if (!empty($html)) {
            $this->wp_parseHTML($html);
        }
    }
    public function __toString()
    {
        return $this->html;
    }
    protected function wp_bottomComment($raw, $compressed)
    {
        $raw = strlen($raw);
        $compressed = strlen($compressed);
        $savings = ($raw - $compressed) / $raw * 100;
        $savings = round($savings, 2);
        return '<!--HTML compressed, size saved ' . $savings . '%. From ' . $raw . ' bytes, now ' . $compressed . ' bytes-->';
    }
    protected function wp_minifyHTML($html)
    {
        $pattern = '/<(?<script>script).*?<\/script\s*>|<(?<style>style).*?<\/style\s*>|<!(?<comment>--).*?-->|<(?<tag>[\/\w.:-]*)(?:".*?"|\'.*?\'|[^\'">]+)*>|(?<text>((<[^!\/\w.:-])?[^<]*)+)|/si';
        preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
        $overriding = false;
        $raw_tag = false;
        $html = '';
        foreach ($matches as $token) {
            $tag = (isset($token['tag'])) ? strtolower($token['tag']) : null;
            $content = $token[0];
            if (is_null($tag)) {
                if (!empty($token['script'])) {
                    $strip = $this->wp_compress_js;
                } else if (!empty($token['style'])) {
                    $strip = $this->wp_compress_css;
                } else if ($content == '<!--wp-html-compression no compression-->') {
                    $overriding = !$overriding;
                    continue;
                } else if ($this->wp_remove_comments) {
                    if (!$overriding && $raw_tag != 'textarea') {
                        $content = preg_replace('/<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->/s', '', $content);
                    }
                }
            } else {
                if ($tag == 'pre' || $tag == 'textarea') {
                    $raw_tag = $tag;
                } else if ($tag == '/pre' || $tag == '/textarea') {
                    $raw_tag = false;
                } else {
                    if ($raw_tag || $overriding) {
                        $strip = false;
                    } else {
                        $strip = true;
                        $content = preg_replace('/(\s+)(\w++(?<!\baction|\balt|\bcontent|\bsrc)="")/', '$1', $content);
                        $content = str_replace(' />', '/>', $content);
                    }
                }
            }
            if ($strip) {
                $content = $this->wp_removeWhiteSpace($content);
            }
            $html .= $content;
        }
        return $html;
    }
    public function wp_parseHTML($html)
    {
        $this->html = $this->wp_minifyHTML($html);
        if ($this->wp_info_comment) {
            $this->html .= "\n" . $this->wp_bottomComment($html, $this->html);
        }
    }
    protected function wp_removeWhiteSpace($str)
    {
        $str = str_replace("\t", ' ', $str);
        $str = str_replace("\n",  '', $str);
        $str = str_replace("\r",  '', $str);
        $str = str_replace(" This function requires postMessage and CORS (if the site is cross domain).", '', $str);
        while (stristr($str, '  ')) {
            $str = str_replace('  ', ' ', $str);
        }
        return $str;
    }
 }
 function wp_html_compression_finish($html)
 {
    return new WP_HTML_Compression($html);
 }
 function wp_wp_html_compression_start()
 {
    ob_start('wp_html_compression_finish');
 }
 add_action('get_header', 'wp_wp_html_compression_start');
Enter fullscreen mode Exit fullscreen mode

Conclusion:
Instead of using plugins to minify simply add this function to your WordPress site and see the magicπŸƒβ€β™‚οΈ.

Top comments (4)

Collapse
 
mjcoder profile image
Mohammad Javed

Nice! I'll check this out on a WP site. πŸ‘

Collapse
 
exthemes profile image
daeng sila

not working anymore... i got issue...
exthemes

Collapse
 
bungfrangki profile image
bungfrangki

just still working until today. thanks
bungfrangki

Collapse
 
notesmatic profile image
Abhijeet Pratap Singh.

Just added to the functions file. There is some significant change in loading speed.
Thanks!