Skip to content

Commit

Permalink
build(esm): Use explicit .mjs extension for ESM
Browse files Browse the repository at this point in the history
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 react-hook-form#7244
Refs react-hook-form#7095
Refs react-hook-form#7088
Refs react-hook-form/resolvers#271
Refs vercel/next.js#30750
  • Loading branch information
evocateur committed Dec 10, 2021
1 parent 9ee9750 commit cf38840
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 6 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

0 comments on commit cf38840

Please sign in to comment.