整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

PHP的缓冲区你了解过吗

PHP的缓冲区你了解过吗

篇文章是翻译自Julien Pauli的博客文章PHP output buffer in deep,Julien是PHP源码的资深开发和维护人员。这篇文章从多个方面讲解了PHP中的输出缓冲区以及怎么使用它。输出缓冲区可能一直都是PHP开发人员的一个盲点,很多人可能只是知道这个东西,而且也知道大概怎么使用,但对于它为什么是这个样子,以及还可能是其他什么样子,可能并不了解,这篇文章可以解决你的所有困惑!

引言

大家都知道PHP中有一个名为“输出缓冲区”层(layer)的东西。这篇文章就是来讲解它到底是个什么东西的?PHP内部是怎么实现它的?以及在PHP程序中怎么使用它?这个层并不复杂,但经常会被误解,很多PHP开发者并没有完成掌握它。今天我们就一起来彻底把它搞清楚吧。

我们要讨论的东西是基于PHP 5.4(及以上版本),PHP中的OB层从5.4版开始就发生了很多变化,确切说是完全重写了,有些地方可能都不兼容PHP 5.3了。

什么是输出缓冲区?

PHP的输出流包含很多字节,通常都是程序员要PHP输出的文本,这些文本大多是echo语句或者printf()函数输出的。对于PHP中的输出缓冲区,你要知道三点内容。

第一点是任何会输出点什么东西的函数都会用到输出缓冲区,当然这说的是用PHP写的程序。如果你是编写PHP扩展,你使用的函数(C函数)可能会直接将输出写到SAPI缓冲区层,而不需要经过OB层。你可以在源文件main/php_output.h中了解到这些C函数的API文档,这个文件给我们提供了很多其他的信息,例如默认的缓冲区大小。

第二点你需要知道的是输出缓冲区层不是唯一用于缓冲输出的层,它实际上只是很多层中的一个。最后一点你要记住输出缓冲区层的行为跟你使用的SAPI(web或cli)相关,不同的SAPI可能有不同的行为。我们先通过一个图片来看看这些层的关系:

上面这张图片展示了PHP中的三种缓冲区层的逻辑关系。上面的两层就是我们通常所认识到的“输出缓冲区”,最后一个是SAPI中的输出缓冲区。这些都是PHP中的层,当输出的字节离开PHP进入计算机体系结构中的更底层时,缓冲区又会不断出现(终端缓冲区(terminal buffer),fast-cgi缓冲区,web服务器缓冲区,OS缓冲区,TCP/IP栈缓冲区。。。)。请记住一个通用原则,除了这篇文章中讨论的PHP中的情况外,一个软件的很多部分都会先保留信息,然后再把它们传递到下一部分,直到最终把这些信息传递给用户。

CLI的SAPI有点特殊,这里重点讲一下。CLI会将INI配置中的output_buffer选项强制设置为0,这表示禁用默认PHP输出缓冲区。所以在CLI中,默认情况下你要输出的东西会直接传递到SAPI层,除非你手动调用ob_()类函数。并且在CLI中,implicit_flush的值也会被设置为1。我们经常会搞不清implicit_flush的作用,源代码已说明一切:当implicit_flush被设置为打开(值为1),一旦有任何输出写入到SAPI缓冲区层,它都会立即刷新(flush,意思是把这些数据写入到更低层,并且缓冲区会被清空)。换句话说就是:任何时候当你写入任何数据到CLI SAPI中时,CLI SAPI都会立即将这些数据扔到它的下一层去,一般会是标准输出管道,write()和fflush()这两个函数就是负责干这个事情的。简单,对吧!

默认PHP输出缓冲区

如果你使用不同于CLI的SAPI,像PHP-FPM,你会用到下面三个跟缓冲区相关的INI配置选项:

output_buffering
implicit_flush
output_handler

在搞清楚这几个选项的含义之前,有一点需要先说明下,不能在运行时使用ini_set()改这几个选项的值。这些选项的值会在PHP程序启动的时候,还没有运行任何脚本之前解析,所以也许在运行时可以使用ini_set()改变它们的值,但改变后的值并不会生效,一切都已经太迟了,因为输出缓冲区层已经启动并已激活。你只能通过编辑php.ini文件或者是在执行PHP程序的时候使用-d选项才能改变它们的值。

默认情况下,PHP发行版会在php.ini中把output_buffering设置为4096个字节。如果你不使用任何php.ini文件(或者也不会在启动PHP的时候使用-d选项),它的默认值将为0,这表示禁用输出缓冲区。如果你将它的值设置为“ON”,那么默认的输出缓冲区的大小将是16kb。你可能已经猜到了,在web应用环境中对输出的内容使用缓冲区对性能有好处。默认的4k的设置是一个合适的值,这意味着你可以先写入4096个ASCII字符,然后再跟下面的SAPI层通信。并且在web应用环境中,通过socket一个字节一个字节的传输消息的方式对性能并不好。更好的方式是把所有内容一次性传输给服务器,或者至少是一块一块地传输。层与层之间的数据交换的次数越少,性能越好。你应该总是保持输出缓冲区处于可用状态,PHP会负责在请求结束后把它们中的内容传输给终端用户,你不用做任何事情。

implicit_flush已在前面谈论CLI的时候提到过。对于其他的SAPI,implicit_flush默认被设置为关闭(off),这是正确的设置,因为只要有新数据写入就刷新SAPI的做法很可能并非你所希望的。对于FastCGI协议,刷新操作(flushing)是每次写入后都发送一个FastCGI数组包(packet),如果发送数据包之前先把FastCGI的缓冲区写满会更好一些。如果你想手动刷新SAPI的缓冲区,使用PHP的flush()函数。如果你想写一次就刷新一次,你可以设置INI配置中的implicit_flush选项,或者调用一次ob_implicit_flush()函数。

output_handler是一个回调函数,它可以在缓冲区刷新之前修改缓冲区中的内容。PHP的扩展提供了很多回调函数(用户也可以自己编写回调函数,下面会讲到)。

ob_gzhandler : 使用ext/zlib压缩输出
mb_output_handler : 使用ext/mbstring转换字符编码
ob_iconv_handler : 使用ext/iconv转换字符编码
ob_tidyhandler : 使用ext/tidy整理输出的HTML文本
ob_[inflate/deflate]_handler : 使用ext/http压缩输出
ob_etaghandler : 使用ext/http自动生成HTTP的Etag

缓冲区中的内容会传递给你选择的回调函数(只能用一个)来执行内容转换的工作,所以如果你想获取PHP传输给web服务器以及用户的内容,你可以使用输出缓冲区回调。当前有一点也需要提一下,这里说的“输出”指的是消息头(headers)和消息体(body)。HTTP的消息头也是OB层的一部分。

消息头和消息体

当你使用一个输出缓冲区(无论是用户的,还是PHP的)的时候,你可能想以你希望的方式发送HTTP消息头和内容。你知道任何协议都必须在发送消息体之前发送消息头(这也是为什么叫做“头”),但是如果你使用了输出缓冲区层,那么PHP会接管这些,而不需要你操心。实际上,任何跟消息头的输出有关的PHP函数(header(),setcookie(),session_start())都使用了内部的sapi_header_op()函数,这个函数只会把内容写入到消息头缓冲区中。然后当你输出内容是,例如使用printf(),这些内容会写入到输出缓冲区(假设只有一个)。当这个输出缓冲区中的内容需要被发送时,PHP会先发送消息头,然后发送消息体。PHP为你搞定了所有的事情。如果你觉得不爽,想自己动手,那你就只有把输出缓冲区禁用掉,除此之外别无他法。

用户输出缓冲区(user output buffers)

对于用户输出缓冲区,我们先通过一个示例来看看它是怎么工作的,以及你可以用它来做什么。再强调一下,如果你想使用默认PHP输出缓冲区层的话,你不能使用CLI,因为它已禁用了这个层。下面的这个示例用的就是默认PHP输出缓冲区,使用了PHP的内部web服务器SAPI:

/* launched via php -doutput_buffering=32 -dimplicit_flush=1 -S127.0.0.1:8080 -t/var/www */
echo str_repeat('a', 31);
sleep(3);
echo 'b';
sleep(3);
echo 'c';

在这个示例中,启动PHP的时候将默认输出缓冲区的大小设置为32字节,程序运行后会先向其中写入31个字节,然后进入睡眠状态。此时屏幕是空的,什么都不会输出,跟预计一样。2秒之后睡眠结束,再写入了一个字节,这个字节填满了缓冲区,它会立即刷新自身,把里面的数据传递给SAPI层的缓冲区,因为我们将implicit_flush设置为1,所以SAPI层的缓冲区也会立即刷新到下一层。字符串’aaaaaaaaaa{31个a}b’会出现在屏幕上,然后脚本再次进入睡眠状态。2秒之后,再输出一个字节,此时缓冲区中有31个空字节,但是PHP脚本已执行完毕,所以包含这1个字节的缓冲区也会立即刷新,从而会在屏幕上输出字符串’c’。

从这个示例我们可以看到默认PHP输出缓冲区是如何工作的。我们没有调用任何跟缓冲区相关的函数,但这并不意味这它不存在,你要认识到它就存在当前程序的运行环境中(在非CLI模式中才有效)。

OK,现在开始讨论用户输出缓冲区,它通过调用ob_start()创建,我们可以创建很多这种缓冲区(至到内存耗尽为止),这些缓冲区组成一个堆栈结构,每个新建缓冲区都会堆叠到之前的缓冲区上,每当它被填满或者溢出,都会执行刷新操作,然后把其中的数据传递给下一个缓冲区。

ob_start(function($ctc) { static $a=0; return $a++ . '- ' . $ctc . "\n";}, 10);
ob_start(function($ctc) { return ucfirst($ctc); }, 3);
echo "fo";
sleep(2);
echo 'o';
sleep(2);
echo "barbazz";
sleep(2);
echo "hello";
/* 0- FooBarbazz\n 1- Hello\n */

在此我代替原作者讲解下这个示例。我们假设第一个ob_start创建的用户缓冲区为缓冲区1,第二个ob_start创建的为缓冲区2。按照栈的后进先出原则,任何输出都会先存放到缓冲区2中。

缓冲区2的大小为3个字节,所以第一个echo语句输出的字符串'fo'(2个字节)会先存放在缓冲区2中,还差一个字符,当第二echo语句输出的'o'后,缓冲区2满了,所以它会刷新(flush),在刷新之前会先调用ob_start()的回调函数,这个函数会将缓冲区内的字符串的首字母转换为大写,所以输出为'Foo'。然后它会被保存在缓冲区1中,缓冲区1的大小为10。

第三个echo语句会输出'barbazz',它还是会先放到缓冲区2中,这个字符串有7个字节,缓冲区2已经溢出了,所以它会立即刷新,调用回调函数得到的结果为'Barbazz',然后被传递到缓冲区1中。这个时候缓冲区1中保存了'FooBarbazz',10个字符,缓冲区1会刷新,同样的先会调用ob_start()的回调函数,缓冲区1的回调函数会在字符串前面添加行号,以及在尾部添加一个回车符,所以输出的第一行是'o- FooBarbazz'。

最后一个echo语句输出了字符串'hello',它大于3个字符,所以会触发缓冲区2刷新,因为此时脚本已执行完毕,所以也会立即刷新缓冲区1,最终得到的第二行输出为'1- Hello'。

输出缓冲区的内部实现

自5.4版后,整个缓冲区层都被重写了(由Michael Wallner完成)。之前的代码很垃圾,很多事情都做不了,并且有很多bug。这篇文章会给你提供更多相关信息。所以PHP 5.4才会对这部分进行重新,现在的设计更好,代码也更整洁,添加了一些新特性,跟5.3版的不兼容问题也很少。赞一个!

其中最赞的一个特性是扩展可以声明它自己的输出缓冲区回调与其他扩展提供的回调冲突。在此之前,这是不可能的,之前如果要开发使用输出缓冲区的扩展,必须先搞清楚所有其他提供了缓冲区回调的扩展可能带来的影响。

下面是一个简单的示例,它展示了怎样注册一个回调函数来将缓冲区中的字符转换为大写,这个示例的代码可能不是很好,但是足以满足我们的目的:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "main/php_output.h"
#include "php_myext.h"
static int myext_output_handler(void **nothing, php_output_context *output_context)
{
 char *dup=NULL;
 dup=estrndup(output_context->in.data, output_context->in.used);
 php_strtoupper(dup, output_context->in.used);
 output_context->out.data=dup;
 output_context->out.used=output_context->in.used;
 output_context->out.free=1;
 return SUCCESS;
}
PHP_RINIT_FUNCTION(myext)
{
 php_output_handler *handler;
 handler=php_output_handler_create_internal("myext handler", sizeof("myext handler") -1, myext_output_handler, /* PHP_OUTPUT_HANDLER_DEFAULT_SIZE */ 128, PHP_OUTPUT_HANDLER_STDFLAGS);
 php_output_handler_start(handler);
 return SUCCESS;
}
zend_module_entry myext_module_entry={
 STANDARD_MODULE_HEADER,
 "myext",
 NULL, /* Function entries */
 NULL,
 NULL, /* Module shutdown */
 PHP_RINIT(myext), /* Request init */
 NULL, /* Request shutdown */
 NULL, /* Module information */
 "0.1", /* Replace with version number for your extension */
 STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_MYEXT
ZEND_GET_MODULE(myext)
#endif

陷阱

大部分陷阱都已经揭示出来了。有一些是逻辑的问题,有一些是隐藏的。逻辑方面,最明显的是你不应该在输出缓冲区回调函数内调用任何缓冲区相关的函数,也不要在回调函数中输出任何东西。

相对不太明显的是有些PHP的内部函数也使用了输出缓冲区,它们会叠加到其他的缓冲区上,这些函数会填满自己的缓冲区然后刷新,或者是返回里面的内容。print_r()、highlight_file()和highlight_file::handle()都是这类函数。你不应该在输出缓冲区的回调函数中使用这些函数。这种行为会导致未定义的错误,或者至少得不到你期望的结果。

总结

输出层(output layer)就像一个网,它会把所有从PHP”遗漏“的输出圈起来,然后把它们保存到一个大小固定的缓冲区中。当缓冲区被填满了的时,里面的内容会刷新(写入)到下一层(如果有的话),或者是写入到下面的逻辑层:SAPI缓冲区。开发人员可以控制缓冲区的数量、大小以及在每个缓冲区层可以执行的操作(清除、刷新和删除)。这种方式非常灵活,它允许库和框架设计者可以完全控制它们自己输出的内容,并把它们放到一个全局的缓冲区中。对于输出,我们需要知道任何输出流的内容和任何HTTP消息头,PHP都会以正确的顺序发送它们。

输出缓冲区也有一个默认缓冲区,可以通过设置3个INI配置选项来控制它,它们是为了防止出现过大量的细小的写入操作,从而造成访问SAPI层过于频繁,这样网络消耗会很大,不利于性能。PHP的扩展也可以定义回调函数,然后在每个缓冲区上执行这个回调,这种应用已经有很多了,例如执行数据压缩,HTTP消息头管理以及搞很多其他的事情。

的互联网产品不仅仅在功能上要高人一筹,在性能层面也需要出类拔萃,否则金玉其外败絮其中,页面是美轮美奂了,结果首屏半天加载不出来,难免让用户乘兴而来,败兴而归。

幸运的是,前端的性能优化有诸多有迹可循的理论和方法,其中相对权威的,无疑是LightHouse。

LightHouse 是一个开源的自动化工具,它作为 Chrome 浏览器的扩展程序运行,提供一套完整的站点评分标准,我们可以依据此标准对站点进行基准测试,从而达到优化的效果。

怎么打开LightHouse?可以在Chrome浏览器开发人员工具中找到LightHouse。

要打开“开发人员工具”,请选择:
“顶部菜单→查看→开发人员→开发人员工具”
或者使用快捷键:

Mac系统上的“?+?+I”
Win系统上的“F12+Ctrl+Shift+I”。

随后点击生成报告按钮即可:

LightHouse评分大体上有四大指标,分别为:性能、无障碍、最佳做法以及SEO。

性能指标(Performance)

性能指标里又分为六个小指标:

Largest Contentful Paint 【简称LCP: 最大内容渲染】
FCP最大内容渲染时间标记了渲染出最大文本或图片的时间。
Total Blocking Time 【简称TBT: 总阻塞时间】
TBT测量了FCP(首次内容渲染)和TTI(可交互时间)之间的总耗时。TTI可能会被主线程阻塞以至于无法及时响应用户。大于50ms的任务称为长任务,当任意长任务出现时,主线程则称为被阻塞状态。由于浏览器不会打断正在进行中的长任务,所以,如果用户在执行长任务时和页面有交互事件时,浏览器必须等到该长任务完成才能响应。TBT计算的是在FCP到TTI之间所有长任务时间内总和。
First Contentful Paint 【简称FCP: 首次内容渲染】

FCP测量了从页面开始加载到页面任意部分的内容渲染到屏幕上。

Speed Index 【简称SI: 速度指数】
SI速度指数表明了网页内容的可见填充速度。lighthouse首先捕获页面加载的视屏,然后对比帧与帧之间视觉效果变化(通过计算结构相似指数SSMI来比较)。
Time to Interactive 【简称TTI: 可交互时间】
可交互时间是指网页需要多长时间才能提供完整交互功能。TTI测量了从页面开始加载到页面的主要附属资源加载完毕,并且可以足够快速回应用户输入的所用时间。
Cumulative Layout Shift 【简称CLS: 累积布局偏移】
CLS累积布局偏移旨在测量可见元素在视口内的移动情况。CLS值越小越好。

性能优化手段

有哪些手段可以提高这些性能指标?

首先需要优化的是页面“资源”,这里的资源指的是页面中加载的一切元素,包含但不限于:js文件、css文件、图片、视频等。

对于js文件来说,首先要做的是业务分拆,不同页面只加载对应需要的文件,并且做到单页面只加载一个js文件,减少Http请求数,多余的文件要做合并压缩操作,但其实这里有一个基础问题,就是如果js文件本身就很庞大,压缩比例再高,也是杯水车薪,举个例子,一般情况下Jquery官方的压缩版就已经高达80kb左右了,这样的体积很难有再次压缩的优化空间,所以还不如直接摒弃Jquery,换成别的功能上可以替换的库,比如zepto,后者的体积只有26kb,是前者的四分之一。随后进行压缩合并操作,首先安装:

npm install uglify-js -g

以本站为例,业务上用到的js库分别为zepto.min.js、my.js、lazyload.min.js、wordcloud2.min.js iconfont.js,将这五个js文件进行合并压缩:

uglifyjs zepto.min.js my.js lazyload.min.js wordcloud2.min.js iconfont.js -o ./1-min.js

如此,最后得到一个体积为59kb的1-min.js文件,当然这是业务层面的压缩,还可以通过修改服务器进行gzip压缩:

location ~ .*.(jpg|gif|png|bmp|js|css)$ {
                gzip on;
                gzip_http_version 1.1;
                gzip_comp_level 3;
                gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss text/javascript application/x-httpd-php image/jpeg image/gif image/png image/x-ms-bmp;
                }

加载方式上,尽量使用预加载:

<link rel="preload" as="script" href="1-min.js" />

同时,对于一些站外js比如广告,或者一些js特效,我们可以对其进行延时加载的操作,即首屏加载好之后,再加载这些逻辑:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
(function() {
var done=false;
var script=document.createElement('script');
script.async=true;
script.type='text/javascript';
script.src='//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';

var createScript=setTimeout(
function(){
document.getElementsByTagName('HEAD').item(0).appendChild(script);
WordCloud(canvas, options);
}, 7000
);

script.onreadystatechange=script.onload=function(e) {
if (!done && (!this.readyState || this.readyState=='loaded' || this.readyState=='complete')) {
(adsbygoogle=window.adsbygoogle || []).push({});
}
};
})();
</script>

上面的逻辑就是首屏完成7秒后再加载Google广告和标签云特效。

对于css文件的处理,原理和js文件差不多,宗旨也是分拆,缩小体积,并且压缩:

cssMinifier(['./bootstrap.min.css', '../js/kindeditor/plugins/code/prettify_dark.css', './style.css'], './tidy_min.css');

优化后,得到体积为17kb的tidy_min.css文件。

对于图片文件,不仅是首图,所有图片最好都采用新的图片格式Webp,用以减少其体积,具体操作方法请移步:石火电光追风逐日|前端优化之次时代图片压缩格式WebP的项目级躬身实践(Python3 PIL+Nginx) 。对于特定的图片,比如Logo,使用svg格式图片,请移步:Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)

同时,对于图片一律声明宽高属性,并且使用支持lazyload.js组件推迟对屏幕外图片的加载。

使用viewport标签加快移动端的载入速度:

<meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="applicable-device" content="pc,mobile"/>

无障碍(Accessibility)

访问无障碍检测所有用户是否都能有效地访问内容并浏览网站,无障碍性的每个指标项测试结果为pass或者fail,与性能指标项的计算方式不同,当页面只是部分通过某项指标时,页面的这项指标将不会得分。例如,如果页面中的一些元素有屏幕阅读器友好的命名,而其他的元素没有,那么这个页面的 screenreader-friendly-names 指标项得分为0。

一般情况下,优化无障碍其实是对于站点标签的优化,比如页面元素是否具备title标签、title元素是否按降序排列、是否声明了页面语言类型、元素是否具备alt标签等等,值得一提的是,页面对比度也是无障碍评分重要的一环,假如背景色是white,那么前景色最好选择高对比度的颜色,比如black。

最佳做法(Best Practice)

最佳做法检测可以改善网页的代码健康状况的一些最佳做法,评分的分值由相关指标的加权平均值计算而来。

最佳做法指标我们可以理解为就是站点安全性的指标,多数情况下,需要保证协议为HTTPS,同时要开启CSP网页安全政策防止XSS攻击。

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。

开启方法:

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

搜索引擎优化(SEO)

搜索引擎优化检测搜索引擎对网页内容的理解程度是怎样的,评分的分值由相关指标的加权平均值计算而来。

说白了,就是站点页面是否适合搜素引擎蜘蛛的抓取以及收录,以本站为例,搜索引擎需要的标签如下:

<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="applicable-device" content="pc,mobile"/>
    <title>当我们进行性能优化,我们在优化什么(LightHouse优化实操)-刘悦</title>
    <meta name="description" content="好的互联网产品不仅仅在功能上要高人一筹,在性能层面也需要出类拔萃,否则金玉其外败絮其中,页面是美轮美奂了,结果首屏半天加载不出来,难免让用户乘兴而来,败兴而归。幸运的是,前端的性能优化有诸多有迹可循的理论和方法,其中相对权威的,无疑是LightHouse。LightHouse是一个开源的自动化工具,它作为Chrome浏览器的扩展程序运行,提供一套完整的站点评分标准,我们可以依">
    <meta content="刘悦" name="Author">
    <link rel="canonical" href="https://v3u.cn/a_id_214"/>
    <link rel="miphtml" href="https://v3u.cn/mipa_id_214">
    <link rel="stylesheet" href="/v3u/Public/css/tidy_min.css?v=11"/>
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
    <link rel="icon" href="favicon.ico" type="image/x-icon"/>
    <link rel="stylesheet" href="/v3u/Public/css/share.min.css?v=1">
</head>

包括页面标题、描述、作者、页面唯一标识等等元素。

当我们完成上面这些指标的优化之后,就可以,坐下来,欣赏这紫禁烟花一万重了:

正是:东风夜放花千树,更吹落,星如雨。

结语

前端的性能分析和优化方式,无论是传统性能还是感官性能完全可以根据LightHouse按图索骥。过程中可以针对某些指标进行一定的取舍,虽然本站在LightHouse的优化实践中取得了一定的效果,但路漫漫其修远兮,吾将上下而求索。

于开发人员来说,利用一款好用的代码编辑器,可以起到事半功倍的作用。本人归纳整理了开发人员比较常用的代码编辑器,希望大家喜欢!

1) chocolatapp

这款代码编辑器,是最新出现的一个版本。它属于Mac系统文本编辑器,不仅具有原生的Cocoa和强大文本编辑功能。这款代码编辑器支持多种编辑语言,且支持关键字高亮显示、窗口分割、标签页、色彩主题等功能。

2)webide

w3cschool开发的这款代码编辑器功能相当丰富,不仅代码可以自动提示,还有适合各种场景下使用的自定义字体。运用这个编辑器,还可以多光标编辑、支持多标签、维持多个文档、在线实时预览。很多程序员爱用这一款编辑器,最主要的原因就是它有自动补全功能,写代码健步如飞。


3) aptana

这个开发工具主要用于Ajax开发,功能也很强大。Aptana近来经开发人员重新设计而焕发了新的活力,同以前相比,现在定制功能更强大,也更加快速。

4) barebones

这款代码编辑器,不知道大家有没有用过,小编没用过,对相关功能不太清楚。

5) Coda

Coda是面向Web开发人员、网页设计师的一款优秀Mac下编辑器软件。Coda不但轻巧,而且功能强大。它整合了终端、文字编辑器、CSS编辑器、内容发布(结合了Transmit的FTP Client功能)等整个Web开发流程所需工具。与Textmate、BBEdit有一拼。

6) editplus

7) emacs

Emacs即Editor MACroS(宏编辑器),是一种强大的文本编辑器。Emacs使用了Emacs Lisp这种有着极强扩展性的编程语言(它的核心是一个Emacs Lisp解释器),并实现了文本编辑支持等的扩展。

8) espresso

9) komodo-ide

10) e-texteditor

E-TextEditor是一款新概念的窗口文本编辑软件,号称Windows平台的TextMate,带有强大文字编辑功能,和一些独立的特性。支持多种语言文字,可以输入大量和实时性通信信息。图形库用的是wxWindows。

11) notepad++

Notepad++ 是一款免费开源的跨平台的代码编辑器,基于GPL许可证。它支持包括中文在内的多国语言,功能强大,除了可以用来制作一般的纯文字说明文件,也十分适合当作撰写电脑程序的编辑器。Notepad++不仅可以实现语法高亮显示,也有语法折叠功能,并且支持宏以及扩充基本功能的外挂模组。

12) macromates

13) textpad

一款强大的可以替代Notepad(记事本)的编辑器。可用于网页编辑或者作为编程IDE。

14) netbeans

15) visual-web-developer-express

16) jetbrains

JetBrains的IDEA是Java开发最好用的IDE,没有之一。

17)CleverCSS

18)Sass

19)Sajax

20)Komodo Edit for Perl, Python, Tcl, PHP, Ruby, Javascript

21)CSSTidy

22)Less

23)About Markup Generator

24)Haml

25)XCSS

26)Zen Coding — a new way of writing HTML and CSS code

27)Vim

28)Layer Styles

这是一个HTML5应用。利用它,开发者可以更直观地编写CSS3代码。尤其看来,这个工具相当好用。

29)Spritemapper

Spritemapper应用可将多张小图片合并为一张图片,从而减少服务器的Http连接数,对提高网站的吞吐量有一定帮助,同时它还会每个图像切片产生相应的CSS定位。

30)Tridiv

免费Web应用Tridiv可以很容易地创建出漂亮的3D图形。使用该应用,我们可以创建4种不同的形状,包括长方体、金字塔、圆柱体和棱柱体,同时也可以对它们进行旋转并改变大小。

31)Responsive Web CSS

Responsive Web CSS是基于Web的一个工具,可用来创建响应式布局框架。你可以很容易地添加任意数量的页面和div,并定义它们的百分比宽度。

32)CSS Form Code Maker

CSS Form Code Maker主要用来为表格创建美观的外观布局。

33)Buttons

Buttons为CSS库,可用来创建高度定制化、灵活的现代Web按钮。

上面介绍的33个代码编辑器,也不知道有没有你最爱用的一款。当然,每个人的习惯不同,兴趣爱好也不同,喜欢使用的代码编辑器也不同,如果你有好的代码编辑器推荐,欢迎来留言哦!