Skip to content

Commit f711ab2

Browse files
committed
Support .mjs files by default.
Since rollup prefers ESM formatted modules, it should look for node's new .mjs file extension before looking for .js files by default. This offers support for deployed modules intended to be used in node's ESM mode. Folks can work around this today by manually supplying the `extensions` option, however it would be great if this worked by default. Note that looking for `.mjs` before `.js` is important for rollup which prefers ESM, however the `resolve` dependency should not use the same order by default since it is used in many other tools which do not yet support ESM or would not expect it by default. Encountered this as the root cause behind graphql/graphql-js#1293
1 parent 7846a19 commit f711ab2

File tree

10 files changed

+45
-5
lines changed

10 files changed

+45
-5
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default {
4444
browser: true, // Default: false
4545

4646
// not all files you want to resolve are .js files
47-
extensions: [ '.js', '.json' ], // Default: ['.js']
47+
extensions: [ '.mjs', '.js', '.jsx', '.json' ], // Default: [ '.mjs', '.js', '.json', '.node' ]
4848

4949
// whether to prefer built-in modules (e.g. `fs`, `path`) or
5050
// local ones with the same names
@@ -53,7 +53,7 @@ export default {
5353
// Lock the module search in this path (like a chroot). Module defined
5454
// outside this path will be marked as external
5555
jail: '/my/jail/path', // Default: '/'
56-
56+
5757
// Set to an array of strings and/or regexps to lock the module search
5858
// to modules that match at least one entry. Modules not matching any
5959
// entry will be marked as external

src/index.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import fs from 'fs';
66

77
const ES6_BROWSER_EMPTY = resolve( __dirname, '../src/empty.js' );
88
const CONSOLE_WARN = ( ...args ) => console.warn( ...args ); // eslint-disable-line no-console
9-
const exts = [ '.js', '.json', '.node' ];
9+
// It is important that .mjs occur before .js so that Rollup will interpret npm modules
10+
// which deploy both ESM .mjs and CommonJS .js files as ESM.
11+
const DEFAULT_EXTS = [ '.mjs', '.js', '.json', '.node' ];
1012

1113
let readFileCache = {};
1214
const readFileAsync = file => new Promise((fulfil, reject) => fs.readFile(file, (err, contents) => err ? reject(err) : fulfil(contents)));
@@ -110,6 +112,7 @@ export default function nodeResolve ( options = {} ) {
110112
return new Promise( ( fulfil, reject ) => {
111113
let disregardResult = false;
112114
let packageBrowserField = false;
115+
const extensions = options.extensions || DEFAULT_EXTS;
113116

114117
const resolveOptions = {
115118
basedir: dirname( importer ),
@@ -123,7 +126,7 @@ export default function nodeResolve ( options = {} ) {
123126
const absoluteKey = resolve( pkgRoot, key );
124127
browser[ absoluteKey ] = resolved;
125128
if ( !extname(key) ) {
126-
exts.reduce( ( browser, ext ) => {
129+
extensions.reduce( ( browser, ext ) => {
127130
browser[ absoluteKey + ext ] = browser[ key ];
128131
return browser;
129132
}, browser );
@@ -146,7 +149,7 @@ export default function nodeResolve ( options = {} ) {
146149
},
147150
readFile: cachedReadFile,
148151
isFile: cachedIsFile,
149-
extensions: options.extensions
152+
extensions: extensions
150153
};
151154

152155
if (preserveSymlinks !== undefined) {

test/node_modules/dual-cjs-mjs/entry.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/node_modules/dual-cjs-mjs/entry.mjs

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/node_modules/dual-cjs-mjs/package.json

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/node_modules/module-mjs/entry.mjs

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/node_modules/module-mjs/package.json

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/samples/dual-cjs-mjs/main.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import module from 'dual-cjs-mjs';
2+
3+
export default module; // MODULE

test/samples/module-mjs/main.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import module from 'module-mjs';
2+
3+
export default module; // MODULE

test/test.js

+22
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,28 @@ describe( 'rollup-plugin-node-resolve', function () {
436436
});
437437
});
438438

439+
it('finds and uses an .mjs module', function () {
440+
return rollup.rollup({
441+
input: 'samples/module-mjs/main.js',
442+
plugins: [
443+
nodeResolve({ preferBuiltins: false })
444+
]
445+
}).then( executeBundle ).then( module => {
446+
assert.equal( module.exports, 'MODULE-MJS' );
447+
});
448+
});
449+
450+
it('finds and uses a dual-distributed .js & .mjs module', function () {
451+
return rollup.rollup({
452+
input: 'samples/dual-cjs-mjs/main.js',
453+
plugins: [
454+
nodeResolve({ preferBuiltins: false })
455+
]
456+
}).then( executeBundle ).then( module => {
457+
assert.equal( module.exports, 'DUAL-MJS' );
458+
});
459+
});
460+
439461
describe( 'symlinks', () => {
440462
function createMissingDirectories () {
441463
createDirectory( './samples/symlinked/first/node_modules' );

0 commit comments

Comments
 (0)