addon-react-native-web icon indicating copy to clipboard operation
addon-react-native-web copied to clipboard

react native skia configuration with react native web

Open YOEL311 opened this issue 1 year ago • 5 comments

I try to use it with skin in my components project

but I got an error when I came to the web

Error: Cannot read properties of undefined (reading 'Matrix')
  at new JsiRenderNode (/vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:1408:29))
  at new GroupNode (/vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:881:5))
  at JsiSkDOM.Group (/vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:933:120))
  at new Container (/vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:5355:26))
  at new SkiaRoot (/vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:5776:22))
  at /vendors-node_modules_shopify_react-native-skia_lib_module_index_js.iframe.bundle.js:5267:69
  at mountMemo (/vendors-node_modules_babel_runtime_helpers_asyncToGenerator_js-node_modules_babel_runtime_hel-6ba1b4.iframe.bundle.js:41175:19))
  at Object.useMemo (/vendors-node_modules_babel_runtime_helpers_asyncToGenerator_js-node_modules_babel_runtime_hel-6ba1b4.iframe.bundle.js:41620:16))
  at useMemo (/vendors-node_modules_babel_runtime_helpers_asyncToGenerator_js-node_modules_babel_runtime_hel-6ba1b4.ifram

I reproduce this error in the repo

https://github.com/YOEL311/storybookPublic reproduce step

git clone
cd
git switch main
yarn
yarn storybook

I tried all ways from this page but I already get the error https://shopify.github.io/react-native-skia/docs/getting-started/web

YOEL311 avatar May 09 '24 13:05 YOEL311

I solved that by adding to my .storybook/main.js file the configuration like that

However, I need to use WithSkiaWeb on each component that requires Skia, and this approach is causing various problems with both the props and the native side.

To address this, can I initialize Skia at the entry point of the web application with the above code?

Additionally, could you please clarify when the AppRegistry for the web application is registered?

import { LoadSkiaWeb } from "@shopify/react-native-skia/lib/module/web";
LoadSkiaWeb().then(async () => {
  const App = (await import("./src/App")).default;
  AppRegistry.registerComponent("Example", () => App);
});

my .storybook/main.js file

const path = require('path');
const fs = require('fs');
const { sources } = require('webpack'); // Ensure webpack is imported to use its native objects and functions.
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
/** @type { import('@storybook/react') } */
const config = {
  stories: ['../src/components/**/*.stories.?(ts|tsx|js|jsx)'],
  addons: [
    'storybook-addon-deep-controls',
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToAlias: {
          'react-native-linear-gradient': 'react-native-web-linear-gradient',
        },
        modulesToTranspile: [
          'react-native-reanimated',
        ],
        babelPlugins: [
          '@babel/plugin-proposal-export-namespace-from',
          'react-native-reanimated/plugin',
        ],
      },
    },
  ],
  framework: {
    name: '@storybook/react-webpack5',
    options: {},
  },
  docs: {
    autodocs: true,
  },
  webpackFinal: async (webpackConfig) => {
    webpackConfig.resolve.alias['@react-native-cookies/cookies'] = path.resolve(
      __dirname,
      '../mocks/cookies.js',
    );

    webpackConfig.resolve.alias['@react-native-community/blur'] = path.resolve(
      __dirname,
      '../mocks/blur.js',
    );

    const fileLoaderRule = webpackConfig.module.rules.find((rule) =>
      rule.test.test('.svg'),
    );
    fileLoaderRule.exclude = /\.svg$/;
    webpackConfig.module.rules.push({
      test: /\.svg$/,
      // exclude: /node_modules/,
      use: [{ loader: '@svgr/webpack' }],
    });

    // CopyPlugin for canvaskit.wasm
    webpackConfig.plugins.push(new NodePolyfillPlugin());

    // CopyPlugin for canvaskit.wasm
    class CopySkiaPlugin {
      apply(compiler) {
        compiler.hooks.thisCompilation.tap('AddSkiaPlugin', (compilation) => {
          compilation.hooks.processAssets.tapPromise(
            {
              name: 'copy-skia',
              stage:
                compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
            },
            async () => {
              const src = require.resolve(
                'canvaskit-wasm/bin/full/canvaskit.wasm',
              );
              if (!compilation.getAsset(src)) {
                compilation.emitAsset(
                  'canvaskit.wasm',
                  new sources.RawSource(await fs.promises.readFile(src)),
                );
              }
            },
          );
        });
      }
    }

    webpackConfig.plugins.push(new CopySkiaPlugin());

    // Alias updates for react-native-reanimated
    webpackConfig.resolve.alias['react-native-reanimated'] = require.resolve(
      'react-native-reanimated',
    );

    webpackConfig.resolve.alias[
      'react-native/Libraries/Image/AssetRegistry'
    ] = false;

    return webpackConfig;
  },
};

export default config;

YOEL311 avatar May 13 '24 12:05 YOEL311

AppRegistry.registerComponent does not seem ideal here. It's probably easier for you to use <WithSkiaWeb> as a decorator when running on the web.

dannyhw avatar May 13 '24 13:05 dannyhw

Decoratore cannot help me here because is get the Story as component In this case I need to import or require the component only after the script of Skia is loaded

YOEL311 avatar May 13 '24 16:05 YOEL311

you can use a custom render function, that might work better

dannyhw avatar May 13 '24 17:05 dannyhw

Hi @dannyhw I appreciate your work

This is what I did, but I had some problems with it that I thought could be solved in a better way with LoadSkiaWeb .

YOEL311 avatar May 13 '24 18:05 YOEL311