异步加载CSS

说到加载 CSS 这种事儿不是很简单吗?像这样咯:

<link rel="stylesheet" href="cssfile.css">

这不就完事儿了嘛!

这样是没错!但是这样有问题啊——会阻塞渲染!浏览器看到这个标签就会停下手里的活儿,去加载 CSS 并解析了。

当然了,如果这个 CSS 文件是接下来要渲染的内容所需的,那无可厚非,必须先要有了这个 CSS 才能接着渲染,阻塞也是情理之中。

但实际的情况却是,我们很多 CSS 内容其实在首屏的时候是不需要,起码等到后续才会使用,那么这个时候这些 CSS 这样加载去阻塞内容渲染就不对了。

也就是说,针对优先级不那么高的(暂时用不到)CSS,就应该要想办法让它异步加载,不要阻塞浏览器渲染。

那么怎么弄呢?

老方子

现在介绍第一种老办法:通过 JS 动态插入 link 标签来异步载入 CSS 代码,就像这样:

var myCSS = document.createElement( "link" );
myCSS.rel = "stylesheet";
myCSS.href = "mystyles.css";
document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );

这个很好理解吧,就是后续 JS 执行的时候,去创建一个 link 标签来加载 CSS 代码。

还有一个办法呢就是利用 link 上的 media 属性,将它设置为和用户当前浏览器环境不匹配的值,比如:media="print",甚至可以设置为一个完全无效的值 media="jscourse" 之类的。

这样一来,浏览器就会认为这个 CSS 文件优先级非常低,就会在不阻塞的情况下进行加载。但是为了让 CSS 规则生效,最后还是要将 media 值改对才行。所以,这个办法落实到代码就是这样:

<link rel="stylesheet" href="cssfile.css" media="jscourse" onload="this.media='all'">

 

介绍完了老方子,我们再来看看新药方。

新的异步加载方式

新方子就是利用规范中新增加的 rel="preload" ,就像这样:

<link rel="preload" href="cssfile.css" as="style" onload="this.rel='stylesheet'">

通过 preload 属性值就是告诉浏览器这个资源文件随后会用到,请提前加载好。但是这只是加载,所以你看当它加载完毕后,还是需要将 rel 值改回去,这才能让 CSS 生效。

你是不是想问:这和老方子也没多大区别嘛!

看上去确实如此,但是呢,语义上更加好一些。另外就是你仔细点就会发现 as="style"这个属性,所以 preload 不仅仅可以用在 CSS 文件上,而是可以用在绝大多数的资源文件上。比如:JS 文件

<link rel="preload" href="scriptfile.js" as="script">

然后要用的时候,就创建一个 script 标签指向它:

var script = document.createElement("script");
script.src = "scriptfile.js";
document.body.appendChild(script);

这个时候浏览器就直接从缓存中拿这个文件了,不会再发请求了,因为此前已经加载好了。

那么 preload 中的 as 属性支持哪些资源文件呢?下面这些都可以:

  • audio
  • document
  • embed
  • fetch
  • font
  • image
  • object
  • script
  • style
  • track
  • worker
  • video

是不是迫不及待想去试试了?告诉你个坏消息,目前 preload 只有 Chrome 是完美支持的,其他浏览器惨不忍睹,哎!

 

posted @ 2017-12-28 09:01  cjx_work  阅读(3762)  评论(0编辑  收藏  举报