如何在 laravel 5 中压缩 HTML
Posted
技术标签:
【中文标题】如何在 laravel 5 中压缩 HTML【英文标题】:How do I compress HTML in laravel 5 【发布时间】:2015-05-25 15:04:48 【问题描述】:在 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])/" => '$1',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
"/ +/" => ' ',
);
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
);
请问我如何在 Laravel 5 中完成这项工作。
或
如果有的话,请在 laravel 5 中提供一种更好的压缩 HTML 的方法。 提前致谢。
注意:我不希望使用任何 laravel 包来压缩 html,只需要一个简单的代码即可完成工作而不会影响性能。
【问题讨论】:
我知道你说过你不想要一个 pacakge - 但github.com/GrahamCampbell/Laravel-HTMLMin 是完美的解决方案。与您自己做的相比,它不会“扼杀性能”。 我建议您不要尝试根本 -pre
元素不是唯一可能影响空格的元素,而且在 @987654324 内@/input
或者基本上在 any 元素中,如果它稍后通过 CSS (white-space
) 格式化。在将输出发送到客户端之前只需 GZip 输出,这比弄乱 HTML 代码本身要有效得多。
@cbroe 如何使用 GZip?任何工作示例
【参考方案1】:
我用非常简单的代码做到了。 示例: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);
?>
【讨论】:
【参考方案2】:以防万一您手动渲染视图:
echo view('example.site')->render(function($view, $content)
return preg_replace(
['/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s'],
['>', '<', '\\1'],
$content
);
);
【讨论】:
【参考方案3】:在我看来,这个包是更好的选择renatomarinho/laravel-page-speed
【讨论】:
【参考方案4】:我创建了一个 webpack 插件来解决同样的问题。MinifyHtmlWebpackPlugin
使用 npm 安装插件:
$ npm install minify-html-webpack-plugin --save-dev
对于 Laravel Mix 用户
将下面的 sn-ps 粘贴到 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 构建期间缩小所有视图文件。
【讨论】:
【参考方案5】:这几乎是Vahid's 答案的副本,但它解决了两个问题。
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
注意:在给出这个答案的时候,我无法找到一个好的正则表达式来匹配单行 cmets 而不会出现复杂情况,或者更确切地说,只忽略带有单行注释的行上的换行符,所以我希望更好的解决方法。
这是修改后的版本。
<?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])/" => '$1',
"/\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;
编辑
使用中间件压缩每个请求的输出确实是个坏主意,我建议您查看this solution by Jokerius
【讨论】:
【参考方案6】:为了方便压缩,我构建了自己的 laravel 模块。该模块将在发送到客户端(浏览器)之前压缩所有最终的 html 输出。
您还可以使用.env
文件一次定位多个环境。
有关如何安装和配置的更多详细信息将found here
【讨论】:
【参考方案7】:完整代码如下(启用自定义 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])/" => '$1',
"/\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
标头。
享受它... :).. .
【讨论】:
(index):1 Uncaught SyntaxError: Unexpected end of input jquery not working after that @Rahul Tathod 这个中间件只会压缩 HTML,并启用 GZip。这两个压缩不会影响 Jquery,或 CSS,JS 文件。如果有任何问题,你应该找到根本原因。【参考方案8】:在中间件中缩小 html 并不是很好的解决方案,因为您可能会在其上花费大量 CPU 时间,并且它会在每个请求上运行。
最好使用 htmlmin 包(https://github.com/HTMLMin/Laravel-HTMLMin):
composer require htmlmin/htmlmin
php artisan vendor:publish
在刀片模板级别缩小 HTML 并将其缓存在存储中应该会更有效。
【讨论】:
如果您的模板中存在需要在每个请求中考虑的变量,这仍然有效吗?甚至是取决于条件的整个区块? 2021更新:这个包好像有很多bug,好像没有维护。【参考方案9】:这是最好的方法..我们不需要使用 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])/" => '$1',
"/\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;
【讨论】:
代码 sn-p 似乎没有运行。【参考方案10】:在 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;
【讨论】:
不错。我该如何使用它?每个请求都运行这个? 是的,你会在每个 http 请求上运行它。您可以通过在app/Http/Kernel.php
中添加您的课程来全局注册它以上是关于如何在 laravel 5 中压缩 HTML的主要内容,如果未能解决你的问题,请参考以下文章