web 页面内容优化管理与性能技巧

回想一下,以前我们不得不花费大量时间去优化页面内容(图片、CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪存文件,里面包含的有视频或者图片。然而,随着移动开发的兴起,我们又回到了过去的窘状。网站优化是十分重要的,需要下载的内容少,反应速度快,就能使我们加载应用程序更快速。

  图片:控制在合适的尺寸大小

  很多时候我们在不同的网站使用同样的图像,例如一个网上商店,所有产品 都 有一个概览图片。打个比方,有三个页面描述产品,第一个页面显示产品清单,第二个页面显示产品细节图,第三个页面显示产品原始大小图。因此,我们需要三种 不同大小的图片。如果使用一个文件放到不同的三个页面上,那么浏览器会自动加载完整大小的图片,就连清单页也是,实际上清单页只需要200×200尺寸的 图片。如果原始文件大小在1MB左右,每页上有十个产品介绍,那么用户就要下载10MB大小的资源。这样做效果不好。如果可以的话,尽量为你的网站不同位 置分配不同的图像文件,那么就可以让用户少下载资源。把屏幕分辨率因素也考虑进去也是很好的。如果有人用iPhone打开你的网站页面,手机上不需要显示 电脑上那么大尺寸的图片,只需适应手机屏幕的大小就可以了。通过CSS Media Queries,你就能将图像压缩到较小尺寸发送出去了:

?
1
2
3
4
5
6
7
@media only screen
and (min-device-width : 320px )
and (max-device-width : 480px ) {
     .header {
         background-image : url (../images/background_ 400 x 200 .jpg);
     }
}

 压缩

  传送图像的时候单单控制适当的尺寸往往是不够的。不少文件格式在不失真的前提下可以被压缩很多。有一类应用程序可以达到这个效果。比如Photoshop有个很好的功能叫做Save for Web and Devices:

web页面内容优化管理与性能技巧

  在此对话框中有多个选项,其中最重要的是质量,将其设计为80%左右,就能显著减少文件大小了。当然,你还可以使用代码来压缩文件,但我个人偏向于使用PS。下面是用PHP编写的一个简单的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function compressImage( $source , $destination , $quality ) {
     $info = getimagesize ( $source );
     switch ( $info [ 'mime' ]) {
         case "image/jpeg" :
             $image = imagecreatefromjpeg( $source );
             imagejpeg( $image , $destination , $quality );
         break ;
         case "image/gif" :
             $image = imagecreatefromgif( $source );
             imagegif( $image , $destination , $quality );
         break ;
         case "image/png" :
             $image = imagecreatefrompng( $source );
             imagepng( $image , $destination , $quality );
         break ;
     }
}
compressImage( 'source.png' , 'destination.png' , 85);

 Sprite

  增加应用程序性能的方法之一,是减少到服务器的请求数。每一个新图像代表一个请求数。有一个办法是将几个图片合并成一个,合并之后的图像叫做一个sprite,在CSS中改变背景层的位置,就能准确的把特定部分的图像显示出来。比如Twitter Bootstrap利用sprites引导内部图标:

web页面内容优化管理与性能技巧

  在CSS中,你可以参照以下方式,显示你喜欢的sprite部分: 

?
1
2
3
4
.icon-edit {
     background-image : url ( "../img/glyphicons-halflings-white.png" );
     background-position : -96px -72px ;
}

 超高速缓存

  浏览器超高速缓存十分好用。尽管有时在开发过程中会导致一些非常有趣的情况,但它确实有助于提高你的网站的性能。所有浏览器的超高速缓存下来的内容包括图片、JavaScript或者CSS。有几种方法可以控制缓存,建议你阅读相关文章。一般情况下,你可以通过设置标题,达到控制效果:

?
1
2
3
4
$expire = 60 * 60 * 24 * 1; // seconds, minutes, hours, days
header( 'Cache-Control: maxage=' . $expire );
header( 'Expires: ' . gmdate ( 'D, d M Y H:i:s' , time() + $expire ). ' GMT' );
header( 'Last-Modified: ' . gmdate ( 'D, d M Y H:i:s' ). ' GMT' );

 预读取

  HTML 5每天都在进步,有一个很好的功能叫做预读取,它让浏览器提前下载你马上需要用到的资源:

?
1
< link rel = "prefetch" href = "/images/background.jpg" >

   数据URI方案/内联图像

  几年前我曾开发了一个简单的网页,只包含一个HTML文件夹,但当然里面应该还包括一些我需要的图像。数据URI方案帮助我解决了问题。我们的想法是将图像转换成一个base64编码的字符串,并将其放置在src属性中的img标签里,例如:

?
1
< img src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt = "Red dot" >

  通过这种方法,你的图像实际上在HTML中并保存了一个HTTP请求。你的图像越大的话,字符串就越长。下面是一个简单的PHP脚本图像转换为base64字符串的实例:

?
1
2
3
4
5
6
7
$picture = fread ( $fp , filesize ( $file ));
fclose( $fp );
// base64 encode the binary data, then break it
// into chunks according to RFC 2045 semantics
$base64 = base64_encode ( $picture );
$tag = '<img src="https://img-blog.csdnimg.cn/2022010708174951845.jpg' . $base64 . '" alt="" />' ;
$css = 'url(https://img-blog.csdnimg.cn/2022010708174951845.jpg' . str_replace ( "\n" , "" , $base64 ). '); ' ;

  有些情况下这种方法挺好用的,但请注意,在IE浏览器中无法很好的兼容。

 CSS

  我觉得编写CSS就如同写代码。你同样需要组织模式,定义不同板块和关系。所以我认为CSS管理非常重要。应用程序的每一部分应该有对应的模式,并很好的独 立。不同的内容存储在不同的文件夹可以有效的管理,但同样也存在问题。使用@import状态这种方法不好用,因为每用一个@import都意味着一个新 的请求发送到服务器。如果你有20个不同的.css文件,就相当于浏览器要发送20个请求。浏览器在渲染/下载所有内容之前不会显示页面。如果你 的.css文件丢失了或者太大,浏览器加载页面的时间就会大大延长。

  使用CSS预处理器

  CSS预处理器可以解决上述问题。你 同样可以保存不同的文件夹,预处理器可以将这些散文件夹最终生成一个.css文件。实际上提供了一系列非常帮的功能比如变量、嵌套块、混入和继承。代码看 上去类似CSS,但实际上被很好的统一格式与结构了。有几种好用的预处理器值得体验——SassLESSStylus。下面是用LESS编写的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.position(@ top : 0 , @ left : 0 ) {
     position : absolute ;
     top : @ top ;
     left : @ left ;
     text-align : left ;
     font-size : 24px ;
}
.header {
     .position( 20px , 30px );
     .tips {
         .position( 10px , -20px );
     }
     .logo {
         .position( 10px , 20px ); 
     }
}

  运行生成:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.header {
     position : absolute ;
     top : 20px ;
     left : 30px ;
     text-align : left ;
     font-size : 24px ;
}
.header .tips {
     position : absolute ;
     top : 10px ;
     left : -20px ;
     text-align : left ;
     font-size : 24px ;
}
.header .logo {
     position : absolute ;
     top : 10px ;
     left : 20px ;
     text-align : left ;
     font-size : 24px ;
}

  又如你想再创建一个同样样式的按钮,但是颜色不同,你可以这样做:

?
1
2
3
4
5
6
7
8
9
10
.button {
     border : solid 1px #000 ;
     padding : 10px ;
     background : #9f0 ;
     color : #0029FF ;
}
.active-button {
     .button();
     color : #FFF ;
}

 高效的CSS

  通常情况下,大多数开发人员没有考虑过CSS效率问题。CSS的效率反映在页面渲染上,如果模式低效,应用程序在浏览器上运行就会很慢。有趣的是浏览器解析CSS选择器是从右到左的。所以以下代码更不一点效率都没有:

?
1
2
3
4
body ul li a {
     color : #F000 ;
     text-decoration : none ;
}

  这是因为该引擎首先识别所有的<a>标签,评估每个母元素,最终收集到所需模式。你要知道,为了提高效率,选择器有个 先后排序:ID、类、标签及其一般。这意味着一个带有id的元素集比只带有标签选择器的元素更快的被渲染。当然,在所有DOM树元素都加上id是没有意义 的,但你应该特定检查代码,把可能加id的地方都加上。比如你可以按照以下方式做:

?
1
2
3
ul #navigation li {
     background : #ff0232 ;
}

   .content元素是body tag的子集,实际上所有元素都是body tag的子集。关于这个话题有两个有用的链接:developers.google.comcss-tricks.com

  文件大小

  正如我们上面提到的,代码越少越好,因为浏览器在加载CSS之前不渲染页面。下面几个技巧可供缩小文件大小:

  把类似的行

?
1
2
3
4
5
6
.header {
     font-size : 24px ;
}
.content {
     font-size : 24px ;
}

  转换成

?
1
2
3
.header, .content {
     font-size : 24px ;
}

  用速记,而不是以下

?
1
2
3
4
5
.header {
     background-color : #999999 ;
     background-image : url (../images/header.jpg);
     background-position : top right ;
}

  用下面的风格编写

?
1
2
3
.header {
     background : #999 url (../images/header.jpg) top right ;
}

  缩减代码,也就是使用一个工具除去所有空间和线,可以使用CSSOptimiserMinifycss。常见做法是在应用程序服务器端使用这种工具。也就是在后端写的语言。通常情况相爱这些组件可以缩减你的代码。

  将你的CSS文件放在<head>标签下

  将你的CSS文件放在head标签下是很好的方法,浏览器会首先下载它们。

 JavaScript

  减少HTTP请求数量

  与CSS情况一样,减少服务器请求是有利的。大多数情况下,加载JavaScript文件的同时不会停止渲染页面,但会造成页面某些部分失去作用。

  缩减代码

  有些小工具可以缩减JavaScript,使文件大小减小了,但要记住在开发环境中,保持代码整洁是十分必要的。这些工具几乎都会改变变量名称,并转换成一个单行的字符串,这个过程不可能调试。

  试试CommonJS, AMD, RequireJS

  JavaScript本身并没有一个机制来管理模数,因此,这些工具是为了解决这个问题的。他们提供一个应用程序接口,你可以定义和使用模数。例如http://requirejs.org/

?
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
< html >
     < head >
         < title >My Sample Project</ title >
         <!-- data-main attribute tells require.js to load
              scripts/main.js after require.js loads. -->
         < script data-main = "scripts/main" src = "scripts/require.js" ></ script >
     </ head >
     < body >
         < h1 >My Sample Project</ h1 >
     </ body >
</ html >

  运行脚本,你可以用require()代替main.js 

?
1
2
3
4
5
6
require([ "helper/util" ], function (util) {
     //This function is called when scripts/helper/util.js is loaded.
     //If util.js calls define(), then this function is not fired until
     //util's dependencies have loaded, and the util argument will hold
     //the module value for "helper/util".
});

  使用名字空间

  提到代码组织,必然要提到命名空间的部分。原本在JavaScript中是没有这个功能的,但你可以通过几行代码来实现这个功能。比如,你想达一个MVC框架,就可以用以下方式:

?
1
2
3
var model = function () { ... };
var view = function () { ... };
var controller = function () { ... };

  光有以上代码是不够的,很容易与其他行的代码发生冲突。所以需要按照以下方式将它们作为独立的对象(命名空间)分组,以保护整体框架:

?
1
2
3
4
5
var MyAwesomeFramework = {
     model: function () { ... },
     view: function () { ... },
     controller: function () { ... }
}

 遵循设计模式

  JavasScript之所以很受欢迎是因为里面包含了大量例子。可重复使用的设计模式是编程中常见问题的解决方案。遵循某些设计模式可以帮助你更好的设计应用程序。如果我全都写下来,估计都可以出书了,所以这里只写出一些例子:

 构造函数模式

  用这个模式构建具体对象实例:

?
1
2
3
4
5
6
7
8
9
var Class = function (param1, param2) {
     this .var1 = param1;
     this .var2 = param2;
}
Class.prototype = {
     method: function () {
         alert( this .var1 + "/" + this .var2);
     }
};

  或者:

?
1
2
3
4
5
6
7
8
9
function Class(param1, param2) {
     this .var1 = param1;
     this .var2 = param2;
     this .method = function () {
         alert(param1 + "/" + param2);
     };
};
  
var instance = new Class( "value1" , "value2" );

 模块模式

  模块模式可以让我们创建私有和公共方法。比如下面的代码中,变量_index和方法privateMethod是私有的,increment和getIndex是公开的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Module = ( function () {
     var _index = 0;
     var privateMethod = function () {
         return _index * 10;
     }
     return {
         increment: function () {
             _index += 1;
         },
         getIndex: function () {
             return _index;
         }
     };     
})();

 观察者模式

  事件的订阅和分派发生的时候就能看到这种模式。观察者对特定对象相关的东西有兴趣,一旦发生动作,就会通知观察者。下面的例子显示我们如何才能增加用户对象的观察者:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var Users = {
     list: [],
     listeners: {},
     add: function (name) {
         this .list.push({name: name});
         this .dispatch( "user-added" );
     },
     on: function (eventName, listener) {
         if (! this .listeners[eventName]) this .listeners[eventName] = [];
         this .listeners[eventName].push(listener);
     },
     dispatch: function (eventName) {
         if ( this .listeners[eventName]) {
             for ( var i=0; i< this .listeners[eventName].length; i++) {
                 this .listeners[eventName][i]( this );
             }
         }
     },
     numOfAddedUsers: function () {
         return this .list.length;
     }
}
  
Users.on( "user-added" , function () {
     alert(Users.numOfAddedUsers());
});
  
Users.add( "Krasimir" );
Users.add( "Tsonev" );

 函数链接模式

  这种模式可以很好的组织模块的公共接口。节省时间,提高可读性:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var User = {
     profile: {},
     name: function (value) {
         this .profile.name = value;
         return this ;
     },
     job: function (value) {
         this .profile.job = value;
         return this ;
     },
     getProfile: function () {
         return this .profile;
     }
};   var profile = User.name( "Krasimir Tsonev" ).job( "web developer" ).getProfile();
console.log(profile);

  我强烈推荐Addy Osmani出的书,它涵盖了JavaScript中设计模式所有最棒的资源。

 Assets-Pack

  在本文结尾的时候,我想分享一些关于服务器上CSS和JavaScript代码管理方面的想法。这是一个常用手段来添加合并、缩小、编译成应用程序的逻辑。 时常有种缓存机制,但在程序运行的时候所有事情都在同时发生。就是说你或许有代码的逻辑,同时处理.js或.css文件请求,然后提供适当的内容。这个过 程的背后是汇编、压缩,以及其他。在我最新一个项目中我用到一种叫做Assets-Pack的工具。它非常有用,我可以详尽解释它能做什么,但更有趣的是 我是怎样使用这个工具的。只能用在开发模式中,不是停留在基于代码形式的,也不是在服务器上调配的。

  我的想法是运用这个工具只当你在处理 CSS和JS的时候,它可以监视特定目录中的变化,然后把代码编译/打包成为一个单一的文件。通过这个步骤,你不需要再去考虑压缩或者汇编。所有你所要做 的仅仅是将编译后的静态文件发送给用户。这增加了应用程序的性能,因为它只能提供静态文件,这当然让事情变得更简单。你不需要设置任何服务器或实施不必要 的逻辑。

  下面是你如何安装和使用Assets-Pack:

?
1
npm install -g assetspack

 用法

  该模块可与JSON配置,当它通过命令行被调用的时候,你应该把设置放到.json文件中。

  通过命令行

  创建assets.json文件夹,在同一个目录下执行以下代码:

?
1
assetspack

  如果你想使用另一种名称或者换一个目录:

?
1
assetspack --config [path to json file]

  代码形式的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var AssetsPack = require( "assetspack" );
var config = [
     {
         type: "css" ,
         watch: [ "css/src" ],
         output: "tests/packed/styles.css" ,
         minify: true ,
         exclude: [ "custom.css" ]
     }
];
var pack = new AssetsPack(config, function () {
     console.log( "AssetsPack is watching" );
});
pack.onPack( function () {
     console.log( "AssetsPack did the job" );
});

 配置

  配置应该是一个有效的JSON文件/对象,下面只是一个对象数组:

?
1
2
3
4
5
6
[
     (asset object),
     (asset object),
     (asset object),
     ...
]

  Asset Object

  Asset Object的基本结构如下:

?
1
2
3
4
5
6
7
8
{
     type: (file type /string, could be css, js or less for example),
     watch: (directory or directories for watching /string or array of strings/),
     pack: (directory or directories for packing /string or array of strings/. ),
     output: (path to output file /string/),
     minify: /boolean/,
     exclude: (array of file names)
}

  pack属性不是强制的,如果丢失了,它的值还是相等的,默认情况下的缩减是假属性。

  下面是一些例子:

  Packing CSS

?
1
2
3
4
5
6
7
8
{
     type: "css" ,
     watch: [ "tests/data/css" , "tests/data/css2" ],
     pack: [ "tests/data/css" , "tests/data/css2" ],
     output: "tests/packed/styles.css" ,
     minify: true ,
     exclude: [ "header.css" ]
}

  Packing JavaScript

?
1
2
3
4
5
6
7
8
{
     type: "js" ,
     watch: "tests/data/js" ,
     pack: [ "tests/data/js" ],
     output: "tests/packed/scripts.js" ,
     minify: true ,
     exclude: [ "A.js" ]
}

  Packing .less Files

  Packing .less Files有点不同,pack属性是强制性的,基于你的切入点。你应当导入所有其他的.less文件。排除属性在这里无效。

?
1
2
3
4
5
6
7
{
     type: "less" ,
     watch: [ "tests/data/less" ],
     pack: "tests/data/less/index.less" ,
     output: "tests/packed/styles-less.css" ,
     minify: true
}

  如果有其他问题,可以在源代码(GitHub)库中查看tests/packing-less.spec.js 

  压缩其他格式文件

  assets-pack适用于所有文件格式。比如你可以结合HTML模板和一个简单文件,用以下方式:

?
1
2
3
4
5
6
{
     type: "html" ,
     watch: [ "tests/data/tpl" ],
     output: "tests/packed/template.html" ,
     exclude: [ "admin.html" ]
}

  有一点需要注意的是这里没有缩小倍率。

  结论

  作为前端Web开发人员,我们应该尽量为的用户提供最佳的性能。上面的提示不应该涵盖所有资产的组织和性能方面的技巧,但它们是常用的几种。

  英文来源:web-assets-tips-for-better-organization-and-performance

转载于:https://www.cnblogs.com/Blog-Yang/p/3261880.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值