はじめに
どうも、@nittannittanです。
趣味でAndroid/iOS/Webアプリを作成しているアニメオタクです。
最近SPAとして開発をしたWebサービスの機能が増えてきたために初回アクセス時のjsロード時間が30秒ほどかかってしまうほど激遅になってしまったのでgzip圧縮で対応をしてみました。
初歩的な技術かもしれませんが、私の環境に完全に合致する記事が探せなかったので本記事を作成しました。
関係する技術
- PHP
- Laravel Mix
- Vue.js
- heroku
- compression-webpack-plugin
1. compression-webpack-pluginをインストール
npm install compression-webpack-plugin --save-dev
2. webpack.mix.jsにcompression-webpack-pluginの記述を追加
下記の2つの処理をwebpack.mix.jsに追加しmixでのapp.js生成時に同時にgzファイルを生成する。
const CompressionPlugin = require('compression-webpack-plugin');
mix.webpackConfig({
plugins: [
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$|\.svg$/,
threshold: 10240,
minRatio: 0.8,
})
]
});
追加後は下記
const mix = require('laravel-mix');
const CompressionPlugin = require('compression-webpack-plugin');//追加
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
//追加
.webpackConfig({
plugins: [
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$|\.svg$/,
threshold: 10240,
minRatio: 0.8,
})
]
});
if (mix.inProduction()) {
mix.version();
}
3. ビルド
リリース用ビルドを実行する
npm run production
完了するとcssとjsのgzipファイルが生成されます。
1/3ほどになりましたね。やったぜ。
4. .htaccessにgzipをレスポンスで返却するように設定
gzipファイルを用意しただけではレスポンスでgzipを返してはくれません。
heroku上ではapacheを利用しているので、.htaccessにgzipの設定を追加します。
# gzip対応
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.+) $1.gz
<FilesMatch "\.css\.gz$">
ForceType text/css
AddEncoding x-gzip .gz
</FilesMatch>
<FilesMatch "\.js\.gz$">
ForceType application/x-javascript
AddEncoding x-gzip .gz
</FilesMatch>
Header append Vary Accept-Encoding env=!dont-vary
laravelはもともと.htaccessでindex.phpへのリダイレクトをコントロールしているため追加後は下記のようになります。
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# gzip対応
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}\.gz -s
RewriteRule ^(.+) $1.gz
<FilesMatch "\.css\.gz$">
ForceType text/css
AddEncoding x-gzip .gz
</FilesMatch>
<FilesMatch "\.js\.gz$">
ForceType application/x-javascript
AddEncoding x-gzip .gz
</FilesMatch>
Header append Vary Accept-Encoding env=!dont-vary
</IfModule>
今回の環境に不要なプロキシの設定も最後にありますが、各自で判断して記載してください。
ちなみに私は.htaccessに食わず嫌い的な苦手意識があるので参考サイトのほぼコピーです。。。
それを少し改善しようと思ったので下記を確認して少し理解はしておきました。
https://html-coding.co.jp/knowhow/tips/wp_modrewrite/
https://github.com/EC-CUBE/ec-cube/issues/1607
5. Heroku環境にデプロイして動作確認
普段と同じようにHerokuにgit pushを行ってリリースします。
その後ChromeのDevToolsでリクエストとレスポンスを確認します。
Content-Lengthもgzipファイルと同じサイズですし、Content-Encodingもx-gzipになっているので成功していそうですね。
雰囲気で.htaccessをコピペして試したらうまく言っているようなのでうまく行き過ぎて不安は感じましたが.htaccessを再確認しても不明点や問題になりそうなものもないため良しとします。
間違いがあればご指摘していただけると嬉しいです。
Laravel Mixについて
Laravelを仕事で使いそうという理由でLaravelを選択しせっかくだからSPAにしようということでドキュメントに従ってLaravel Mixを利用していますが、日本語の記事をあまり見かけないので流行っていないのかもと心配になりますね。ただとても簡単にwebpackの環境が導入できたのでLaravel Mixはとても気に入っています。簡単に使えるから特に迷うこともなくて記事が少ないというのもあるかもしれませんね。
開発しているWebサービス(LAR)について
LARは放送時期(クール)ごとにアニメを一覧で見ることができるサービスです。
ログイン不要で自由にアニメの一覧が作成できる「おすすめアニメメーカー」やアニメのランキングが自由に作成できる「アニメランキングメーカー」などの機能があります。
- 放送クールごとの一覧表示
- おすすめアニメメーカー
- アニメランキングメーカー
- お気に入り表示(ログイン後のみ)
- MY番組表表示(ログイン後のみ)
参考サイト