December 2018  |  01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

CSSの@importはどれだけ悪影響なのか自分で試してみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Webサイトの高速化について調べてみるとCSSの@import url();は使わない方が良いという指摘をよく見かけます。
問題となるのはパラレルロード(複数のリソースを同時にロードする)ができなくなる場合があることと、CSSの読み込み順序が変わってしまうことがあるようです。
実際にどれだけ読み込み速度に問題があるのか、3つの読み込み方で試してみたいと思います。

比較する3つの読み込み方

今回はこの3つで読み込みを比較してみます。

  1. CSSの@import url();で読み込む
  2. HTMLのlink要素で別々に読み込む
  3. Sassで@importして1つにまとめてlink要素で読み込む

対象ブラウザ

今回の検証ブラウザはChromeとInternet Explorerです。
どちらも備え付けの開発者ツールで検証します。

今回計測したサンプル

サンプルはこちらに公開しているので問題があれば指摘してください。

1,準備

HTMLのbody部分は共通になります。

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
<body>
  <header>
    <h1>Site ID</h1>
    <nav>
      <ul>
        <li><a href="#">nav 01</a></li>
        <li><a href="#">nav 02</a></li>
        <li><a href="#">nav 03</a></li>
      </ul>
    </nav>
  </header>
 
  <section id="container">
    <header>
      <h1>Main title</h1>
      <p>Sub title</p>
    </header>
    <main class="editable">
      <h2 id="toc-title">title</h2>
      <p>this is dammy text.</p>
    </main>
  </section>
 
  <footer>
    <p>Copyright</p>
  </footer>
</body>

1.1,CSSの@import url();で読み込む

検証サンプル

以下のようなファイル構造にします。

  • css/
    • module/
      • header.css
      • container.css
      • footer.css
      • editable.css
      • button.css
    • common.css
    • style.css(import)
  • css_import.html

ポイントとなる読み込み部分:style.css

1
2
3
4
5
6
7
8
9
10
11
/* *****************************
 *
 * Import CSS file.
 *
 **************************** */
@import url('common.css');
@import url('module/header.css');
@import url('module/container.css');
@import url('module/footer.css');
@import url('module/editable.css');
@import url('module/button.css');

1.2,HTMLのlink要素で別々に読み込む

検証サンプル

こちらは上記の構造とほぼ同じですが、import用のstyle.cssを省きます。

  • css/
    • module/
      • header.css
      • container.css
      • footer.css
      • editable.css
      • button.css
    • common.css
  • css_import.html

ポイントとなる読み込み部分:css_link.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>CSS Link Tag Sample</title>
<link rel='stylesheet' href='css/common.css' type='text/css' media='all' />
<link rel='stylesheet' href='css/module/header.css' type='text/css' media='all' />
<link rel='stylesheet' href='css/module/container.css' type='text/css' media='all' />
<link rel='stylesheet' href='css/module/footer.css' type='text/css' media='all' />
<link rel='stylesheet' href='css/module/editable.css' type='text/css' media='all' />
<link rel='stylesheet' href='css/module/button.css' type='text/css' media='all' />
</head>

1.3,Sassで@importして1つにまとめてlink要素で読み込む

検証サンプル

Sassを使いコンパイル後のまとめられたCSSのみをlink要素でHTMLに読み込みます。
モジュール化されたSCSSファイルはパーシャルという「_」を付けた読み込み専用ファイルにしてstyle.scssに読み込ませます。

  • scss/
    • module/
      • _header.scss
      • _container.scss
      • _footer.scss
      • _editable.scss
      • _button.scss
    • _common.scss
    • style.scss
  • output/
    • style.css
  • css_import.html

ポイントとなる読み込み部分:style.scss

1
2
3
4
5
6
7
8
9
10
11
/* *****************************
 *
 * Import file to Scss or Sass.
 *
 **************************** */
@import "common";
@import "module/header";
@import "module/container";
@import "module/footer";
@import "module/editable";
@import "module/button";
1
2
3
4
5
6
7
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>SCSS @import Sample</title>
<link rel='stylesheet' href='output/style.css' type='text/css' media='all' />
</head>

2,読み込んだ結果を比較検証

結果は以下の比較表を見て貰えるとわかりますが、link要素で連続的に読み込むよりも@importが遅いことがわかります。
また、Sassでコンパイルしたものがリクエストも少なくロードしたサイズまで1/3程度になっています。

比較表

対象ブラウザ 読み込み方法 リクエスト数 サイズ 読み込み時間
Chrome CSS @import 8 1.75KB 607ms
link 7 1.53KB 437ms
Sass compile 2 448B 388ms
Internet Explorer CSS @import 8 1.23KB 924ms
link 7 1.07KB 390ms
Sass compile 2 315B 374ms

Chromeで検証したタイムライン

CSS @import

インポート用のstyle.cssを読み込んでから@import対象のファイルのリクエストを出しているのでその分読み込み完了時間が遅くなっています。
また、若干ですが@importしているファイルの読み込み時間に差があり、パラレルロードが行えていないように見受けられます。@import対象のファイルサイズが重くなるとロードの順序が顕著に表れてくるかもしれません。

Chrome CSS @import

CSS link要素

スムーズに読み込まれていますが、リクエスト数が多いため待機時間とリクエストヘッダの分ファイルサイズが大きくなっています。

Chrome CSS link要素

Sass compile

リクエスト数も少なくファイルサイズも小さいためとても理想的です。

Chrome Sass Compile

Internet Explorerで検証したタイムライン

CSS @import

Chromeと違い@import部分でも読み込みに大きな差がでています。
何が原因なのかはこれだけではわかりませんね。

IE CSS @import

CSS link要素

Chromeとほぼ変わらず安定して読み込んでくれます。

IE CSS link要素

Sass compile

Chromeと変わらず最速です。

IE Sass Compile

CSSもモジュール化・コンポーネント化するメリットとまとめ

実はこの記事で言いたいことは@importの問題というよりはCSSをモジュール化・コンポーネント化するメリットにあります。

最近公開されたこちらの記事「画面ではなく部品から始めてみよう」でも言われているように固定の画面サイズに合わせたCSSをだらだらと記述するより、モジュール・コンポーネントを必要に応じて読み込む方が変化に強いのではないかと最近思い始めました。
Bootstrapは顕著な例でしょう。

モジュール化やコンポーネント化はiOSやAndroid、Adobe Flexや大規模なWebサイト開発ではすでに行われているかと思います。
個人的な主観ですが、小規模なWebサイトを作る際は、ページ単位でCSSを記述することが多く作っている時は良いけれども、運用中に変更する事があると手間が多く作りにくいなと感じていました。(変更は可能だが不要なCSSの消し忘れや消して他のページにも影響したなど手間がかかる)

Sassが使えなかった時はモジュール化するには@importを使うしか方法がなく管理のしやすさとサイトの表示速度のどちらかしか実現できません(正確にはサーバー側で処理させるなど方法はある)。
これからは、Sassなどのメタ言語を利用しコンパイルを行うことで今回のサンプルのように管理のしやすさを維持しつつ、サイトの高速化も実現することができます。

今後はWeb Componentsも利用できるようになるとHTMLのコンポーネント化が可能になりよりモジュール化やコンポーネント化を意識した構築方法にく変化していくと思います。
考え方を今から少しずつ変えていきたいですね。

@importの問題についてはより詳しい検証を行っているこちらの記事も参考になります。
@importを使うべきでない理由

pagetop