2018-05-17

NuxtデフォルトサーバはCache-Controlできないので注意

まとめ

  • Nuxtは各種のサーバサイドフレームワークと組み合わせられるがNuxtだけでもサーバとして機能する
  • デフォルトで ETag は吐くが Cache-Control は吐かないのでそのまま CDN に食わせるといつまでもリフレッシュされない
    • この影響を受けるのはあくまで vue-router を経由する Page だけ
    • assets に関しては nuxt start で serve している場合は問答無用で max-age は 1 year になる1
  • optional な http response header を追加する middleware はどうもなさげ
    • 他のフレームワークと組み合わせてその middleware を使えば追加できる(Koa で確認済み)

そもそもWebのcacheって

  • private cache と public cache がある
  • CDN は public cache
  • ブラウザは private cache
  • Cache-Control を private にすると CDN は cache できない(したがって、リクエスト数も転送量も減らない)
  • とにかく Nuxt.js は何の情報も追加しない

※ public と private の話は恥ずかしながら CDN切り替え作業における、Web版メルカリの個人情報流出の原因につきまして - Mercari Engineering Blog にあるようにメルカリのやらかしで知りました。(ちなみに Rails はデフォルトで max-age=0, private, must-revalidate を付加するので特に何も考える必要なく CDN はスルーになる。)

CDN側では基本的にmax-ageを推奨してる

基本的には Cache-Control: max-age= を設定するのがよさげ。(Surrogate-Control や s-maxage だったりもしますが、細かいことは置いておく。)

しかし Nuxt.js にはサーバ側の設定の余地がない。(SSR用の MartinLG/nuxt-custom-headers: Nuxt module to add custom headers to SSR rendered pages. というものはある。)

NuxtではETagと304しか考えてない

具体的なコードは以下の部分。

lib/core/middleware/nuxt.js

  // Add ETag header
   if (!error && this.options.render.etag) {
     const etag = generateETag(html, this.options.render.etag)
     if (fresh(req.headers, { etag })) {
       res.statusCode = 304
       res.end()
       return
     }
     res.setHeader('ETag', etag)
   }

nuxt.config.js の render.etag option を見るこの辺以外に cache を考慮しているコードは存在しない。ETag を付けるか付けないかだけ。直接ブラウザとやりとりするならこれだけでも十分かもしれないが CDN を通す場合はそうはいかない。

そこでNode.jsのサーバサイドフレームワークと組み合わせる

nuxt-community/create-nuxt-app: Create Nuxt.js App in seconds.

を使えば Express, Koa, Hapi, … などなどからフレームワークを選べる。これらの middleware で custom header を吐いてあげればおk

具体的に効果的にcacheするには

例えば Koa であれば

を組み合わせて、./server/index.js で

const Koa = require('koa')

const app = new Koa()

require('koa-ctx-cache-control')(app)

app.use(async (ctx, next) => {
  ctx.cacheControl('max-age=0')

こんな感じ。

こうすると pages 以下の component を serve する時には Cache-Control: max-age=0 が付加されたうえで ETag でのキャッシュ内容のチェックが行われるので、origin サーバから直接転送されるものはコンテンツの鮮度チェックはしつつも転送はほぼエッヂサーバから行われるので速い。(はず)

  1. cache buster の効くファイルが生成されている 

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm