refactor: Output ESM files w/ .mjs when appropriate (#950)

* fix: Output ESM w/ .mjs ext when pkg type is cjs

* docs: Adding changeset

* Update README.md

* Update README.md

Co-authored-by: Jason Miller <developit@users.noreply.github.com>

* chore: Add warning for new ESM output extension behavior

* Update src/index.js

Co-authored-by: Jason Miller <developit@users.noreply.github.com>

Co-authored-by: Jason Miller <developit@users.noreply.github.com>
This commit is contained in:
Ryan Christian 2022-04-25 14:17:55 -05:00 committed by GitHub
parent 242754f43c
commit 6f6e080f3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 317 additions and 297 deletions

View File

@ -0,0 +1,5 @@
---
'microbundle': minor
---
Microbundle will now output ESM using `.mjs` as the file extension when the package type is CJS

View File

@ -120,8 +120,8 @@ export default function (e, t, r) {
```jsonc
{
"main": "./dist/foo.umd.js", // legacy UMD output (for Node & CDN use)
"module": "./dist/foo.module.js", // legacy ES Modules output (for bundlers)
"exports": "./dist/foo.modern.js", // modern ES2017 output
"module": "./dist/foo.module.mjs", // legacy ES Modules output (for bundlers)
"exports": "./dist/foo.modern.mjs", // modern ES2017 output
"scripts": {
"build": "microbundle src/foo.js"
}
@ -134,9 +134,9 @@ The `"exports"` field can also be an object for packages with multiple entry mod
{
"name": "foo",
"exports": {
".": "./dist/foo.modern.js", // import "foo" (the default)
"./lite": "./dist/lite.modern.js", // import "foo/lite"
"./full": "./dist/full.modern.js" // import "foo/full"
".": "./dist/foo.modern.mjs", // import "foo" (the default)
"./lite": "./dist/lite.modern.mjs", // import "foo/lite"
"./full": "./dist/full.modern.mjs" // import "foo/full"
},
"scripts": {
"build": "microbundle src/*.js" // build foo.js, lite.js and full.js
@ -163,15 +163,15 @@ The filenames and paths for generated bundles in each format are defined by the
```jsonc
{
"source": "src/index.js", // input
"main": "dist/foo.js", // CommonJS output bundle
"umd:main": "dist/foo.umd.js", // UMD output bundle
"module": "dist/foo.m.js", // ES Modules output bundle
"source": "src/index.js", // input
"main": "dist/foo.js", // CommonJS output bundle
"umd:main": "dist/foo.umd.js", // UMD output bundle
"module": "dist/foo.mjs", // ES Modules output bundle
"exports": {
"require": "./dist/foo.js", // CommonJS output bundle
"default": "./dist/foo.modern.js", // Modern ES Modules output bundle
"require": "./dist/foo.js", // CommonJS output bundle
"default": "./dist/foo.modern.mjs", // Modern ES Modules output bundle
},
"types": "dist/foo.d.ts" // TypeScript typings directory
"types": "dist/foo.d.ts" // TypeScript typings directory
}
```

View File

@ -2,7 +2,7 @@ import fs from 'fs';
import { resolve, relative, dirname, basename, extname } from 'path';
import camelCase from 'camelcase';
import escapeStringRegexp from 'escape-string-regexp';
import { blue, red } from 'kleur';
import { blue, yellow, red } from 'kleur';
import { map, series } from 'asyncro';
import glob from 'tiny-glob/sync';
import autoprefixer from 'autoprefixer';
@ -282,6 +282,7 @@ function walk(exports, includeDefault) {
function getMain({ options, entry, format }) {
const { pkg } = options;
const pkgMain = options['pkg-main'];
const pkgTypeModule = pkg.type === 'module';
if (!pkgMain) {
return options.output;
@ -301,18 +302,23 @@ function getMain({ options, entry, format }) {
mainsByFormat.es = replaceName(
pkg.module && !pkg.module.match(/src\//)
? pkg.module
: pkg['jsnext:main'] || 'x.esm.js',
: pkg['jsnext:main'] || pkgTypeModule
? 'x.esm.js'
: 'x.esm.mjs',
mainNoExtension,
);
mainsByFormat.modern = replaceName(
(pkg.exports && walk(pkg.exports, pkg.type === 'module')) ||
(pkg.exports && walk(pkg.exports, pkgTypeModule)) ||
(pkg.syntax && pkg.syntax.esmodules) ||
pkg.esmodule ||
'x.modern.js',
pkgTypeModule
? 'x.modern.js'
: 'x.modern.mjs',
mainNoExtension,
);
mainsByFormat.cjs = replaceName(
pkg['cjs:main'] || (pkg.type && pkg.type === 'module' ? 'x.cjs' : 'x.js'),
pkg['cjs:main'] || (pkgTypeModule ? 'x.cjs' : 'x.js'),
mainNoExtension,
);
mainsByFormat.umd = replaceName(
@ -440,6 +446,15 @@ function createConfig(options, entry, format, writeMeta) {
const outputDir = dirname(absMain);
const outputEntryFileName = basename(absMain);
// Warn about the (somewhat) breaking change in #950
if (format === 'es' && !pkg.module && outputEntryFileName.endsWith('.mjs')) {
stdout(
yellow(
'Warning: your package.json does not specify {"type":"module"}. Microbundle assumes this is a CommonJS package and is generating ES Modules with the ".mjs" file extension.',
),
);
}
let config = {
/** @type {import('rollup').InputOptions} */
inputOptions: {

File diff suppressed because one or more lines are too long