如何在 laravel 5 中压缩 HTML
How do I compress HTML in laravel 5
在 Laravel 4.0 中,我使用下面的代码将 HTML laravel 响应输出压缩到浏览器,但是它在 laravel 5 中不起作用。
App::after(function($request, $response)
{
if($response instanceof Illuminate\Http\Response)
{
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
}
});
请问我如何在 Laravel 5 中完成这项工作。
或
如果有的话,请在 laravel 5 中提供更好的压缩 HTML 的方法。
提前致谢。
注意:我不想使用任何 laravel 包来压缩 html,只需要一个简单的代码来完成工作而不会降低性能。
在 Larvel 5 中推荐的方法是将函数重写为 middleware。如文档中所述:
..此中间件将在 请求由应用程序处理后 执行其任务:
<?php namespace App\Http\Middleware;
class AfterMiddleware implements Middleware {
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}
完整代码是这样的(启用自定义 GZip):
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); // If you like to enable GZip, too!
return $response;
}
}
请检查您的浏览器网络检查器 Content-Length
header before/after 是否实施此代码。
尽情享受吧……:)..
这几乎是 答案的副本,但它解决了两个问题。
1) 它检查响应是否为 BinaryFileResponse
,因为任何修改此类响应的尝试都会引发异常。
2) 它保留了换行符,因为完全消除换行符会导致带有单行注释的行上出现错误的 Javascript 代码。
例如下面的代码
var a; //This is a variable
var b; //This will be commented out
会变成
var a; //This is a variable var b; //This will be commented out
注意:在回答这个问题时,我无法找到一个好的正则表达式来匹配单行注释而不会出现并发症,或者更确切地说,忽略只有单行注释的行上的换行符,所以我希望有更好的解决方法。
这是修改后的版本。
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse) {
return $response;
} else {
$buffer = $response->getContent();
if (strpos($buffer, '<pre>') !== false) {
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
} else {
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n+/" => "\n",
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); //enable GZip, too!
return $response;
}
}
}
编辑
使用中间件压缩每个请求的输出确实是一个坏主意,我建议您查看
这是最好的方法..我们不需要使用 laravel 包。谢谢..
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); // If you like to enable GZip, too!
return $response;
}
}
在中间件中缩小 html 并不是很好的解决方案,因为您可能会在上面花费大量 CPU 时间,而且它会在每次请求时运行。
最好使用 htmlmin 包 ( https://github.com/HTMLMin/Laravel-HTMLMin ):
composer require htmlmin/htmlmin
php artisan vendor:publish
在 blade 模板级别缩小 HTML 并将其缓存在存储中应该更有效。
为了方便压缩,我构建了自己的 laravel 模块。该模块将在发送到客户端(浏览器)之前压缩所有最终的 html 输出。
您还可以使用 .env
文件一次定位多个环境。
有关如何安装和配置的更多详细信息将 found here
我创建了一个 webpack 插件来解决同样的问题。MinifyHtmlWebpackPlugin
使用 npm 安装插件:
$ npm install minify-html-webpack-plugin --save-dev
对于 Laravel 混合用户
将以下片段粘贴到 mix.js 文件中。
const MinifyHtmlWebpackPlugin = require('minify-html-webpack-plugin');
const mix = require('laravel-mix');
mix.webpackConfig({
plugins: [
new MinifyHtmlWebpackPlugin({
src: './storage/framework/views',
ignoreFileNameRegex: /\.(gitignore)$/,
rules: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
minifyJS: true,
}
})
]
});
它将在 Webpack 构建期间缩小所有视图文件。
我认为这个包是更好的选择renatomarinho/laravel-page-speed
以防万一您手动渲染视图:
echo view('example.site')->render(function($view, $content) {
return preg_replace(
['/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s'],
['>', '<', '\1'],
$content
); }
);
我用非常简单的代码做到了。
示例:welcome.blade.php
在页面开头添加以下代码
<?php ob_start('compress_page');?>
在页面末尾添加如下代码:
<?php
ob_end_flush();
function compress_page($buffer) {
$search = array("/>[[:space:]]+/", "/[[:space:]]+</");
$replace = array(">","<");
return preg_replace($search, $replace, $buffer);
}?>
整页代码示例:
<?php ob_start('compress_page');?>
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Raleway', sans-serif;
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.content {
text-align: center;
}
.title {
font-size: 84px;
}
.links > a {
color: #636b6f;
padding: 0 25px;
font-size: 12px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}
.m-b-md {
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ route('login') }}">Login</a>
<a href="{{ route('register') }}">Register</a>
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel
</div>
<div class="links">
<a href="https://laravel.com/docs">Documentation</a>
<a href="https://laracasts.com">Laracasts</a>
<a href="https://laravel-news.com">News</a>
<a href="https://forge.laravel.com">Forge</a>
<a href="https://github.com/laravel/laravel">GitHub</a>
</div>
</div>
</div>
</body>
</html>
<?php
ob_end_flush();
function compress_page($buffer) {
$search = array("/>[[:space:]]+/", "/[[:space:]]+</");
$replace = array(">","<");
return preg_replace($search, $replace, $buffer);
}?>
在 Laravel 4.0 中,我使用下面的代码将 HTML laravel 响应输出压缩到浏览器,但是它在 laravel 5 中不起作用。
App::after(function($request, $response)
{
if($response instanceof Illuminate\Http\Response)
{
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
}
});
请问我如何在 Laravel 5 中完成这项工作。
或
如果有的话,请在 laravel 5 中提供更好的压缩 HTML 的方法。 提前致谢。
注意:我不想使用任何 laravel 包来压缩 html,只需要一个简单的代码来完成工作而不会降低性能。
在 Larvel 5 中推荐的方法是将函数重写为 middleware。如文档中所述:
..此中间件将在 请求由应用程序处理后 执行其任务:
<?php namespace App\Http\Middleware;
class AfterMiddleware implements Middleware {
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}
完整代码是这样的(启用自定义 GZip):
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); // If you like to enable GZip, too!
return $response;
}
}
请检查您的浏览器网络检查器 Content-Length
header before/after 是否实施此代码。
尽情享受吧……:)..
这几乎是
1) 它检查响应是否为 BinaryFileResponse
,因为任何修改此类响应的尝试都会引发异常。
2) 它保留了换行符,因为完全消除换行符会导致带有单行注释的行上出现错误的 Javascript 代码。
例如下面的代码
var a; //This is a variable
var b; //This will be commented out
会变成
var a; //This is a variable var b; //This will be commented out
注意:在回答这个问题时,我无法找到一个好的正则表达式来匹配单行注释而不会出现并发症,或者更确切地说,忽略只有单行注释的行上的换行符,所以我希望有更好的解决方法。
这是修改后的版本。
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse) {
return $response;
} else {
$buffer = $response->getContent();
if (strpos($buffer, '<pre>') !== false) {
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
} else {
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n+/" => "\n",
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); //enable GZip, too!
return $response;
}
}
}
编辑
使用中间件压缩每个请求的输出确实是一个坏主意,我建议您查看
这是最好的方法..我们不需要使用 laravel 包。谢谢..
<?php
namespace App\Http\Middleware;
use Closure;
class OptimizeMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$buffer = $response->getContent();
if(strpos($buffer,'<pre>') !== false)
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
);
}
else
{
$replace = array(
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
ini_set('zlib.output_compression', 'On'); // If you like to enable GZip, too!
return $response;
}
}
在中间件中缩小 html 并不是很好的解决方案,因为您可能会在上面花费大量 CPU 时间,而且它会在每次请求时运行。
最好使用 htmlmin 包 ( https://github.com/HTMLMin/Laravel-HTMLMin ):
composer require htmlmin/htmlmin
php artisan vendor:publish
在 blade 模板级别缩小 HTML 并将其缓存在存储中应该更有效。
为了方便压缩,我构建了自己的 laravel 模块。该模块将在发送到客户端(浏览器)之前压缩所有最终的 html 输出。
您还可以使用 .env
文件一次定位多个环境。
有关如何安装和配置的更多详细信息将 found here
我创建了一个 webpack 插件来解决同样的问题。MinifyHtmlWebpackPlugin
使用 npm 安装插件:
$ npm install minify-html-webpack-plugin --save-dev
对于 Laravel 混合用户
将以下片段粘贴到 mix.js 文件中。
const MinifyHtmlWebpackPlugin = require('minify-html-webpack-plugin');
const mix = require('laravel-mix');
mix.webpackConfig({
plugins: [
new MinifyHtmlWebpackPlugin({
src: './storage/framework/views',
ignoreFileNameRegex: /\.(gitignore)$/,
rules: {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
minifyJS: true,
}
})
]
});
它将在 Webpack 构建期间缩小所有视图文件。
我认为这个包是更好的选择renatomarinho/laravel-page-speed
以防万一您手动渲染视图:
echo view('example.site')->render(function($view, $content) {
return preg_replace(
['/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s'],
['>', '<', '\1'],
$content
); }
);
我用非常简单的代码做到了。 示例:welcome.blade.php
在页面开头添加以下代码
<?php ob_start('compress_page');?>
在页面末尾添加如下代码:
<?php
ob_end_flush();
function compress_page($buffer) {
$search = array("/>[[:space:]]+/", "/[[:space:]]+</");
$replace = array(">","<");
return preg_replace($search, $replace, $buffer);
}?>
整页代码示例:
<?php ob_start('compress_page');?>
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Raleway', sans-serif;
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.content {
text-align: center;
}
.title {
font-size: 84px;
}
.links > a {
color: #636b6f;
padding: 0 25px;
font-size: 12px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}
.m-b-md {
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@auth
<a href="{{ url('/home') }}">Home</a>
@else
<a href="{{ route('login') }}">Login</a>
<a href="{{ route('register') }}">Register</a>
@endauth
</div>
@endif
<div class="content">
<div class="title m-b-md">
Laravel
</div>
<div class="links">
<a href="https://laravel.com/docs">Documentation</a>
<a href="https://laracasts.com">Laracasts</a>
<a href="https://laravel-news.com">News</a>
<a href="https://forge.laravel.com">Forge</a>
<a href="https://github.com/laravel/laravel">GitHub</a>
</div>
</div>
</div>
</body>
</html>
<?php
ob_end_flush();
function compress_page($buffer) {
$search = array("/>[[:space:]]+/", "/[[:space:]]+</");
$replace = array(">","<");
return preg_replace($search, $replace, $buffer);
}?>