# LIFFプラグイン
# LIFFプラグインとは
LIFFプラグインとは、LIFF SDKを拡張できる機能です。LIFFプラグインを使うと、LIFF SDKに独自のAPIを追加したり、LIFF APIの挙動を変更したりできます。
LIFFプラグインの実態は、特定のプロパティやメソッドを持つ、オブジェクトあるいはクラスです。
# LIFFプラグインの動作環境
LIFFプラグインはLIFF v2.19.0以降で利用できます。
# LIFFプラグインを使用する
LIFFプラグインは、liff.use()
メソッドを使用して有効化します。liff.use()
メソッドにLIFFプラグインを渡すと、LIFFプラグインが有効化されます。LIFFプラグインを有効化すると、liff
オブジェクトが拡張され、LIFFプラグインのAPIを利用できるようになります。
以下は、LIFFプラグインGreetPlugin
を有効化し、liff.$greet.hello()
メソッドを実行する例です。
# LIFFプラグインがクラスの場合
LIFFプラグインがクラスの場合、liff.use()
メソッドにインスタンスを渡す必要があります。
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return {
hello: this.hello,
};
}
hello() {
console.log("Hello, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet.hello(); // Hello, World!
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
# LIFFプラグインがオブジェクトの場合
const hello = () => {
console.log("Hello, World!");
};
const greetPlugin = {
name: "greet",
install() {
return {
hello,
};
},
};
liff.use(greetPlugin);
liff.$greet.hello(); // Hello, World!
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
このように、LIFFプラグインを有効化すると、name
プロパティの値に$
の接頭語がついたプロパティがliff
オブジェクトに追加されます。これにより、LIFFプラグインのAPIをliff.${LIFFプラグインのnameプロパティの値}.{プロパティ}
やliff.${LIFFプラグインのnameプロパティの値}.{メソッド}()
の形式で利用できます。
# LIFFプラグインを作成する
LIFFプラグインは、name
プロパティとinstall()
メソッドを持つ、オブジェクトあるいはクラスとして作成できます。
以下は、APIとしてhello()
メソッドとgoodbye()
メソッドを提供する、LIFFプラグインGreetPlugin
の例です。
# LIFFプラグインがクラスの場合
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return {
hello: this.hello,
goodbye: this.goodbye,
};
}
hello() {
console.log("Hello, World!");
}
goodbye() {
console.log("Goodbye, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet.hello(); // Hello, World!
liff.$greet.goodbye(); // Goodbye, World!
# LIFFプラグインがオブジェクトの場合
const hello = () => {
console.log("Hello, World!");
};
const goodbye = () => {
console.log("Goodbye, World!");
};
const greetPlugin = {
name: "greet",
install() {
return {
hello,
goodbye,
};
},
};
liff.use(greetPlugin);
liff.$greet.hello(); // Hello, World!
liff.$greet.goodbye(); // Goodbye, World!
# nameプロパティ
name
プロパティは、LIFFプラグインの名前です。文字列で指定します。
指定した値は、liff.${LIFFプラグインのnameプロパティの値}
のように、liff
オブジェクトのプロパティ名となります。
# install()メソッド
install()
メソッドは、以下のことを行う関数です。
# LIFFプラグインの初期化処理を記述する
install()
メソッドは、LIFFプラグインの有効化時にliff.use()
メソッドによって実行されます。そのため、LIFFプラグインの初期化処理をinstall()
メソッド内に記述できます。
# LIFFプラグインのAPIを定義する
LIFFプラグインのAPIは、install()
メソッドの返り値として定義されます。オブジェクトを返すことで、複数のAPIを定義できます。
なお、LIFFプラグインのAPIが1つのみの場合、そのAPIを返り値とすることも可能です。以下は、install()
メソッドの返り値として、オブジェクトではなく関数を返す例です。
class GreetPlugin {
constructor() {
this.name = "greet";
}
install() {
return this.hello;
}
hello() {
console.log("Hello, World!");
}
}
liff.use(new GreetPlugin());
liff.$greet(); // Hello, World!
# install()メソッドの引数
install()
メソッドは、第1引数にcontext
オブジェクト、第2引数にoption
を取ります。
class GreetPlugin {
constructor() {
this.name = "greet";
}
install(context, option) {}
}
# context
オブジェクト
install()
メソッドの第1引数です。以下の2つのプロパティを持ちます。
プロパティ | 値 |
---|---|
liff | liff オブジェクト |
hooks | フックにコールバックを登録するためのメソッドを提供するオブジェクト |
# option
install()
メソッドの第2引数です。liff.use()
メソッドの第2引数に指定した値が渡されます。liff.use()
メソッドの第2引数が未指定の場合、option
の値はundefined
となります。
option
は、liff.use()
メソッド側からLIFFプラグインの挙動をカスタマイズできるようにする、といった用途に利用できます。
# フックについて
フックとは、LIFF APIの処理中の特定のタイミングで、事前に登録されたコールバックを実行させるためのLIFFプラグインの仕組みです。フックは、JavaScriptのイベント処理と同じように考えることができます。フックにコールバックを登録しておくと、フックが発火したタイミングで、コールバックが実行されます。
LIFF APIが提供するフックを利用するだけでなく、LIFFプラグインが独自のフックを提供することも可能です。
# LIFF APIのフック
現時点では、LIFF APIはliff.init()
メソッドのみ、フックを提供しています。
LIFF API | フック | フックの種類 | フックの発火タイミング |
---|---|---|---|
liff.init() メソッド | before フック | 非同期フック | liff.init() の呼び出し直後(LIFFアプリの初期化前) |
after フック | 非同期フック | successCallback の呼び出し直前(LIFFアプリの初期化後) |
# フックの種類
# 同期フック
同期フックは、登録されたコールバックを同期的に処理します。登録されたコールバックは、登録された順番に処理されます。登録されたコールバックの返り値は無視されます。
# 非同期フック
非同期フックは、登録されたコールバックを非同期的に処理します。登録されたコールバックは、Promise.all()
メソッドを使って、並列に処理されます。登録されたコールバックの返り値はPromise
オブジェクトである必要があります。
# フックにコールバックを登録する
フックにコールバックを登録するには、install()
メソッドのcontext.hooks
プロパティを使います。
以下は、liff.init()
メソッドのbefore
フックとafter
フックにコールバックを登録する例です。liff.init()
メソッドが実行されると、before
フックとafter
フックが発火し、登録されたコールバックが実行されます。
before
フックとafter
フックは非同期フックのため、Promise
オブジェクトを返す必要がある点に注意してください。
class GreetPlugin {
constructor() {
this.name = "greet";
}
install(context) {
context.hooks.init.before(this.initBefore);
context.hooks.init.after(this.initAfter);
return {
hello: this.hello,
goodbye: this.goodbye,
};
}
hello() {
console.log("Hello, World!");
}
goodbye() {
console.log("Goodbye, World!");
}
initBefore() {
console.log("before hook is called");
return Promise.resolve();
}
initAfter() {
console.log("after hook is called");
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff
.init({
liffId: "123456-abcedfg", // Use own liffId
})
.then(() => {
// ...
});
# フックを作成する
フックは、SyncHook
クラスあるいはAsyncHook
クラスのインスタンスとして作成できます。
フックの種類 | クラス |
---|---|
同期フック | SyncHook |
非同期フック | AsyncHook |
以下は、helloBefore
フックとhelloAfter
フックを作成する例です。SyncHook
クラスとAsyncHook
クラスは、@liff/hooks
パッケージからインポートする必要がある点に注意してください。
作成したフックを発火するには、SyncHook
クラスのインスタンスやAsyncHook
クラスのインスタンスのcall()
メソッドを実行します。
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call();
console.log("Hello, World!");
this.hooks.helloAfter.call();
}
goodbye() {
console.log("Goodbye, World!");
}
}
作成したフックは、別のLIFFプラグインがコールバックを登録するのに利用できます。以下は、LIFFプラグインGreetPlugin
のhelloBefore
フックとhelloAfter
フックにコールバックを登録する例です。
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call();
console.log("Hello, World!");
this.hooks.helloAfter.call();
}
goodbye() {
console.log("Goodbye, World!");
}
}
class OtherPlugin {
constructor() {
this.name = "other";
}
install(context) {
context.hooks.$greet.helloBefore(this.greetBefore);
context.hooks.$greet.helloAfter(this.greetAfter);
}
greetBefore() {
console.log("helloBefore hook is called");
}
greetAfter() {
console.log("helloAfter hook is called");
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff.use(new OtherPlugin());
liff.$greet.hello();
// helloBefore hook is called
// Hello, World!
// helloAfter hook is called
# call()
メソッド
call()
メソッドはフックを発火するための関数です。call()
メソッドには、任意の数の引数を渡すことができます。call()
メソッドに渡した引数は、フックに登録したコールバックが引数として受け取ることができます。
以下は、フックのcall()
メソッドに引数を渡し、それをコールバックが受け取る例です。
import { SyncHook, AsyncHook } from "@liff/hooks";
class GreetPlugin {
constructor() {
this.name = "greet";
this.hooks = {
helloBefore: new SyncHook(),
helloAfter: new AsyncHook(),
};
}
install(context) {
return {
hello: this.hello.bind(this),
goodbye: this.goodbye,
};
}
hello() {
this.hooks.helloBefore.call("foo");
console.log("Hello, World!");
this.hooks.helloAfter.call("foo", 0);
}
goodbye() {
console.log("Goodbye, World!");
}
}
class OtherPlugin {
constructor() {
this.name = "other";
}
install(context) {
context.hooks.$greet.helloBefore(this.greetBefore);
context.hooks.$greet.helloAfter(this.greetAfter);
}
greetBefore(foo) {
console.log(foo); // foo
}
greetAfter(foo, bar) {
console.log(foo, bar); // foo 0
return Promise.resolve();
}
}
liff.use(new GreetPlugin());
liff.use(new OtherPlugin());
liff.$greet.hello(); // Hello, World!
# 公式LIFFプラグイン
LINEでは、以下の公式LIFFプラグインを公開しています。
# LIFF Inspector
LIFF Inspectorは、LIFFアプリをデバッグするためのLIFFプラグインです。LIFF Inspectorを使うと、LIFFアプリを実行している端末とは別のPC上のChrome DevTools (opens new window)を使って、LIFFアプリをデバッグできます。
LIFF Inspectorについて詳しくは、GitHubのREADME (opens new window)やnpm (opens new window)の[Readme]タブを参照してください。
# LIFF Mock
LIFF Mockは、LIFFアプリのテストを簡単にするためのLIFFプラグインです。LIFF Mockを使うと、LIFF SDKにモックモードを追加できます。モックモードでは、LIFFアプリがLIFFサーバーから独立し、LIFF APIがモックデータを返すため、単体テストや負荷テストをより簡単に行うことができます。
LIFF Mockについて詳しくは、GitHubのREADME (opens new window)やnpm (opens new window)の[Readme]タブを参照してください。