wasm-bindgenを用いることでjsファイルで定義されたクラスや関数などをRustから利用できます.今回はそのwasm_bindgenとJavaScript等のバンドラであるwebpackを利用して,jsパッケージ(具体的にはplyr)をRustから利用してみます.また,バンドルサイズを小さくするためにjsパッケージをCDNからも利用してみます.作成したクレートはこちら.
JavaScriptのバンドル
まずはwebpackを利用するプロジェクトをwebpackのGetting Startedに従って作成します.次に利用したいjsライブラリであるplyrをnpmなどでインストールします.
npm i plyr
そしてエントリーとなるsrc/index.jsを作成します.本来はこちらにRust側で利用したい関数やクラスなどを定義するのですが,今回はデフォルトimportしたPlyrクラスをそのままexportします.
import Plyr from 'plyr';
export {Plyr};
次にバンドルについての設定をwebpack.config.jsに記述します.output.library.typeを'module'とすることでバンドルしたファイルをESモジュールとして読み込めるようになります.typeを'module'にするにはexperiments.outputModuleをtrueにする必要があるためそちらも設定しておきます.
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
experiments: {
outputModule: true,
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'main.js',
library: {
type: 'module',
},
},
};
これによって
npm run build
(webpackコマンドが実行される)で利用したパッケージを含めてバンドルされ,dist/main.jsが作成されます.
一方でパッケージをバンドルに含めずCDNで利用したい場合は以下のようにconfig.jsを設定します.先ほどの例と異なる部分はexternalsTypeとexternalsです.CDNとして読み込むためexternalsTypeには'global'を指定します.その場合externalsにはプロジェクトで利用するライブラリ名(plyr)と対応するCDNを読み込んだグローバル変数名('Plyr')を指定します.
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
experiments: {
outputModule: true,
},
output: {
path: path.resolve(__dirname, '../dist_cdn'),
filename: 'main.js',
library: {
type: 'module',
},
},
externalsType: 'global',
// externalsType: 'window', // こちらでもよい
externals: {
plyr: "Plyr"
}
};
これによって
npm run build -- --config cdn_webpack.config.js
でplyrが除外されてバンドルされ,dist_cdn/main.jsが作成されます.
この作成されたdist/main.jsとdist_cdn/main.jsをwasm_bindgenから読み込みます.
wasm-bindgenでjsファイルを読み込む
あとはwasm-bindgenの公式ドキュメントにあるようにwasm_bindgenアトリビュートにmoduleを指定してjsファイルを読み込みます.cfg_attrで指定したfeatureに応じて読み込まれるファイルを異なるようにすると便利です.以下ではPlyr型とそのコンストラクタを定義しています.このコンストラクタからは読み込んだjs側のPlyrクラスのコンストラクタが呼び出されます.
use wasm_bindgen::prelude::*;
#[cfg_attr(feature = "cdn", wasm_bindgen(module = "/dist_cdn/main.js"))]
#[cfg_attr(not(feature = "cdn"), wasm_bindgen(module = "/dist/main.js"))]
extern "C" {
#[derive(Debug, Clone)]
pub type Plyr;
#[wasm_bindgen(constructor)]
pub fn new(css_selector: &str) -> Plyr;
}
これで以下のように利用できるようになります.
let player = Plyr::new("#player");
moduleでパスを指定することで,クレートとして利用したときにもjsスニペットごと利用できます.