Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re.pack Rspack (5.0.0-alpha.0) - Panic occurred at runtime. Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks. #748

Open
sahajarora1286 opened this issue Sep 12, 2024 · 1 comment
Assignees
Labels
status:new New issue, not reviewed by the team yet. type:bug A bug report.

Comments

@sahajarora1286
Copy link

Describe the bug

I am trying to upgrade from @callstack/repack v4 to v5.0.0-alpha.0.
I have followed the templates in the repack example as well as the official webpack -> rspack migration documentation to migrate from webpack to rspack.

I have a react-native super-app that leverages module-federation and exists as a monorepo.

Here's what my rspack.config.mjs file looks like for the host:

export default (env) => {
  console.log('using mobile webpack config...');
  const {
    mode = 'development',
    context = Repack.getDirname(import.meta.url),
    entry = './index.js',
    platform = process.env.PLATFORM,
    minimize = mode === 'production',
    devServer = undefined,
    bundleFilename = undefined,
    sourceMapFilename = undefined,
    assetsPath = undefined,
    reactNativePath = new URL('./node_modules/react-native', import.meta.url)
      .pathname,
  } = env;
  const dirname = Repack.getDirname(import.meta.url);

  if (!platform) {
    throw new Error('Missing platform');
  }

  /**
   * Depending on your Babel configuration you might want to keep it.
   * If you don't use `env` in your Babel config, you can remove it.
   *
   * Keep in mind that if you remove it you should set `BABEL_ENV` or `NODE_ENV`
   * to `development` or `production`. Otherwise your production code might be compiled with
   * in development mode by Babel.
   */
  process.env.BABEL_ENV = mode;

  return {
    mode,
    /**
     * This should be always `false`, since the Source Map configuration is done
     * by `SourceMapDevToolPlugin`.
     */
    devtool: false,
    context,
    /**
     * `getInitializationEntries` will return necessary entries with setup and initialization code.
     * If you don't want to use Hot Module Replacement, set `hmr` option to `false`. By default,
     * HMR will be enabled in development mode.
     */
    entry,
    resolve: {
      /**
       * `getResolveOptions` returns additional resolution configuration for React Native.
       * If it's removed, you won't be able to use `<file>.<platform>.<ext>` (eg: `file.ios.js`)
       * convention and some 3rd-party libraries that specify `react-native` field
       * in their `package.json` might not work correctly.
       */
      ...Repack.getResolveOptions(platform),
      tsConfig: './tsconfig.json',
    },
    /**
     * Configures output.
     * It's recommended to leave it as it is unless you know what you're doing.
     * By default Webpack will emit files into the directory specified under `path`. In order for the
     * React Native app use them when bundling the `.ipa`/`.apk`, they need to be copied over with
     * `Repack.OutputPlugin`, which is configured by default inside `Repack.RepackPlugin`.
     */
    output: {
      clean: true,
      hashFunction: 'xxhash64',
      path: path.join(dirname, 'build/generated', platform),
      filename: 'index.bundle',
      chunkFilename: '[name].chunk.bundle',
      publicPath: Repack.getPublicPath({ platform, devServer }),
    },
    /**
     * Configures optimization of the built bundle.
     */
    optimization: {
      /** Enables minification based on values passed from React Native CLI or from fallback. */
      minimize,
      /** Configure minimizer to process the bundle. */
      minimizer: [
        new TerserPlugin({
          test: /\.(js)?bundle(\?.*)?$/i,
          /**
           * Prevents emitting text file with comments, licenses etc.
           * If you want to gather in-file licenses, feel free to remove this line or configure it
           * differently.
           */
          extractComments: false,
          terserOptions: {
            format: {
              comments: false,
            },
          },
        }),
      ],
      chunkIds: 'named',
    },
    module: {
      rules: [
        Repack.REACT_NATIVE_LOADING_RULES,
        Repack.NODE_MODULES_LOADING_RULES,
        /* repack is symlinked to a local workspace */
        {
          test: /\.[jt]sx?$/,
          type: 'javascript/auto',
          include: [/repack[/\\]dist/],
          use: {
            loader: 'builtin:swc-loader',
            options: {
              env: { targets: { 'react-native': '0.74' } },
              jsc: { externalHelpers: true },
            },
          },
        },
        /* codebase rules */
        {
          test: /\.[jt]sx?$/,
          type: 'javascript/auto',
          exclude: [/node_modules/, /repack[/\\]dist/],
          use: {
            loader: 'builtin:swc-loader',
            /** @type {import('@rspack/core').SwcLoaderOptions} */
            options: {
              sourceMaps: true,
              env: {
                targets: { 'react-native': '0.74' },
              },
              jsc: {
                parser: {
                  syntax: 'typescript',
                },
                externalHelpers: true,
                transform: {
                  react: {
                    runtime: 'automatic',
                  },
                },
              },
            },
          },
        },
        {
          test: Repack.getAssetExtensionsRegExp(Repack.ASSET_EXTENSIONS),
          use: {
            loader: '@callstack/repack/assets-loader',
            options: {
              platform,
              devServerEnabled: Boolean(devServer),
            },
          },
        },
      ],
    },
    plugins: [
      new rspack.IgnorePlugin({ resourceRegExp: /@react-native-masked-view/ }),
      /**
       * Configure other required and additional plugins to make the bundle
       * work in React Native and provide good development experience with
       * sensible defaults.
       *
       * `Repack.RepackPlugin` provides some degree of customization, but if you
       * need more control, you can replace `Repack.RepackPlugin` with plugins
       * from `Repack.plugins`.
       */
      new Repack.RepackPlugin({
        context,
        mode,
        platform,
        devServer,
        output: {
          bundleFilename,
          sourceMapFilename,
          assetsPath,
        },
      }),
      new Repack.plugins.ModuleFederationPlugin({
        name: 'host',
        shared: {
          react: {
            ...Repack.Federated.SHARED_REACT,
            requiredVersion: '18.2.0',
            eager: true,
          },
          'react-native': {
            ...Repack.Federated.SHARED_REACT_NATIVE,
            requiredVersion: '0.74',
            eager: true,
          },
          reselect: {
            singleton: true,
            requiredVersion: monorepoDeps['reselect'],
            eager: true,
          },
          'react-redux': {
            singleton: true,
            requiredVersion: monorepoDeps['react-redux'],
            eager: true,
          },
          '@reduxjs/toolkit': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit'],
            eager: true,
          },
          '@reduxjs/toolkit/query': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit/query'],
            eager: true,
          },
          '@reduxjs/toolkit/query/react': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit/query/react'],
            eager: true,
          },
          '@react-navigation/native': {
            singleton: true,
            requiredVersion: monorepoDeps['@react-navigation/native'],
            eager: true,
          },
          '@react-navigation/native-stack': {
            singleton: true,
            requiredVersion: monorepoDeps['@react-navigation/native-stack'],
            eager: true,
          },
          'react-native-screens': {
            singleton: true,
            requiredVersion: monorepoDeps['react-native-screens'],
            eager: true,
          },
          'react-native-safe-area-context': {
            singleton: true,
            requiredVersion: monorepoDeps['react-native-safe-area-context'],
            eager: true,
          },
          'redux-persist': {
            singleton: true,
            requiredVersion: monorepoDeps['redux-persist'],
            eager: true,
          },
          '@react-native-async-storage/async-storage': {
            singleton: true,
            requiredVersion:
              monorepoDeps['@react-native-async-storage/async-storage'],
            eager: true,
          },
        },
      }),
      new rspack.EnvironmentPlugin({ MF_CACHE: null }),
      process.env.RSDOCTOR && new RsdoctorRspackPlugin(),
    ].filter(Boolean),
  };
};

When I try to start the host app using the command: react-native webpack-start --webpackConfig ./rspack.config.mjs --host 127.0.0.1, I get the following error:

Panic occurred at runtime. Please file an issue on GitHub with the backtrace below: https://github.com/web-infra-dev/rspack/issues
Message:  Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
Location: crates/rspack_binding_options/src/options/raw_devtool.rs:99

My motivation, and need, to get to Rspack from Webpack is to lower the build time it currently takes with webpack. The fact that with callstack/repack v4 we need to use webpack and babel-loader to transpile huge node_module files (for react-native compatibility) is a pain and leads to really slow compilation of the host and other mini-apps that have bare minimal code (2-4 source files).
I have learnt that swc is a much faster alternative to babel-loader and hence I'd love to be able to leverage it in my project setup.

Any help with resolving this issue and getting my project to successfully work with @callstack/repack v5.0.0-alpha.0 and rspac + swc-loader would be highly appreciated.

Thanks !

System Info

System:
  OS: macOS 14.5
  CPU: (10) arm64 Apple M1 Max
  Memory: 104.30 MB / 64.00 GB
  Shell:
    version: 3.2.57
    path: /bin/bash
Binaries:
  Node:
    version: 18.18.0
    path: ~/.nvm/versions/node/v18.18.0/bin/node
  Yarn:
    version: 1.19.0
    path: /opt/homebrew/bin/yarn
  npm:
    version: 9.8.1
    path: ~/.nvm/versions/node/v18.18.0/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.15.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK: Not Found
  Android SDK: Not Found
IDEs:
  Android Studio: 2021.3 AI-213.7172.25.2113.9123335
  Xcode:
    version: /undefined
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.5
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react: Not Found
  react-native:
    installed: 0.74.5
    wanted: "0.74"
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Re.Pack Version

5.0.0-alpha.0

Reproduction

n/a

Steps to reproduce

Use the following config for rspack.config.js :

import path from 'path';
import TerserPlugin from 'terser-webpack-plugin';
import * as Repack from '@callstack/repack';
import monorepoPackage from '../../package.json' assert { type: 'json' };
import rspack from '@rspack/core';
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';

const monorepoDeps = monorepoPackage.dependencies;

/**
 * More documentation, installation, usage, motivation and differences with Metro is available at:
 * https://github.com/callstack/repack/blob/main/README.md
 *
 * The API documentation for the functions and plugins used in this file is available at:
 * https://re-pack.netlify.app/
 */

/**
 * Webpack configuration.
 * You can also export a static object or a function returning a Promise.
 *
 * @param env Environment options passed from either Webpack CLI or React Native CLI
 *            when running with `react-native start/bundle`.
 */
export default (env) => {
  console.log('using mobile webpack config...');
  const {
    mode = 'development',
    context = Repack.getDirname(import.meta.url),
    entry = './index.js',
    platform = process.env.PLATFORM,
    minimize = mode === 'production',
    devServer = undefined,
    bundleFilename = undefined,
    sourceMapFilename = undefined,
    assetsPath = undefined,
    reactNativePath = new URL('./node_modules/react-native', import.meta.url)
      .pathname,
  } = env;
  const dirname = Repack.getDirname(import.meta.url);

  if (!platform) {
    throw new Error('Missing platform');
  }

  /**
   * Depending on your Babel configuration you might want to keep it.
   * If you don't use `env` in your Babel config, you can remove it.
   *
   * Keep in mind that if you remove it you should set `BABEL_ENV` or `NODE_ENV`
   * to `development` or `production`. Otherwise your production code might be compiled with
   * in development mode by Babel.
   */
  process.env.BABEL_ENV = mode;

  return {
    mode,
    /**
     * This should be always `false`, since the Source Map configuration is done
     * by `SourceMapDevToolPlugin`.
     */
    devtool: false,
    context,
    /**
     * `getInitializationEntries` will return necessary entries with setup and initialization code.
     * If you don't want to use Hot Module Replacement, set `hmr` option to `false`. By default,
     * HMR will be enabled in development mode.
     */
    entry,
    resolve: {
      /**
       * `getResolveOptions` returns additional resolution configuration for React Native.
       * If it's removed, you won't be able to use `<file>.<platform>.<ext>` (eg: `file.ios.js`)
       * convention and some 3rd-party libraries that specify `react-native` field
       * in their `package.json` might not work correctly.
       */
      ...Repack.getResolveOptions(platform),
      tsConfig: './tsconfig.json',
    },
    /**
     * Configures output.
     * It's recommended to leave it as it is unless you know what you're doing.
     * By default Webpack will emit files into the directory specified under `path`. In order for the
     * React Native app use them when bundling the `.ipa`/`.apk`, they need to be copied over with
     * `Repack.OutputPlugin`, which is configured by default inside `Repack.RepackPlugin`.
     */
    output: {
      clean: true,
      hashFunction: 'xxhash64',
      path: path.join(dirname, 'build/generated', platform),
      filename: 'index.bundle',
      chunkFilename: '[name].chunk.bundle',
      publicPath: Repack.getPublicPath({ platform, devServer }),
    },
    /**
     * Configures optimization of the built bundle.
     */
    optimization: {
      /** Enables minification based on values passed from React Native CLI or from fallback. */
      minimize,
      /** Configure minimizer to process the bundle. */
      minimizer: [
        new TerserPlugin({
          test: /\.(js)?bundle(\?.*)?$/i,
          /**
           * Prevents emitting text file with comments, licenses etc.
           * If you want to gather in-file licenses, feel free to remove this line or configure it
           * differently.
           */
          extractComments: false,
          terserOptions: {
            format: {
              comments: false,
            },
          },
        }),
      ],
      chunkIds: 'named',
    },
    module: {
      rules: [
        Repack.REACT_NATIVE_LOADING_RULES,
        Repack.NODE_MODULES_LOADING_RULES,
        /* repack is symlinked to a local workspace */
        {
          test: /\.[jt]sx?$/,
          type: 'javascript/auto',
          include: [/repack[/\\]dist/],
          use: {
            loader: 'builtin:swc-loader',
            options: {
              env: { targets: { 'react-native': '0.74' } },
              jsc: { externalHelpers: true },
            },
          },
        },
        /* codebase rules */
        {
          test: /\.[jt]sx?$/,
          type: 'javascript/auto',
          exclude: [/node_modules/, /repack[/\\]dist/],
          use: {
            loader: 'builtin:swc-loader',
            /** @type {import('@rspack/core').SwcLoaderOptions} */
            options: {
              sourceMaps: true,
              env: {
                targets: { 'react-native': '0.74' },
              },
              jsc: {
                parser: {
                  syntax: 'typescript',
                },
                externalHelpers: true,
                transform: {
                  react: {
                    runtime: 'automatic',
                  },
                },
              },
            },
          },
        },
        {
          test: Repack.getAssetExtensionsRegExp(Repack.ASSET_EXTENSIONS),
          use: {
            loader: '@callstack/repack/assets-loader',
            options: {
              platform,
              devServerEnabled: Boolean(devServer),
            },
          },
        },
      ],
    },
    plugins: [
      new rspack.IgnorePlugin({ resourceRegExp: /@react-native-masked-view/ }),
      /**
       * Configure other required and additional plugins to make the bundle
       * work in React Native and provide good development experience with
       * sensible defaults.
       *
       * `Repack.RepackPlugin` provides some degree of customization, but if you
       * need more control, you can replace `Repack.RepackPlugin` with plugins
       * from `Repack.plugins`.
       */
      new Repack.RepackPlugin({
        context,
        mode,
        platform,
        devServer,
        output: {
          bundleFilename,
          sourceMapFilename,
          assetsPath,
        },
      }),
      new Repack.plugins.ModuleFederationPlugin({
        name: 'host',
        shared: {
          react: {
            ...Repack.Federated.SHARED_REACT,
            requiredVersion: '18.2.0',
            eager: true,
          },
          'react-native': {
            ...Repack.Federated.SHARED_REACT_NATIVE,
            requiredVersion: '0.74',
            eager: true,
          },
          reselect: {
            singleton: true,
            requiredVersion: monorepoDeps['reselect'],
            eager: true,
          },
          'react-redux': {
            singleton: true,
            requiredVersion: monorepoDeps['react-redux'],
            eager: true,
          },
          '@reduxjs/toolkit': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit'],
            eager: true,
          },
          '@reduxjs/toolkit/query': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit/query'],
            eager: true,
          },
          '@reduxjs/toolkit/query/react': {
            singleton: true,
            requiredVersion: monorepoDeps['@reduxjs/toolkit/query/react'],
            eager: true,
          },
          '@react-navigation/native': {
            singleton: true,
            requiredVersion: monorepoDeps['@react-navigation/native'],
            eager: true,
          },
          '@react-navigation/native-stack': {
            singleton: true,
            requiredVersion: monorepoDeps['@react-navigation/native-stack'],
            eager: true,
          },
          'react-native-screens': {
            singleton: true,
            requiredVersion: monorepoDeps['react-native-screens'],
            eager: true,
          },
          'react-native-safe-area-context': {
            singleton: true,
            requiredVersion: monorepoDeps['react-native-safe-area-context'],
            eager: true,
          },
          'redux-persist': {
            singleton: true,
            requiredVersion: monorepoDeps['redux-persist'],
            eager: true,
          },
          '@react-native-async-storage/async-storage': {
            singleton: true,
            requiredVersion:
              monorepoDeps['@react-native-async-storage/async-storage'],
            eager: true,
          },
        },
      }),
      new rspack.EnvironmentPlugin({ MF_CACHE: null }),
      process.env.RSDOCTOR && new RsdoctorRspackPlugin(),
    ].filter(Boolean),
  };
};

Try to start the dev server using:
react-native webpack-start --webpackConfig ./rspack.config.mjs

@sahajarora1286 sahajarora1286 added status:new New issue, not reviewed by the team yet. type:bug A bug report. labels Sep 12, 2024
@sahajarora1286 sahajarora1286 changed the title Re.pack Rspack (5.0.0-alpha.0) - Panic occurred at runtime. Please file an issue on GitHub with the backtrace below: https://github.com/web-infra-dev/rspack/issues Message: Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks. Location: crates/rspack_binding_options/src/options/raw_devtool.rs:99 Re.pack Rspack (5.0.0-alpha.0) - Panic occurred at runtime. Message: Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks. Location: crates/rspack_binding_options/src/options/raw_devtool.rs:99 Sep 12, 2024
@sahajarora1286 sahajarora1286 changed the title Re.pack Rspack (5.0.0-alpha.0) - Panic occurred at runtime. Message: Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks. Location: crates/rspack_binding_options/src/options/raw_devtool.rs:99 Re.pack Rspack (5.0.0-alpha.0) - Panic occurred at runtime. Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks. Sep 12, 2024
@jbroma
Copy link
Member

jbroma commented Sep 13, 2024

Hi @sahajarora1286, could you please create a reproduction repository with this issue? It really saves a lot of time and allows us to handle issues more swiftly instead of trying to recreate this on our own, thanks!

@jbroma jbroma self-assigned this Sep 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:new New issue, not reviewed by the team yet. type:bug A bug report.
Projects
None yet
Development

No branches or pull requests

2 participants