You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently redux toolkit causes errors when using named exports in ESM modules from within Node (when using Jest)
An example:
There is a source code file like this in my Frontend code, which gets bundled a bundler (Parcel in this case, Vite, Webpack etc would be similar).
// some-slice.jsimport{createSlice}from'@reduxjs/toolkit';// define the slice.
Then I have a test which tests things in this file. The test is run via Jest through a modern version of Node (18 in this case).
import{stuff}from'./some-slice';// run the test
This results in the following error when Jest is run.
SyntaxError: The requested module '@reduxjs/toolkit' does not provide an export named 'createSlice.
The package.json contains type: module and the jest tests are run with NODE_OPTIONS=--experimental-vm-modules jest src (which is currently needed to run Jest with ESM enabled)
Easy way to reproduce
mkdir testcdtestecho'{"type": "module"}'> package.json
npm init -y
echo'import { createSlice } from "@reduxjs/toolkit"'> index.mjs # note the .mjs extension to force ESM (type module in package.json also works)
node index.mjs #throws the error
Why does this happen?
Short answer
Redux toolkit's ESM module definition is broken for named exports, when using native ESM in NodeJS.
main is used for NodeJS CJS code. module provides an ESM export. However, this field is only used by bundlers and ignored by NodeJS.
This means that when using CJS node chooses the main field to require() the redux toolkit code.
But when Node is running ESM it does NOT use the module field because Node does not support this field, falling back to importing the CJS file specified in main (which is possible because of the backward compatibilty provided by Node).
However, this backward compatibility comes at a cost. Namely the fact that named exports don't work properly. NodeJs tries to provide named exports for CJS code imported by ESM code using a runtime check but the fact is that only the default export is reliable because CJS exports are not wenn suited for static analysis. Using the default export is not possible however, when using a bundler because the ESM version of the code provided by the "module" field, has no default export, only named exports. So one is "stuck", there's no way to satisfy the two at the moment.
Proposed Solution
NodeJS does not support the module field but it does support the exports field. Adding something like this to the package.json would allow NodeJS to import the correct ESM/CJS variant of the build
{
"main": "dist/index.js",
"module": "dist/redux-toolkit.esm.js",
"unpkg": "dist/redux-toolkit.umd.min.js",
"types": "dist/index.d.ts",
"exports" {
"types": "dist/index.d.ts",
"import": "dist/redux-toolkit.mjs", // note that this must have an .mjs extension (or type: "module" in the package.json) to be interpreted as ESM "require": "dist/index.js"
}
}
This would solve the problem for Node and allow importing of the ESM build. Note that the file must have an .mjs extension since type: module is currently not set in the package.json.
Using this might even make the module field obsolete since bundlers tend to prefer exports if it's provided over module, but it doesn't hurt to leave it there.
The text was updated successfully, but these errors were encountered:
Problem
Currently redux toolkit causes errors when using named exports in ESM modules from within Node (when using Jest)
An example:
There is a source code file like this in my Frontend code, which gets bundled a bundler (Parcel in this case, Vite, Webpack etc would be similar).
Then I have a test which tests things in this file. The test is run via Jest through a modern version of Node (18 in this case).
This results in the following error when Jest is run.
SyntaxError: The requested module '@reduxjs/toolkit' does not provide an export named 'createSlice
.The
package.json
containstype: module
and the jest tests are run withNODE_OPTIONS=--experimental-vm-modules jest src
(which is currently needed to run Jest with ESM enabled)Easy way to reproduce
Why does this happen?
Short answer
Redux toolkit's ESM module definition is broken for named exports, when using native ESM in NodeJS.
Long answer
Redux toolkit's package.json currently exposes two entrypoints in the package json.
main
is used for NodeJS CJS code.module
provides an ESM export. However, this field is only used by bundlers and ignored by NodeJS.This means that when using CJS node chooses the
main
field torequire()
the redux toolkit code.But when Node is running ESM it does NOT use the
module
field because Node does not support this field, falling back to importing the CJS file specified in main (which is possible because of the backward compatibilty provided by Node).However, this backward compatibility comes at a cost. Namely the fact that named exports don't work properly. NodeJs tries to provide named exports for CJS code imported by ESM code using a runtime check but the fact is that only the default export is reliable because CJS exports are not wenn suited for static analysis. Using the default export is not possible however, when using a bundler because the ESM version of the code provided by the "module" field, has no default export, only named exports. So one is "stuck", there's no way to satisfy the two at the moment.
Proposed Solution
NodeJS does not support the
module
field but it does support theexports
field. Adding something like this to the package.json would allow NodeJS to import the correct ESM/CJS variant of the buildThis would solve the problem for Node and allow importing of the ESM build. Note that the file must have an
.mjs
extension sincetype: module
is currently not set in the package.json.Using this might even make the
module
field obsolete since bundlers tend to preferexports
if it's provided overmodule
, but it doesn't hurt to leave it there.The text was updated successfully, but these errors were encountered: