この記事はKotlin Advent Calendar 2019・16日目の記事です。
先日、第二回技術書同人誌博覧会にて、週刊IM@Study Vol.4という合同誌を頒布させていただきました。こちらに寄稿した記事『小鳥さんと一緒に100%Kotlinのサイト製作 〜frontend編〜』にて、性懲りもなくKotlin/JSネタで一筆したためたのですが、サンプル用のWebアプリを実装した時にハマった箇所がありました。今回はこちらを解決策と共に共有します。
Kotlin/JSを使ってWebアプリを実装する際、大まかな手順は以下のようになります。今回問題が発生したのは、2と3の手順です。
Kotlin->JS変換とWebpackのバンドル処理は、npmとGradleのどちらでも実行可能です。今回はフロントエンドエンジニアを想定読者としたため、Kotlin->JS変換にKotlinWebpackPluginというnpmモジュールを使う構成にしています。
そして、実際に実装したWebアプリがこちら。
→765プロスケジュールチェッカー: imasbook04.otonashi-kotlin.dev
→GitHub: subroh0508/imasbook04-sample
見ての通り、一切スタイルをいじらない素朴なWebアプリとなっています。使用しているライブラリも数少なく、出力されるバンドルファイルも大したサイズにはならないと高を括っていたのですが…
何も考えずproductionモードでビルドし、出力されたバンドルファイルのサイズはなんと1.12MB!流石にデカすぎる…、このままで本番環境にデプロイするのはめちゃくちゃ気が引ける…😣
というわけで、このデカすぎバンドルファイルを小さくしていきます。
Kotlin/JSには、JS変換時に使われていないメソッドを自動判別し、これらを削除するツール「kotlin-dce-js」が存在します(参考: kotlinlang.org/docs/reference/javascript-dce.html)。これを利用することで、Kotlin/JSの標準ライブラリ、およびKotlin製ライブラリのJS変換後のファイルサイズを大幅に削減することが可能になります。
KotlinWebpackPluginでは、optimize
オプションでこのツールを有効にすることができます。デフォルトの設定ではkotlin_build
というディレクトリにJS変換後のファイルが出力されるので、yarn run webpack
の実行後正しく出力されるか確認してみるとよいでしょう。
webpack.config.jsconst path = require('path');
module.exports = {
...,
plugins: [
new KotlinWebpackPlugin({
src: path.resolve(__dirname, 'src'),
optimize: true, // ←ココ
moduleName: 'bundlekt',
moduleKind: 'commonjs',
librariesAutoLookup: true,
verbose: true,
sourceMap: !isProduction,
packagesContents: [require('./package.json')],
}),
...,
],
};
※optimize
はKotlinWebpackPluginのREADME.mdに書いていないオプションなので注意!該当コードはこの辺りです。
さて、kotlin-dce-jsも有効になったところで、再度ビルドを走らせて見ましょう!どのくらい小さくなったかな…!
さっきと同じ1.12MB!全然変わってなーい!!!ナンデー???
kotlin-dce-jsを通したにも関わらず、バンドルサイズが全く変わらない問題。こちらは、JSモジュールを1つのバンドルファイルにまとめる過程で、kotlin-dce-jsを通す前のファイルを読み込んでしまうことが原因です。これを解決するには、webpack.config.js
に以下の記述を追加します。
webpack.config.jsconst path = require('path');
module.exports = {
...,
resolve: {
modules: [
path.resolve(__dirname, 'kotlin_build'),
path.resolve(__dirname, 'node_modules'),
],
},
...,
}
こうすることで、Kotlinの標準ライブラリの元データが含まれるnode_modules
ディレクトリより先に、kotlin-dce-jsを通したファイルの出力先であるkotlin_build
ディレクトリを読み込むよう指定できます(この設定はREADME.mdにしっかり書いてあります、ちゃんと読もうね自分🥺)。
これで準備は整った…!いざ、ビルド実行!!!
1.12MBあったバンドルファイルが185KBまで小さくなりました!大勝利!!!
Kotlin/JSのGradle Pluginでのkotlin-dce-jsサポートはv1.3.70で正式に入るようです。現状でも利用できないことはないはずですが、正直しんどかった記憶…🤔
毎度思うけど、Kotlin/JSはドキュメントが貧弱すぎてつらい
8月のKotlin Fest 2019では、主にGradleを使ったKotlin/JS製Webアプリの実装手順を解説しましたが、今回はnpm + Webpackで色々と頑張ってみました。Gradleとnpm、慣れ親しんだ方を自由に選択できるのはKotlin/JSの良さだと思っているので、もっと多くの人に触って欲しいなと思います。