Skip to content

Commit

Permalink
build(esm): Use explicit .mjs extension for ESM, with CJS interop (#7261
Browse files Browse the repository at this point in the history
)

* build(esm): Use explicit .mjs extension for ESM

This ensures that Node always treats the ESM output as ESM, despite the package.json (implicit) type of commonjs. Bundlers that expect ESM, such as Next v12, no longer explode when encountering this module.

Refs #7244
Refs #7095
Refs #7088
Refs react-hook-form/resolvers#271
Refs vercel/next.js#30750

* fix(esm-interop): Import non-ESM React as default
  • Loading branch information
evocateur committed Dec 11, 2021
1 parent 9ee9750 commit ef770c5
Show file tree
Hide file tree
Showing 53 changed files with 114 additions and 56 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"description": "Performant, flexible and extensible forms library for React Hooks",
"version": "7.21.2",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"module": "dist/index.esm.mjs",
"umd:main": "dist/index.umd.js",
"unpkg": "dist/index.umd.js",
"jsdelivr": "dist/index.umd.js",
"jsnext:main": "dist/index.esm.js",
"jsnext:main": "dist/index.esm.mjs",
"source": "src/index.ts",
"types": "dist/index.d.ts",
"sideEffects": true,
Expand All @@ -18,15 +18,15 @@
"exports": {
"./package.json": "./package.json",
".": {
"import": "./dist/index.esm.js",
"import": "./dist/index.esm.mjs",
"require": "./dist/index.cjs.js"
}
},
"scripts": {
"clean": "rimraf dist",
"prebuild": "yarn clean",
"build": "yarn build:modern",
"postbuild": "rimraf dist/__tests__",
"postbuild": "rimraf dist/__tests__; node ./scripts/rollup/assert-esm-exports.mjs && node ./scripts/rollup/assert-cjs-exports.cjs",
"build:modern": "rollup -c ./scripts/rollup/rollup.config.js",
"build:esm": "rollup -c ./scripts/rollup/rollup.esm.config.js",
"prettier:fix": "prettier --config .prettierrc --write \"**/*.{ts,tsx}\"",
Expand Down Expand Up @@ -135,6 +135,6 @@
"url": "https://opencollective.com/react-hook-form"
},
"engines": {
"node": ">=12.0"
"node": ">=12.22.0"
}
}
13 changes: 13 additions & 0 deletions scripts/rollup/all-exports.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
"Controller",
"FormProvider",
"appendErrors",
"get",
"set",
"useController",
"useFieldArray",
"useForm",
"useFormContext",
"useFormState",
"useWatch"
]
22 changes: 22 additions & 0 deletions scripts/rollup/assert-cjs-exports.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* This file, when executed in the postbuild lifecycle, ensures that
* the CJS output is valid CJS according to the package.json spec.
*
* @see https://nodejs.org/docs/latest/api/packages.html#packages_determining_module_system
*/
/* eslint-disable @typescript-eslint/no-var-requires */
const exported = require('react-hook-form');
const assert = require('assert');
const fs = require('fs');

/**
* When this fails, fine the update one-liner in ./assert-esm-exports.mjs
*/
const expected = JSON.parse(
fs.readFileSync(
require('path').resolve(__dirname, './all-exports.json'),
'utf-8',
),
);

assert.deepStrictEqual(Object.keys(exported), expected);
22 changes: 22 additions & 0 deletions scripts/rollup/assert-esm-exports.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* This file, when executed in the postbuild lifecycle, ensures that
* the ESM output is valid ESM according to the package.json spec.
*
* @see https://nodejs.org/docs/latest/api/packages.html#packages_determining_module_system
*/
import * as exported from 'react-hook-form';
import assert from 'assert';
import fs from 'fs';

/**
* A shell one-liner to update this array when neccessary (run from root of repo):
* node -e "import('react-hook-form').then((mod) => console.log(JSON.stringify(Object.keys(mod), null, 2)))" > scripts/rollup/all-exports.json
*/
const expected = JSON.parse(
fs.readFileSync(
new URL('./all-exports.json', import.meta.url).pathname,
'utf-8',
),
);

assert.deepStrictEqual(Object.keys(exported), expected);
5 changes: 4 additions & 1 deletion scripts/rollup/createRollupConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import typescript from 'rollup-plugin-typescript2';

export function createRollupConfig(options, callback) {
const name = options.name;
const outputName = 'dist/' + [name, options.format, 'js'].join('.');
// A file with the extension ".mjs" will always be treated as ESM, even when pkg.type is "commonjs" (the default)
// https://nodejs.org/docs/latest/api/packages.html#packages_determining_module_system
const extName = options.format === 'esm' ? 'mjs' : 'js';
const outputName = 'dist/' + [name, options.format, extName].join('.');

const config = {
input: options.input,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/controller.server.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { renderToString } from 'react-dom/server';

import { Controller } from '../controller';
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/controller.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act,
fireEvent,
Expand Down
4 changes: 0 additions & 4 deletions src/__tests__/logic/focusFieldBy.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import focusFieldBy from '../../logic/focusFieldBy';
import get from '../../utils/get';

jest.mock('../../utils/isHTMLElement', () => ({
default: () => true,
}));

describe('focusFieldBy', () => {
it('should focus on the first error it encounter', () => {
const focus = jest.fn();
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/logic/getFieldValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import getFieldValue from '../../logic/getFieldValue';
import { Field } from '../../types';

jest.mock('../../logic/getRadioValue', () => ({
__esModule: true,
default: () => ({
value: 2,
}),
}));

jest.mock('../../logic/getCheckboxValue', () => ({
__esModule: true,
default: () => ({
value: 'testValue',
}),
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/type.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { Controller } from '../controller';
import {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useController.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/append.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react-hooks';

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/focus.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { act, fireEvent, render, screen } from '@testing-library/react';

import { useFieldArray } from '../../useFieldArray';
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/insert.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/move.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/prepend.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/remove.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/replace.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { act } from '@testing-library/react-hooks';

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/swap.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFieldArray/update.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm.server.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { renderToString } from 'react-dom/server';

import { useForm } from '../useForm';
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/clearErrors.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/formState.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/getValues.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { act, fireEvent, render, screen } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/handleSubmit.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/register.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/reset.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/resetField.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';

import { useForm } from '../../useForm';
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/resolver.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/setError.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react-hooks';

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/setValue.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/trigger.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useForm/watch.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act as actComponent,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFormContext.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { render } from '@testing-library/react';
import { act, renderHook } from '@testing-library/react-hooks';

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useFormState.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act,
act as actComponent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/useWatch.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import {
act,
fireEvent,
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/utils/isMessage.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import isMessage from '../../utils/isMessage';

Expand Down
2 changes: 1 addition & 1 deletion src/controller.native.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { fireEvent, render, waitFor } from '@testing-library/react-native';

Expand Down
2 changes: 1 addition & 1 deletion src/logic/mapCurrentIds.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { FieldValues } from '../types';

Expand Down
2 changes: 1 addition & 1 deletion src/types/controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { RegisterOptions } from './validator';
import {
Expand Down
2 changes: 1 addition & 1 deletion src/types/form.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { Subject, Subscription } from '../utils/createSubject';

Expand Down
2 changes: 1 addition & 1 deletion src/useController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import getEventValue from './logic/getEventValue';
import isNameInFieldArray from './logic/isNameInFieldArray';
Expand Down
2 changes: 1 addition & 1 deletion src/useFieldArray.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import focusFieldBy from './logic/focusFieldBy';
import getFocusFieldName from './logic/getFocusFieldName';
Expand Down
2 changes: 1 addition & 1 deletion src/useForm.native.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { fireEvent, render, waitFor } from '@testing-library/react-native';

Expand Down
2 changes: 1 addition & 1 deletion src/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { createFormControl } from './logic/createFormControl';
import getProxyFormState from './logic/getProxyFormState';
Expand Down
2 changes: 1 addition & 1 deletion src/useFormContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import omit from './utils/omit';
import { FieldValues, FormProviderProps, UseFormReturn } from './types';
Expand Down
2 changes: 1 addition & 1 deletion src/useFormState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import getProxyFormState from './logic/getProxyFormState';
import shouldRenderFormState from './logic/shouldRenderFormState';
Expand Down
2 changes: 1 addition & 1 deletion src/useSubscribe.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';

import { Subject, Subscription } from './utils/createSubject';

Expand Down

0 comments on commit ef770c5

Please sign in to comment.