-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
CommonJS
If we're running in a CommonJS environment, the package cannot be required:
$ node -e 'require( "@wordpress/dataviews" );'
node:internal/modules/cjs/loader:647
throw e;
^
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /tmp/test/node_modules/@wordpress/dataviews/package.json
This is particularly problematic when trying to test with jest, e.g.
const x = require( '@wordpress/dataviews' );
it( 'passes', () => {
expect( true ).toBe( true );
} );This fails with the following error:
Cannot find module '@wordpress/dataviews' from 'foo.test.js'
> 1 | const x = require( '@wordpress/dataviews' );
| ^
2 |
3 | it( 'passes', () => {
4 | expect( true ).toBe( true );
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:427:11)
at Object.<anonymous> (foo.test.js:1:44)
All this is because there is no commonjs export anymore after #66825, only types and import.
gutenberg/packages/dataviews/package.json
Lines 27 to 31 in cff73d4
| "exports": { | |
| ".": { | |
| "types": "./build-types/index.d.ts", | |
| "import": "./build-module/index.js" | |
| }, |
Adding a "require": "./build/index.js" or "default": "./build/index.js" at the end of the object makes it work.
ESM
Let's look at Jest first, running the following test with --experimental-vm-modules as documented at https://jestjs.io/docs/ecmascript-modules.
import * as x from '@wordpress/dataviews';
it( 'passes', () => {
expect( true ).toBe( true );
} );This fails with the following error: (with some irrelevant text snipped)
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
[...]
Details:
/tmp/test/node_modules/@wordpress/dataviews/build-module/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as DataViews } from './components/dataviews';
^^^^^^
SyntaxError: Unexpected token 'export'
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)
This is because the file at node_modules/@wordpress/dataviews/build-module/index.js is supposedly in CommonJS format, not ESM, but actually contains ESM code. There are two different ways you might fix this:
- Rename all the files under
build-module/to.mjsso they're parsed as ESM.- Also
build-wp/index.js, since that contains ESM code too.
- Also
- Add
"type": "module"to the package.json so all.jsfiles default to being interpreted as ESM.- And then rename all the files under
build/to.cjsso they're parsed as CommonJS.
- And then rename all the files under
Trying to import it with node --input-type=module -e 'import * as dataviews from "@wordpress/dataviews";' has additional problems due to the stricter ECMAScript loader:
- It does not support folders as modules, directory indexes (e.g.
'./startup/index.js') must be fully specified.- It does no extension searching. A file extension must be provided when the specifier is a relative or absolute file URL.
so even after applying the fixes above we still get failures like
Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/tmp/test/node_modules/@wordpress/dataviews/build-module/components/dataviews' is not supported resolving ES modules imported from /tmp/test/node_modules/@wordpress/dataviews/build-module/index.mjs
But since this package is probably not intended to be used that way (and it works with webpack and jest), it's probably safe to ignore that.