expo bare workflowの環境で、wasmを使用したライブラリを読み込んで、expo build:webを通す方法です。(=== React Native for Webでwasmを使ったパッケージを読み込みたい)
ちなみに、私が使用したいライブラリは、https://github.com/VirgilSecurity/virgil-e3kit-js です。
何も考えずに expo build:webすると以下のエラーがでます。
Module parse failed: magic header not detected
File was processed with these loaders:
* ./node_modules/@expo/webpack-config/node_modules/file-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
Error: magic header not detected
webpack.config.jsを設定して、エラーが出ないようにします。以下のコマンドで、webpack.config.jsを選択するとwebpack.config.jsが作らます。同時に@expo/webpack-configをインストールするか聞かれるのでインストールします。
expo customize:web
file-loaderもインストールしておきます。
yarn add -D file-loader
webpack.config.jsを以下のように編集します。
ポイントは、@expo/webpack-configでは wasmが読み込まれないように一旦excludeに入れておいて、あらためて自分が設定したfile-loaderでwasmを読み込むことです。
const createExpoWebpackConfigAsync = require('@expo/webpack-config');
module.exports = async function (env, argv) {
let config = await createExpoWebpackConfigAsync(env, argv);
const wasmExtensionRegExp = /\.wasm$/;
config.resolve.extensions.push('.wasm');
//node_modules/@expo/webpack-config/webpack/loaders/createAllLoaders.jsのfile-loaderで
// export default **** のwasmがstatic/media/の中に作られて、それを読み込もうとしてエラーになるので
//wasmをそこでは処理しないようにexcludeに追加する。
config.module.rules.forEach((rule) => {
(rule.oneOf || []).forEach((oneOf) => {
if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
// make file-loader ignore WASM files
oneOf.exclude.push(wasmExtensionRegExp);
}
});
});
//あらためて自分でfile-loaderを設定すると、wasmのバイナリデータのままstatic/jsに出力されるので、
//問題なく読み込めるようになる。
config.module.rules.push({
test: wasmExtensionRegExp,
type: 'javascript/auto',
use: [{ loader: require.resolve('file-loader'), options: { outputPath: 'static/js' } }],
});
return config;
};
expo web:buidが通って、web-build/static/jsの中にバイナリのwasmファイルが出来ていればOKです。yarn webでアプリを起動して動作確認できれば大成功!
出来てしまえば簡単ですが、ググっても、react-app-rewiredとwasm-loaderを使うとできるとか、webpack5の方法とかは出てくるものの、どれも環境が微妙に違って上手くいかず、苦労したので共有しておきます。