Expiresヘッダの設定と、gulp-revを利用したフィンガープリントの付与

公開

Googleはなぜモバイルに力を入れるのか?これからのWebパフォーマンスで注力すべきポイント | HTML5Experts.jpを読んで、「そういえばこのブログはGoogleのPageSpeed Insightsでチェックしていたかな?」と思い、早速分析にかけてみました。

分析結果を確認すると、「修正を考慮」の項で"画像やCSSファイルのHTTPヘッダー内で有効期日を設定するとよい"という趣旨のアドバイスが表示されました。そういえば、まだデザイン等を修正するかもしれないので落ち着くまでExpiresヘッダの設定はしないでおこうと考えていました。サイトロゴの作成も完了し、デザインもひとまず満足しているので、早速nginxの設定を変更し、Expiresヘッダを送信するようにしました。
PageSpeed Insightsで分析を行った結果画面の一部分

URLフィンガープリントを利用してCSS変更時の対策を行う

CSSだけは時々変更を行うことがあります。すぐに反映されないと困るのでどうしようかと考えつつ「ブラウザのキャッシュを活用する」を読んでいると、「URL フィンガープリントの使用」の項にヒントがありました。

ときどき変更されるリソースの場合、サーバー上でリソースが変更され、サーバーがブラウザに新しいバージョンが提供されたことを通知するまで、ブラウザでリソースをキャッシュしておくことができます。リソースの各バージョンに一意の URL を指定すると、この方法を実現できます。たとえば、「my_stylesheet.css」というリソースがあるとします。このファイル名を「my_stylesheet_fingerprint.css」に変更できます。リソースが変更されると、フィンガープリントも変更されるため、URL も変わります。URL が変更されるとすぐに、ブラウザはリソースの再取得を強制されます。フィンガープリントを使用すると、頻繁に変更されるリソースでも、有効期限をそれより先の方の日付に設定できるようになります。

フィンガープリントの一般的な方法として、ファイルのコンテンツのハッシュをコード化した 128 ビットの 16 進数が使用されます。

"url fingerprint"でGoogle検索を行いページを見ているとGruntのタスクが出てきたので、「Gruntで自動化すれば良いのか」と気付きました。ただ、今のGruntfile.coffeeに新たなタスクを追加すると、CSS関連のタスクが色々あって分かりづらそうなので、gulpに移行してgulp-revをインストールし、下記のようにgulpfile.coffeeを書きました(一部抜粋)。やはりgulpで書く方が分かりやすい印象です。

# Path Settings
basepath = '../htdocs/'
paths =
    styles:
        src: basepath + '_scss/'
        dest: basepath + 'css/'
    images:
        src: basepath + '**/*.{png,jpg,svg}'

# Read Modules
gulp = require 'gulp'
path = require 'path'
plugins = require('gulp-load-plugins')()

# Tasks
gulp.task 'styles', ->
    gulp.src paths.styles.src + 'basic.scss'
        .pipe plugins.rubySass
            style: 'compressed'
            sourcemap: false
            precision: 3
            loadPath: path.join(__dirname) + '/' + paths.styles.src
        .pipe plugins.autoprefixer 'last 2 version', 'ie 9', 'ie 8', 'Firefox ESR'
        .pipe if plugins.util.env.prod then plugins.rev() else plugins.util.noop()
        .pipe gulp.dest paths.styles.dest

gulp.task 'webserver', ->
    gulp.src basepath
        .pipe plugins.webserver
            livereload: true
            host: '0.0.0.0'
            port: 3501

gulp.task 'watch', ->
    gulp.watch paths.styles.src + '*.scss', ['styles']
    return

gulp.task 'default', [
    'webserver'
    'styles'
    'watch'
]

これにより、通常はgulpコマンドで制作を行い、作業完了時はgulp styles --prodコマンドでコンパイルを行い、"basic-ea73a21c.css"のようなフィンガープリント付きのファイルを出力するようにしました(128ビットの16進数にはなっていないものの、ひとまずこれで...)。

link要素で指定しているCSS名のファイル名も変更が必要ですが、gulp-revのintegration guideなどにヒントがありそうです。このサイトはMTなので、rev-manifest.jsonとMTのプラグインで対応すれば良いかなと考えています。