parcel icon indicating copy to clipboard operation
parcel copied to clipboard

Add ESM support to glob resolver

Open samjt opened this issue 3 years ago • 4 comments

↪️ Pull Request

Checks if dependency.specifierType is esm and then writes imports and exports in and ES6 style instead of commonjs style requires from glob resolved javascript files.

If it is marked as ESM then generate an import using the format

import ${key} from ${JSON.stringify(matches)};

instead of

const ${key} = require(${JSON.stringify(matches)});

exports will be written as

export { _temp0 as "a" }

instead of

module.exports = {"a": _temp0}

💻 Examples

When in a project with module set:

import * as React from 'react';
import * as Icons from './svg/*.svg';

export default function () {
  const {SVG_Logo} = Icons;

  console.log('>> SVG_Logo should be a React functional component, SVG_Logo.default should be undefined', SVG_Logo, SVG_Logo.default);

  return (
    <>
      <SVG_Logo />
      <div>hello!</div>
    </>
  );
}

🚨 Test instructions

yarn test:integration --g 'glob'

✔️ PR Todo

  • [x] Added/updated unit tests for this change
  • [x] Filled out test instructions (In case there aren't any unit tests)
  • [x] Included links to related issues/PRs

samjt avatar Sep 26 '22 19:09 samjt

One point to note:

async imports are treated as esm based on the dependency specifiertype returned to the resolver.

samjt avatar Sep 27 '22 13:09 samjt

One question: where did this requirement come from? Did you have an issue that was caused by using CommonJS? I think the tree shaking implementation should handle both the same way, so just curious where this PR is coming from.

devongovett avatar Oct 24 '22 04:10 devongovett

@devongovett It came from attempting to build an SVG library that exported as pure esm. When using the glob resolver to do this I would get back an objects rather than functions:

import * as Icons from  "./svg/*.svg"
const { AnIcon } = Icons;
console.log(AnIcon) // > { esmodule: true, default: function }
<AnIcon /> // Does not render
<AnIcon.default /> //Does render

I believed this was because the glob resolver was incorrectly exporting them as commonjs compatible, and by making the changes above, I was able to import directly and use the icons without having to reference default.

samjt avatar Oct 28 '22 13:10 samjt

But with the change to import * rather than only the default, wouldn't this now have the same issue?

devongovett avatar Nov 06 '22 18:11 devongovett