web页面内容优化管理与性能技巧
来源:GBin1.com
回 想一下,以前我们不得不花费大量时间去优化页面内容(图片、CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪 存文件,里面包含的有视频或者图片。然而,随着移动开发的兴起,我们又回到了过去的窘状。网站优化是十分重要的,需要下载的内容少,反应速度快,就能使我 们加载应用程序更快速。
图片:控制在合适的尺寸大小
很多时候我们在不同的网站使用同样的图像,例如一个网上商店,所有产品 都 有一个概览图片。打个比方,有三个页面描述产品,第一个页面显示产品清单,第二个页面显示产品细节图,第三个页面显示产品原始大小图。因此,我们需要三种 不同大小的图片。如果使用一个文件放到不同的三个页面上,那么浏览器会自动加载完整大小的图片,就连清单页也是,实际上清单页只需要200×200尺寸的 图片。如果原始文件大小在1MB左右,每页上有十个产品介绍,那么用户就要下载10MB大小的资源。这样做效果不好。如果可以的话,尽量为你的网站不同位 置分配不同的图像文件,那么就可以让用户少下载资源。把屏幕分辨率因素也考虑进去也是很好的。如果有人用iPhone打开你的网站页面,手机上不需要显示 电脑上那么大尺寸的图片,只需适应手机屏幕的大小就可以了。通过CSS Media Queries,你就能将图像压缩到较小尺寸发送出去了:
- @media only screen
- and (min-device-width : 320px)
- and (max-device-width : 480px) {
- .header {
- background-image: url(../images/background_400x200.jpg);
- }
- }
压缩
传送图像的时候单单控制适当的尺寸往往是不够的。不少文件格式在不失真的前提下可以被压缩很多。有一类应用程序可以达到这个效果。比如Photoshop有个很好的功能叫做Save for Web and Devices:
在此对话框中有多个选项,其中最重要的是质量,将其设计为80%左右,就能显著减少文件大小了。当然,你还可以使用代码来压缩文件,但我个人偏向于使用PS。下面是用PHP编写的一个简单的例子:
- 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引导内部图标:
在CSS中,你可以参照以下方式,显示你喜欢的sprite部分:
- .icon-edit {
- background-image: url("../img/glyphicons-halflings-white.png");
- background-position: -96px -72px;
- }
超高速缓存
浏览器超高速缓存十分好用。尽管有时在开发过程中会导致一些非常有趣的情况,但它确实有助于提高你的网站的性能。所有浏览器的超高速缓存下来的内容包括图片、JavaScript或者CSS。有几种方法可以控制缓存,建议你阅读相关文章。一般情况下,你可以通过设置标题,达到控制效果:
- $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每天都在进步,有一个很好的功能叫做预读取,它让浏览器提前下载你马上需要用到的资源:
- <link rel="prefetch" href="/images/background.jpg">
数据URI方案/内联图像
几年前我曾开发了一个简单的网页,只包含一个HTML文件夹,但当然里面应该还包括一些我需要的图像。数据URI方案帮助我解决了问题。我们的想法是将图像转换成一个base64编码的字符串,并将其放置在src属性中的img标签里,例如:
- <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
通过这种方法,你的图像实际上在HTML中并保存了一个HTTP请求。你的图像越大的话,字符串就越长。下面是一个简单的PHP脚本图像转换为base64字符串的实例:
- $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="data:image/jpg;base64,'.$base64.'" alt="" />';
- $css = 'url(data:image/jpg;base64,'.str_replace("\n", "", $base64).'); ';
有些情况下这种方法挺好用的,但请注意,在IE浏览器中无法很好的兼容。
CSS
我 觉得编写CSS就如同写代码。你同样需要组织模式,定义不同板块和关系。所以我认为CSS管理非常重要。应用程序的每一部分应该有对应的模式,并很好的独 立。不同的内容存储在不同的文件夹可以有效的管理,但同样也存在问题。使用@import状态这种方法不好用,因为每用一个@import都意味着一个新 的请求发送到服务器。如果你有20个不同的.css文件,就相当于浏览器要发送20个请求。浏览器在渲染/下载所有内容之前不会显示页面。如果你 的.css文件丢失了或者太大,浏览器加载页面的时间就会大大延长。
使用CSS预处理器
CSS预处理器可以解决上述问题。你 同样可以保存不同的文件夹,预处理器可以将这些散文件夹最终生成一个.css文件。实际上提供了一系列非常帮的功能比如变量、嵌套块、混入和继承。代码看 上去类似CSS,但实际上被很好的统一格式与结构了。有几种好用的预处理器值得体验——Sass、LESS、Stylus。下面是用LESS编写的例子:
- .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);
- }
- }
运行生成:
- .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;
- }
又如你想再创建一个同样样式的按钮,但是颜色不同,你可以这样做:
- .button {
- border: solid 1px #000;
- padding: 10px;
- background: #9f0;
- color: #0029FF;
- }
- .active-button {
- .button();
- color: #FFF;
- }
高效的CSS
通常情况下,大多数开发人员没有考虑过CSS效率问题。CSS的效率反映在页面渲染上,如果模式低效,应用程序在浏览器上运行就会很慢。有趣的是浏览器解析CSS选择器是从右到左的。所以以下代码更不一点效率都没有:
- body ul li a {
- color: #F000;
- text-decoration: none;
- }
这是因为该引擎首先识别所有的<a>标签,评估每个母元素,最终收集到所需模式。你要知道,为了提高效率,选择器有个 先后排序:ID、类、标签及其一般。这意味着一个带有id的元素集比只带有标签选择器的元素更快的被渲染。当然,在所有DOM树元素都加上id是没有意义 的,但你应该特定检查代码,把可能加id的地方都加上。比如你可以按照以下方式做:
- ul #navigation li {
- background: #ff0232;
- }
.content元素是body tag的子集,实际上所有元素都是body tag的子集。关于这个话题有两个有用的链接:developers.google.com和css-tricks.com。
文件大小
正如我们上面提到的,代码越少越好,因为浏览器在加载CSS之前不渲染页面。下面几个技巧可供缩小文件大小:
把类似的行
- .header {
- font-size: 24px;
- }
- .content {
- font-size: 24px;
- }
转换成
- .header, .content {
- font-size: 24px;
- }
用速记,而不是以下
- .header {
- background-color: #999999;
- background-image: url(../images/header.jpg);
- background-position: top right;
- }
用下面的风格编写
- .header {
- background: #999 url(../images/header.jpg) top right;
- }
缩减代码,也就是使用一个工具除去所有空间和线,可以使用CSSOptimiser或Minifycss。常见做法是在应用程序服务器端使用这种工具。也就是在后端写的语言。通常情况相爱这些组件可以缩减你的代码。
将你的CSS文件放在<head>标签下
将你的CSS文件放在head标签下是很好的方法,浏览器会首先下载它们。
JavaScript
减少HTTP请求数量
与CSS情况一样,减少服务器请求是有利的。大多数情况下,加载JavaScript文件的同时不会停止渲染页面,但会造成页面某些部分失去作用。
缩减代码
有些小工具可以缩减JavaScript,使文件大小减小了,但要记住在开发环境中,保持代码整洁是十分必要的。这些工具几乎都会改变变量名称,并转换成一个单行的字符串,这个过程不可能调试。
JavaScript本身并没有一个机制来管理模数,因此,这些工具是为了解决这个问题的。他们提供一个应用程序接口,你可以定义和使用模数。例如http://requirejs.org/:
- <!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
- 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框架,就可以用以下方式:
- var model = function() { ... };
- var view = function() { ... };
- var controller = function() { ... };
光有以上代码是不够的,很容易与其他行的代码发生冲突。所以需要按照以下方式将它们作为独立的对象(命名空间)分组,以保护整体框架:
- var MyAwesomeFramework = {
- model: function() { ... },
- view: function() { ... },
- controller: function() { ... }
- }
遵循设计模式
JavasScript之所以很受欢迎是因为里面包含了大量例子。可重复使用的设计模式是编程中常见问题的解决方案。遵循某些设计模式可以帮助你更好的设计应用程序。如果我全都写下来,估计都可以出书了,所以这里只写出一些例子:
构造函数模式
用这个模式构建具体对象实例:
- var Class = function(param1, param2) {
- this.var1 = param1;
- this.var2 = param2;
- }
- Class.prototype = {
- method:function() {
- alert(this.var1 + "/" + this.var2);
- }
- };
或者:
- 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是公开的。
- var Module = (function() {
- var _index = 0;
- var privateMethod = function() {
- return _index * 10;
- }
- return {
- increment: function() {
- _index += 1;
- },
- getIndex: function() {
- return _index;
- }
- };
- })();
观察者模式
事件的订阅和分派发生的时候就能看到这种模式。观察者对特定对象相关的东西有兴趣,一旦发生动作,就会通知观察者。下面的例子显示我们如何才能增加用户对象的观察者:
- 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");
函数链接模式
这种模式可以很好的组织模块的公共接口。节省时间,提高可读性:
- 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:
- npm install -g assetspack
用法
该模块可与JSON配置,当它通过命令行被调用的时候,你应该把设置放到.json文件中。
通过命令行
创建assets.json文件夹,在同一个目录下执行以下代码:
- assetspack
如果你想使用另一种名称或者换一个目录:
- assetspack --config [path to json file]
代码形式的
- 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文件/对象,下面只是一个对象数组:
- [
- (asset object),
- (asset object),
- (asset object),
- ...
- ]
Asset Object
Asset Object的基本结构如下:
- {
- 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
- {
- 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
- {
- 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文件。排除属性在这里无效。
- {
- 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模板和一个简单文件,用以下方式:
- {
- type: "html",
- watch: ["tests/data/tpl"],
- output: "tests/packed/template.html",
- exclude: ["admin.html"]
- }
有一点需要注意的是这里没有缩小倍率。
结论
作为前端Web开发人员,我们应该尽量为的用户提供最佳的性能。上面的提示不应该涵盖所有资产的组织和性能方面的技巧,但它们是常用的几种。
via 极客标签
web页面内容优化管理与性能技巧的更多相关文章
- web 页面内容优化管理与性能技巧
回想一下,以前我们不得不花费大量时间去优化页面内容(图片.CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪存文件,里面包含的有视频或者图片.然而,随着移动开发的兴起,我 ...
- 知名网站内部资料:WEB页面内容优化管理与性能技巧
回想一下,以前我们不得不花费大量时间去优化页面内容(图片.CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪 存文件,里面包含的有视频或者图片.然而,随着移动开发的兴起, ...
- 基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作
在前面介绍了很多篇相关的<Bootstrap开发框架>的系列文章,这些内容基本上覆盖到了我这个Bootstrap框架的各个主要方面的内容,总体来说基本达到了一个稳定的状态,随着时间的推移可 ...
- web页面的优化
众所周知,一个web页面通常会包括HTML(XHTML.XML).CSS.Javascript,而其中HTML(XHTML.XML)为结构化语言,用于构建页面结构和相关数据:CSS则负责页面的样式,即 ...
- (转)基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作
http://www.cnblogs.com/wuhuacong/p/5147368.html 在前面介绍了很多篇相关的<Bootstrap开发框架>的系列文章,这些内容基本上覆盖到了我这 ...
- Swipe JS – 移动WEB页面内容触摸滑动类库
想必做移动前端的同学经常会接到这样子的一个需求,就是在移动设备页面上的banner图能够用手指触摸左右或上下的滑动切换,这在移动设备是个很常见的一个效果,其用户体验远甚于点击一个按钮区域,通过手指的触 ...
- js打印WEB页面内容代码大全
第一种方法:指定不打印区域 使用CSS,定义一个.noprint的class,将不打印的内容放入这个class内. 详细如下: <style media=print type="tex ...
- web页面内容打印总结
web页面打印有两种,一种是直接调用window.print()命令操作,一种是使用ActiveX插件(Object标签)操作,但是第二种只支持IE内核的浏览器. 示例1: <!DOCTYPE ...
- Winfrom 抓取web页面内容代码
WebRequest request = WebRequest.Create("http://1.bjapp.sinaapp.com/play.php?a=" + PageUrl) ...
随机推荐
- CentOS 6.4 系统上如何安装 tomcat 8
CentOS 6.4 系统上如何安装 tomcat 8 本文将详细讲解在Linux系统上如何安装tomcat,tomcat是没有32位和64位之分的. 1.下载tomcat 首先我们肯定要先下载tom ...
- Codeforces 1099 B. Squares and Segments-思维(Codeforces Round #530 (Div. 2))
B. Squares and Segments time limit per test 1 second memory limit per test 256 megabytes input stand ...
- 初始pip
关于pip包括下面的东西还不是很懂,慢慢的了解,我的pip是从https://bootstrap.pypa.io/get-pip.py 粘贴并命名为 get-pip.py 后,执行 python ge ...
- java之异常
package com.text.exception; class Test{ void add(int a,int b) throws Exception { int c; c=a/b; Syste ...
- Linux命令之head
head [选项] [文件] head命令输出文件开头部分,默认情况下显示文件的头10行.如果指定多个文件,每个文件前都有一个标题,给出文件名.如果没有指定文件,或当文件为-时,读取标准输入. (1) ...
- DBCS 从256开始
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字 ...
- [P2526][SHOI2001]小狗散步
Link: P2526 传送门 Solution: 一道提示非常到位的题目 题面中强调了在两个路径相邻点间只能再去至多一个点,且每个点只计算一次贡献 于是明显可以将原题看作询问在两个不相交点集间最多能 ...
- 【最大流Dinic模板】HDU1532&POJ1273-Drainage Ditches(16/3/6更正)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inc ...
- python3-开发进阶Django-CBV和FBV及CBV的源码分析
一.CBV和FBV 全称应该是class base views 和function base views理解起来应该就是基于类的视图函数和基于函数的视图函数 FBV 应该是我目前最常用的一种方式了,就 ...
- iOS 未读消息角标 仿QQ拖拽 简单灵活 支持xib(源码)
一.效果 二.简单用法 超级简单,2行代码集成:xib可0代码集成,只需拖一个view关联LFBadge类即可 //一般view上加角标 _badge1 = [[LFBadge alloc] init ...