Skip to main content

Babel plugin

Built-in plugin for babel can be used for ssr and debugging. It inserts a name a Unit, inferred from variable name and sid (stable identifier), computed from the location in the source code.

For example, in case effects without handlers, it improves error message by clearly showing in which effect error happened.

import {createEffect} from 'effector'

const fetchFx = createEffect()

fetchFx()

// => no handler used in fetchFx

Try it

Usage

In the simplest case, it can be used without any configuration:

.babelrc
{
"plugins": ["effector/babel-plugin"]
}

sid

since

effector 20.2.0

Stable hash identifier for events, effects, stores and domains, preserved between environments, to handle client-server interaction within the same codebase.

The crucial value of sid is that it can be autogenerated by effector/babel-plugin with default config, and it will be stable between builds.

See example project

common.js
import {createEffect} from 'effector'

export const getUser = createEffect({sid: 'GET /user'})
console.log(getUsers.sid)
// => GET /user
worker.js
import {getUsers} from './common.js'

getUsers.use(userID => fetch(userID))

getUsers.done.watch(({result}) => {
postMessage({sid: getUsers.sid, result})
})

onmessage = async ({data}) => {
if (data.sid !== getUsers.sid) return
getUsers(data.userID)
}
client.js
import {createEvent} from 'effector'
import {getUsers} from './common.js'

const onMessage = createEvent()

const worker = new Worker('worker.js')
worker.onmessage = onMessage

getUsers.use(
userID =>
new Promise(rs => {
worker.postMessage({sid: getUsers.sid, userID})
const unwatch = onMessage.watch(({data}) => {
if (data.sid !== getUsers.sid) return
unwatch()
rs(data.result)
})
}),
)

Configuration

importName

  • Type: string | string[]
  • Default: ['effector', 'effector/compat']

Specifying import name or names to process by plugin. Import should be used in the code as specified.

factories

since

effector 21.6.0

  • Type: string[]

Accepts an array of module names which exports treat as custom factories therefore each function call provides unique prefix for sids of units inside them. Used to SSR(Server Side Rendering) and it's not required for client-only application.

  • Factories can have any amount of arguments.
  • Factories can create any amount of units.
  • Factories can call any effector methods.
  • Factories can call another factories from others modules.
  • Modules with factories can export any amount of functions.
  • Factories should be compiled with effector/babel-plugin as well as code which use them.

Example

.babelrc
{
"plugins": [
[
"effector/babel-plugin",
{
"factories": ["src/createEffectStatus", "~/createCommonPending"]
}
]
]
}
./src/createEffectStatus.js
import {rootDomain} from './rootDomain'

export function createEffectStatus(fx) {
const $status = rootDomain
.createStore('init')
.on(fx.finally, (_, {status}) => status)

return $status
}
./src/statuses.js
import {createEffectStatus} from './createEffectStatus'
import {fetchUserFx, fetchFriendsFx} from './api'

export const $fetchUserStatus = createEffectStatus(fetchUserFx)
export const $fetchFriendsStatus = createEffectStatus(fetchFriendsFx)

Import createEffectStatus from './createEffectStatus' was treated as factory function so each store created by it has its own sid and will be handled by serialize independently, although without factories they will share the same sid.

reactSsr

since

effector 21.5.0

  • Type: boolean
  • Default: false

Replace imports from effector-react to effector-react/scope. Useful for building both server-side and client-side builds from the same codebase.

addNames

since

effector 21.8.0

  • Type: boolean
  • Default: true

Add names to units factories calls. Useful for minification and obfuscation of production builds.

addLoc

  • Type: boolean
  • Default: false

Add location to methods' calls. Used by devtools, for example effector-logger.

debugSids

  • Type: boolean
  • Default: false

Add path of a file and a variable name whether a unit was defined to a sid. Useful for debugging SSR.

noDefaults

since

effector 20.2.0

  • Type: boolean
  • Default: false

Option for effector/babel-plugin for making custom unit factories with clean configuration.

.babelrc
{
"plugins": [
["effector/babel-plugin", {"addLoc": true}],
[
"effector/babel-plugin",
{
"importName": "@lib/createInputField",
"storeCreators": ["createInputField"],
"noDefaults": true
},
"createInputField"
]
]
}
@lib/createInputField.js
import {createStore} from 'effector'
import {resetForm} from './form'

export function createInputField(defaultState, {sid, name}) {
return createStore(defaultState, {sid, name}).reset(resetForm)
}
src/state.js
import {createInputField} from '@lib/createInputField'

const foo = createInputField('-')
/*

will be treated as store creator and compiled to

const foo = createInputField('-', {
name: 'foo',
sid: 'z&si65'
})

*/

Bundlers

Vite + React (SSR)

To use with effector/babel-plugin, you have to following next steps:

  1. Install @vitejs/plugin-react package.
  2. vite.js.config should be follows:

Note: effector/babel-plugin is not a package, it is bundled with effector

// vite.config.js
import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
plugins: [
react({
babel: {
plugins: ['effector/babel-plugin'],
// Use .babelrc files
babelrc: true,
// Use babel.config.js files
configFile: true,
},
}),
],
})