An official SWC plugin can be used for SSR and easier debugging experience in SWC-powered projects, like Next.js or Vite with vite-react-swc plugin.
The plugin has the same functionality as the built-in babel-plugin.
It provides all Units with unique SIDs (Stable Identifier) and name, as well as other debug information.
This SWC plugin, along with all other SWC plugins, is currently considered experimental and unstable.
SWC and Next.js might not follow semver when it comes to plugin compatibility.
Installation
Install @effector/swc-plugin using your preferred package manager.
npm install -ED @effector/swc-pluginVersioning
To avoid compatibility issues caused by breaking changes in SWC or Next.js, this plugin publishes different ‘labels’ for different underlying @swc/core. Refer to the table below to choose the correct plugin version for your setup.
For better stability, we recommend pinning both your runtime (like Next.js or @swc/core) and the @effector/swc-plugin version.
Use the --exact/--save-exact option in your package manager to install specific, compatible versions. This ensures updates to one dependency don’t break your application.
@swc/core version | Next.js version | Correct plugin version |
|---|---|---|
>=1.4.0 <1.6.0 | >=14.2.0 <=14.2.15 | @swc1.4.0 |
>=1.6.0 <1.7.0 | >=15.0.0-canary.37 <=15.0.0-canary.116 | @swc1.6.0 |
>=1.7.0 <1.8.0 | >=15.0.0-canary.122 <=15.0.2 | @swc1.7.0 |
>=1.9.0 <1.10.0 | >=15.0.3 <15.2.0 | @swc1.9.0 |
>=1.10.0 <1.11.0 | >=15.2.0 <15.2.1 | @swc1.10.0 |
>=1.11.0 | >=15.2.1 <15.4.0 | @swc1.11.0 |
>=1.12.0 | >=15.4.0 | @swc1.12.0 |
For more information on compatibility, refer to the SWC documentation on Selecting the SWC Version and interactive compatibility table on SWC website.
Usage
To use the plugin, simply add it to your tool’s configuration.
Next.js
If you’re using the Next.js Compiler powered by SWC, add this plugin to your next.config.js.
const nextConfig = { experimental: { // even if empty, pass an options object `{}` to the plugin swcPlugins: [["@effector/swc-plugin", {}]], },};You’ll also need to install the official @effector/next bindings to enable SSR/SSG.
Note that some functionality may be broken when using Turbopack with Next.js, especially with relative factories. Use at your own risk.
.swcrc
Add a new entry to jsc.experimental.plugins option in your .swcrc.
{ "$schema": "https://json.schemastore.org/swcrc", "jsc": { "experimental": { "plugins": [["@effector/swc-plugin", {}]] } }}Configuration
factories
Specify an array of module names or files to treat as custom factories. When using SSR, factories is required for ensuring unique SIDs across your application.
Community packages (patronum, @farfetched/core, atomic-router, effector-action and @withease/factories) are always enabled, so you don’t need to list them explicitly.
Formulae
["@effector/swc-plugin", { "factories": ["./path/to/factory", "factory-package"] }]- Type:
string[] - Default:
[]
If you provide a relative path (starting with ./), the plugin treats it as a local factory relative to your project’s root directory. These factories can only be imported using relative imports within your code.
Otherwise, if you specify a package name or TypeScript alias, it’s interpreted as an exact import specifier. You must use such import exactly as specified in configuration.
Examples
["@effector/swc-plugin", { "factories": ["./src/factory"] }]import { createStore } from "effector";
/* createBooleanStore is a factory */export const createBooleanStore = () => createStore(true);import { createBooleanStore } from "../factory";
const $boolean = createBooleanStore(); /* Treated as a factory! */debugSids
Append the full file path and Unit name to generated SIDs for easier debugging of SSR issues.
Formulae
["@effector/swc-plugin", { "debugSids": false }]- Type:
boolean - Default:
false
hmr
@effector/swc-plugin@0.7.0
Enable Hot Module Replacement (HMR) support to clean up links, subscriptions and side effects managed by Effector. This prevents double-firing of Effects and watchers.
Hot Module Replacement works best when all factories in the project are properly declared. A correct configuration allows the plugin to detect what code should be cleaned up during hot reload.
Formulae
["@effector/swc-plugin", { "hmr": "es" }]- Type:
"es"|"cjs"|false"es": Useimport.meta.hotHMR API in bundlers that are ESM-compliant, like Vite and Rollup"cjs": Usemodule.hotHMR API in bundlers that rely on CommonJS modules, like Webpack, Next.js or Metro (React Native)false: Disable Hot Module Replacement
- Default:
false
When bundling for production, make sure to set the hmr option to false to reduce bundle size and improve runtime performance.
addNames
Add names to Units when calling factories (like createStore or createDomain). This is helpful for debugging during development and testing, but its recommended to disable it for minification.
Formulae
["@effector/swc-plugin", { "addNames": true }]- Type:
boolean - Default:
true
addLoc
Include location information (file paths and line numbers) for Units and factories. This is useful for debugging with tools like effector-logger.
Formulae
["@effector/swc-plugin", { "addLoc": true }]- Type:
boolean - Default:
false
forceScope
Inject forceScope: true into all hooks or @effector/reflect calls to ensure your app always uses Scope during rendering. If Scope is missing, an error will be thrown, eliminating the need for /scope or /ssr imports.
Read more about Scope enforcement in the effector-react documentation.
Formulae
[ "@effector/swc-plugin", { "forceScope": { "hooks": true, "reflect": false } }]- Type:
boolean | { hooks: boolean, reflect: boolean } - Default:
false
hooks
Enforces all hooks from effector-react and effector-solid, like useUnit and useList, to use Scope in runtime.
reflect
Supported by @effector/reflect since 9.0.0
For @effector/reflect users, enforces all components created with reflect library use Scope in runtime.
transformLegacyDomainMethods
When enabled (default), this option transforms Unit creators in Domains, like domain.event() or domain.createEffect(). However, this transformation can be unreliable and may affect unrelated code. If that’s the case for you, disabling this option can fix these issues.
Disabling this option will stop adding SIDs and other debug information to these unit creators. Ensure your code does not depend on domain methods before disabling.
Instead of using unit creators directly on domain, consider using the domain argument in regular methods.
Formulae
["@effector/swc-plugin", { "transformLegacyDomainMethods": false }]- Type:
boolean - Default:
true