webpack 入門 ~ Babel, Polyfill を使って快適 ES6 ライフ ~

目次

はじめに

kintone の JavaScript カスタマイズを開発しているときに、誰しも "Internet Explorer 11 で動かない!" ことを体験したことがあると思います。
こういった特定のブラウザーでプログラムが動作しない問題を解決するために Babel, Polyfill, webpack というツールを利用するのがスタンダードな解決策になっています。
本記事ではこの 3 つのツールを kintone カスタマイズで利用する方法を紹介します。

チュートリアルで扱う node, npm, npx コマンドは https://nodejs.org/ (External link) でインストーラーをダウンロードして node.js をインストールすると自動的にインストールされます。
インストール方法、node, npm, npx コマンドが何を意味しているかは本記事では取り扱いません。

Babel と Polyfill について

JavaScript は日々進化しており、ES5, ES6(ES2015), ES2016 といったバージョンがあることはご存じでしょうか?
JavaScript の進化には 2 つの側面があります。
1 つはプログラミング言語の拡張、もうひとつは標準ライブラリの拡張です。
しかし、各ブラウザー間でサポートされる機能が異なってしまいます。
参考: ES6 のブラウザ間の実装状況 (External link)

プログラミング言語の拡張

たとえば ES6 の JavaScript ではテンプレート文字列という文法を利用できます。
文字列の中で変数を展開できるだけでなく、文字列中に改行が含まれても大丈夫になります。

1
2
3
4
5
6
const es6Name = 'john';
console.log(`hello ${es6Name} . nice to meet you`);

// ES5
const name = 'john';
console.log('hello ' + name + ' . nice to meet you');

プログラムが簡潔にかけて気持ちいいですね!
しかし、このテンプレート文字列は Internet Explorer 11 では動作せず、JavaScript を解釈する時点でエラーになってしまいます。

こういった問題を解決するのが Babel (External link) です。
ES6 のコードを ES5 で動作するようにコードを変換してくれます。
コード変換の動作は Babel の公式サイトで確認できます。

標準ライブラリの拡張

文法の進化だけでなく、JavaScript のビルトインオブジェクトライブラリも進化しています。

たとえば ES6 には Object.values という便利メソッドが追加されています。

1
2
const object = {a: 'sample', b: 42, c: false};
console.log(Object.values(object)); // output: ["sample", 42, false];

ですがこれも Internet Explorer 11 では未実装のため動作しません。
こういったブラウザーごとの実装・未実装を埋めてくれるのが Polyfill です。

Polyfill は未実装のメソッドを見つけると、Polyfill ライブラリが読み込まれた時点で実装を追加してくれます。
そのため、Internet Explorer 11 などの環境でも Object.values を利用できます。

polyfill.io (External link) というサービスが CDN として公開されていますので、こちらを利用できます。

webpack について

webpack (External link) は JavaScript のビルドツールです。
JavaScript をブラウザーで動かすために必要なライブラリをバンドルしたり、プログラミング言語の変換をします。

webpack は ES6 で導入された import (External link) , export (External link) を解釈して、必要なライブラリやモジュールをバンドルしてくれます。

本記事では webpack の中に Babel と Polyfill を組み込んで動作する例を解説します。
これで最低限のツールの知識は説明し終えたのでチュートリアルにトライしてみましょう。

チュートリアル

ES6 の文法を使って kintone カスタマイズの実装をしてみましょう。

Step1 : npm を使ってプロジェクトを初期化する

1
npm init

以後の作業はプロジェクト・ディレクトリーで作業するものとします。

Step2 : webpack, Babel などのツールをインストールする

1
2
npm install -D webpack webpack-cli webpack-dev-server \
                        babel-loader @babel/core @babel/preset-env core-js@3
  • webpack ... webpack の本体
  • webpack-cli ... コマンドラインから webpack を利用するためのツール
  • webpack-dev-server ... 開発中プログラムをローカルホスト上でホスティングしてくれる開発ツール
  • babel-loader ... Babel の webpack プラグイン
  • @babel/core ... Babel の本体
  • @babel/preset-env ... Babel の JavaScript の変換ツール
  • core-js ... JavaScript の標準ライブラリが定義されており Polyfill を組み込んで利用できる。

Step3 : webpack.config.js を配置する

npm init したのと同じディレクトリーに webpack.config.js を配置します。

 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
28
29
30
31
32
33
34
35
36
37
38
const path = require('path');

module.exports = {
  entry: {
    'kintone-create-edit-show': './src/kintone-create-edit-show.js'
  },
  // webpack 5 を利用していて、IE 対応する場合は以下のコメントを外す
  // target: ['web', 'es5'],
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: 3
                }
              ]
            ]
          }
        }
      }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  externals: {
    jquery: 'jQuery'
  }
};
webpack.config.js の設定項目

kintone でカスタマイズする上で最低限知っておくと良さそうな設定項目を紹介します。
もっと複雑なこともできますが、詳細は webpack のドキュメント (External link) を参照してください。

entry

JavaScript のエントリーポイントを指定します。
kintone カスタマイズの場合、kintone.events.on メソッドが書いてあるプログラムになります。
オブジェクトを設定し、サンプルプログラムだと、kintone-create-edit-show のエントリーポイントを作っています。

target

ビルド後のファイルがどの環境に向けたファイルかを指定します。
指定しない場合、デフォルトで ['web']が設定されています(参照: target (External link)
ただし、webpack 5 でビルドした場合、Internet Explorer に対応していない構文が出力されます。
webpack 5 で Internet Explorer に対応する場合には、['web', 'es5']を指定します(上記サンプルのコメントを外してください)。

module

JavaScript の変換ルールを書きます。
test の中で指定されている正規表現にマッチした場合、Babel の変換プログラムが動作します。
今回の場合は、.js, mjs にマッチするファイルが読み込まれた場合、Babel による自動変換の対象として設定しています。

output

ビルドした JavaScript を出力するディレクトリーを設定します。
path は出力先のディレクトリー、filename はファイル名です。
path がわかりにくいですが、package.json が配置されているのと同じディレクトリーに dist というディレクトリーが作られて、その下にビルドした JavaScript が配置されます。
filename の [name]ですが、entry で指定したキー名をファイル名として文字列を自動的に設定してくれます。

externals

kintone の JS カスタマイズではアップロードできるファイルの大きさに制限があります。
一方で、webpack は利用しているライブラリをひとつのファイルにまとめます。
このため、webpack でビルドしたファイルは大きくなりやすい特徴があるため注意してください。
jQuery などグローバル変数を定義するタイプのライブラリなどを externals に設定しておくと、webpack は jQuery がソースコードで import されていても無視してくれます。

Step4 : ES6 を使って JS カスタマイズを書いてみよう!

サンプルプログラムでは ES6 で導入された文法やライブラリを使った簡単なプログラムを書いています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import jQuery from 'jquery';
const events = [
  'app.record.create.show',
  'app.record.edit.show',
];
kintone.events.on(events, (ev) => {
  const el = kintone.app.record.getHeaderMenuSpaceElement();
  const hello = 'hello';
  const world = 'world!';
  const message = {
    hello,
    world,
  };
  const copied = Object.assign({}, message);
  jQuery(el).append(`<div>${copied.hello} ${copied.world}!</div>`);
});

作業フォルダー内に「src」フォルダーを用意し、「kintone-create-edit-show.js」というファイル名で保存してください。
webpack.config.js の entry ポイントと合わせてください。

Step5 : ビルドしてみよう!

次のコマンドを実行すると webpack が JavaScript をビルドしてくれます。

1
2
3
npx webpack --mode development # 開発
# リリース時は次のコマンドで圧縮なども実施してくれる
# npx webpack --mode production  

--mode developmentproduction が指定可能です。開発中は development を指定します。
ビルドが完了すると dist ディレクトリーに kintone-create-edit-show.js が作成されているので、アップロードして動作確認してみましょう。

webpack-dev-server というツールもあります。これは別記事で解説させていただきます。

Step6 : アップロードしてみよう

ビルドしたプログラムを kintone にアップロードしてみましょう。
kintone-create-edit-show.js をアップロードします。
jQuery を別途カスタマイズとして登録するのを忘れないようにしてください。

Internet Explorer でも動作するのがわかると思います。

Chrome ブラウザーのコンソールで webpack でビルドしたプログラムを確認してみましょう。
テンプレート文字列が変換されているのを確認できると思います。

Step7 : import、export を体験してみよう

全角半角を変換するオープンソースライブラリを npm install でインストールして import, export を使って実装してみます。

1
npm install moji

全角半角を変換する実装を作成、export してみます。(src/hankaku.js)

1
2
import moji from 'moji';
export const zenkakuToHankaku = (value) => moji(value).convert('ZE', 'HE').toString();

kintone.events.on を書くファイルで import します。(src/kintone-create-edit-submit.js)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {zenkakuToHankaku} from './hankaku';

const events = [
  'app.record.create.submit',
  'app.record.edit.submit'
];
kintone.events.on(events, (ev) => {
  if (ev.record.文字列__1行_.value) {
    ev.record.文字列__1行_.value = zenkakuToHankaku(ev.record.文字列__1行_.value);
  }
  return ev;
});

webpack.config.js を修正する必要があります。サンプルコードのリポジトリ(後述)にあるので割愛します。

再度ビルドすると 2 つのファイルが作成されます。

  • 新規レコード、レコード修正画面を開いたときのファイル
  • 追加・更新時のイベント処理用ファイル

全角を半角に変換するメソッドは利用しているライブラリと一緒にイベント処理用のファイルの中にバンドルされています。

チュートリアルは以上です。お疲れさまでした。

参考: サンプルコード (External link)

注意点: Proxy だけには注意しましょう

Babel の制限事項として次のようなものがあります。

Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled. See support in various JavaScript engines (External link) .( Babel の公式サイトから引用 (External link)

ES5 から使える Proxy だけは制限事項になっています。
このため Internet Explorer 11 では Proxy を利用していると原因でエラーになってしまいます。
webpack を使うことでオープンソースのライブラリを使いやすくなりますが、ライブラリを利用する際は、念のためサポートブラウザーを一度確認してから使うようにしましょう。

おまけ:最近はこんな書き方ができるようになってます!

モダンな JavaScript からお気に入り機能を紹介して終わりたいと思います。

const, let

  • ブロックスコープ内で const で宣言された変数は書き換えるとエラーになります。
  • ブロックスコープ内で let で宣言された変数は書き換えることができます。

ブロックスコープを外れるとその変数は参照できなくなります。

参考: const (External link) , let (External link)

テンプレート文字列

改行や変数の埋め込みをしやすい文法が使えるようになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const message = 'hello world';
`
This is string template.
${message}.
`;
// output:
//
// This is string template.
// hello world.
//

参考: テンプレートリテラル (テンプレート文字列) (External link)

export, import

モジュール機能を実現するために導入された文法です。JavaScript でモジュール機能が使えます。
グローバルにメソッド定義するのを避けつつモジュール機能を利用できます
kintone カスタマイズの場合は webpack を使ってビルドするようにしましょう。

export
1
2
3
4
// functions.js
export function sum(a, b) {
  return a + b;
}
import
1
import {sum} from './functions';

参考: export (External link) , import (External link)

分割代入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
    const [a, b] = [10, 20];
    console.log(a); // 10
    console.log(b); // 20
}
{
    const [a, b, ...rest] = [10, 20, 30, 40, 50];
    console.log(a); // 10
    console.log(b); // 20
    console.log(rest); // [30, 40, 50]
}
{
    const ({ a, b } = { a: 10, b: 20 });
    console.log(a); // 10
    console.log(b); // 20
}

配列もしくはオブジェクトのプロパティの一部の値を簡単に取り出せるようになりました。

参考: 分割代入 (External link)

オブジェクト初期化子

今まではオブジェクトのキー名を必ず渡す必要がありましたが、変数をそのままオブジェクトのリテラルの中にわたすと、そのままオブジェクトのプロパティとして適用してくれます。

1
2
3
4
5
6
7
8
9
const a = 1;
const b = 2;
const c = 3;
const d = {
  a,
  b,
  c,
  e: 'hello!'
};

参考: オブジェクト初期化子 (External link)

アロー関数

関数を簡潔に書けるようになりました。

1
const sum = (a, b) => a + b;

参考: アロー関数式 (External link)

おわりに

お疲れさまでした。
webpack, Babel, Polyfill を活用して JavaScript 開発の面倒なところを避けつつ、快適な JavaScript ライフをお過ごしください!

このチュートリアルでは毎回ビルドしていますが更新された JavaScript を検知して自動的に再ビルドしてくれるしくみもあります。
開発中はこちらを使うと JavaScript 更新の手間が省けます。
こちらの記事も執筆予定です。次回作にご期待ください!

information

この Tips は、2019 年 2 月版 kintone で動作を確認しています。