JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q16516F
  • License MIT

Swc plugin implementation of react-refresh/babel

Package Exports

  • swc-plugin-react-refresh
  • swc-plugin-react-refresh/target/wasm32-wasi/release/swc_plugin_react_refresh.wasm

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (swc-plugin-react-refresh) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

swc-plugin-react-refresh

Swc plugin implementation of react-refresh/babel

[!IMPORTANT] A plugin for developing bundlers and this plugin is experimental.

  • Explore React components in module
    • Function expressions
    • Arrow function expressions
    • Class declarations
    • Import statements(default, named)
    • Export statements(default, named, named with declare)
  • Get component name from AST
  • Parse hook calls from AST
  • Parse HoC(High Order Component) expressions(React.memo, React.forwardedRef, and Custom HoC)
  • Generate signature key based on the order of hook call expressions

Setup

npm install swc-plugin-react-refresh
# or yarn
yarn add swc-plugin-react-refresh

Add plugin to your swc options.

import { transform } from '@swc/core';

await transform(code, {
  jsc: {
    experimental: {
      plugins: [
        // Add plugin here
        ['swc-plugin-react-refresh', {
          /**
           * moduleId: string;
           * 
           * Module id (eg. generated id by bundler)
           */
          moduleId: "",
          /**
           * skipEnvCheck?: boolean;
           * 
           * Plugin available on only development environment.
           * If you want to use plugin in production, set `skipEnvCheck` to `true`.
           */
          skipEnvCheck: true,
        }],
      ],
    },
  },
});

Finally, inject runtime code at the top of bundled source.

Runtime Code
const RefreshRuntime = require('react-refresh/runtime');


const ModuleMap = typeof WeakMap === 'function' ? WeakMap : Map;
const modules = new ModuleMap();

const createHmrContext = (type) => {
  if (!isReactRefreshBoundary(type)) {
    return {
      accept: () => undefined,
      dispose: () => undefined,
    };
  }

  const state = {
    timeout: null,
    accepted: false,
    disposed: false,
  };

  const hot = {
    accept: () => {
      if (state.disposed) {
        throw new Error('HMR module was disposed');
      }
  
      if (state.accepted) {
        throw new Error('HMR already accepted');
      }

      state.accepted = true;
      state.timeout = setTimeout(() => {
        state.timeout = null;
        RefreshRuntime.performReactRefresh();
      }, 50);
    },
    dispose: () => {
      state.disposed = true;
    },
  };

  if (modules.has(type)) {
    modules.get(type).dispose();
  }
  modules.set(type) = hot;

  return hot;
};

const isReactRefreshBoundary = (type) => {
  return RefreshRuntime.isLikelyComponentType(type) && !type.prototype.isReactComponent;
}

// `global` is platform dependent.
RefreshRuntime.injectIntoGlobalHook(global);
global.$RefreshReg$ = () => {};
global.$RefreshSig$ = () => (type) => type;
global.$RefreshRuntime$ = {
  getRegisterFunction: () => {
    return (type, id) => {
      if (!isReactRefreshBoundary(type)) return;
      RefreshRuntime.register(type, id);
    };
  },
  getCreateSignatureFunction: () => {
    return () => {
      const signature = RefreshRuntime.createSignatureFunctionForTransform();
      return (type, id, forceReset, getCustomHooks) => {
        if (!isReactRefreshBoundary(type)) return;
        signature(type, id, forceReset, getCustomHooks);
      }
    };
  },
  getContext: (type) => createHmrContext(type),
};

Development

cargo build

# release build
yarn build # target: wasm32-wasi
# or
cargo build-wasi --release # target: wasm32-wasi
cargo build-wasm32 --release # target: wasm32-unknown-unknown

# run unit tests
cargo test

# run on @swc/core (debug build required)
yarn build
yarn demo

License

MIT