New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will/does Webpack support "module" field? #1979

Closed
TehShrike opened this Issue Feb 2, 2016 · 77 comments

Comments

Projects
None yet
@TehShrike

TehShrike commented Feb 2, 2016

To allow importing of ES6 modules with an ES5 module in the package.json's "main" field.

As proposed by rollup.

@IngwiePhoenix

This comment has been minimized.

Contributor

IngwiePhoenix commented Feb 27, 2016

I +1 this.

Proposed:

However... Should jsnext:main be treatened in a way that it can't be ignored? Just a thought.

Kind regards,
Ingwie.

@SimenB

This comment has been minimized.

Contributor

SimenB commented Feb 28, 2016

@taion

This comment has been minimized.

taion commented Apr 16, 2016

Coming from ReactTraining/react-router#3333, I'd really like if there were a way to specify the location of the ES module build for webpack users.

I'm a little bit frightened that people are importing from the subdirectory containing the ES modules directly.

@rosskevin

This comment has been minimized.

rosskevin commented Jun 20, 2016

+1 to be a default as @IngwiePhoenix says.

Is there a current way to plugin a resolver to webpack 2 to prefer jsnext:main and otherwise fallback to main? I can currently alter resolve.mainFields (until it is in the default list) but don't we still have to either include that dynamically as part of the src loading?

@TheLarkInn

This comment has been minimized.

Member

TheLarkInn commented Jun 27, 2016

@sokra I could take a stab at this if this is as easy as it appears to be.

@taion

This comment has been minimized.

taion commented Jun 27, 2016

Why do you need a plugin for this? Just set e.g.

mainFields: ['jsnext:main', 'browser', 'main']

in your webpack config.

@rosskevin

This comment has been minimized.

rosskevin commented Jun 27, 2016

@taion - The problem with this approach is transitive dependencies (or so it seemed when I tried it). I don't think it is as simple as it looks to simply configure or plug-in, it needs to be considered in the primary resolution so that we can take advantage of tree-shaking etc.

@taion

This comment has been minimized.

taion commented Jun 27, 2016

It works just fine transitively.

@rosskevin

This comment has been minimized.

rosskevin commented Jun 27, 2016

That is my error in that case; if you have figured it out I'm sure all the participants here would like to see an example of this running.

@taion

This comment has been minimized.

taion commented Jun 27, 2016

In webpack.config.js, just do e.g.

resolve: {
  mainFields: ['jsnext:main', 'browser', 'main'],
},

That's all you need.

@rosskevin

This comment has been minimized.

rosskevin commented Jun 27, 2016

hmm, that didn't work for me when I tried it and I had multiple transitive dependency failures. Several projects including react-router provide these sources yet my imports failed. I was sure to allow sources to be pulled (not excluded) from node_modules.

@TheLarkInn

This comment has been minimized.

Member

TheLarkInn commented Jun 27, 2016

I'd assume this would be a desired default with fallback for main. No?

@adamdicarlo

This comment has been minimized.

adamdicarlo commented Jul 12, 2016

Besides adding 'jsnext:main' to mainFields, don't you need to somehow teach Babel "you actually need to process some stuff in my node_modules folder"?

@umidbekkarimov

This comment has been minimized.

umidbekkarimov commented Jul 23, 2016

@adamdicarlo

That works for me

{
  test: /\.js$/,
  loader: 'babel',
  exclude: /node_modules\/(?!(([^\/]+?\/){1,2}(src|es6)))/,
}

Tested it here

@adamdicarlo

This comment has been minimized.

adamdicarlo commented Jul 23, 2016

that matches /node_modules/react-router/node_modules/foo/es6/index.js. but anyway, I don't think checking for a folder named src or es6 is a long term/general solution.

Webpack supports callbacks for exclude/include; in the past, I've set up logic to do this:

  1. figure out which package the file is a part of (by recursively scanning folder & parent folders for a package.json), and
  2. inspect that package.json to figure out whether its source needs transpilation

but if Webpack will support jsnext:main out of the box, it seems pretty silly to manually need to set up this kind of mechanism for every project...

@taion

This comment has been minimized.

taion commented Jul 23, 2016

Babel doesn't need to process anything in node_modules. By convention, an ES module build is the same as the CJS build, with the only exception being the module system. The rest of the ESNext features should still be transpiled.

@taion

This comment has been minimized.

taion commented Jul 23, 2016

Take a look at e.g. how Redux and React Router do this.

@adamdicarlo

This comment has been minimized.

adamdicarlo commented Jul 23, 2016

Hmm, right. That's maybe good enough in general. There are downsides, though: your host project's babel plugins do not get applied to the (e.g.) React components you npm installed. So you can't, for instance, use babel-plugin-rewire to mock a package in node_modules. You can't apply babel-plugin-react-transform to those components either.

And when npm linking packages and working on them in the context of a host app—which is already a pain, of course—you'd have to have the linked package's build watcher running, too.

@adamdicarlo

This comment has been minimized.

adamdicarlo commented Jul 23, 2016

Another thought: What about the (not too distant?) future where we want to ship ES2015 code to browsers? Surely packages will mostly be written in ES2016 (or ES2017) then — so they'd need to provide ES5 and ES2015 (and eventually ES2016) builds. ¯_(ツ)_/¯ (WebAssembly support can't come fast enough IMO...)

@taion

This comment has been minimized.

taion commented Jul 23, 2016

wasm isn't going to fix anything because if for some bizarre reason you decide to compile JS to wasm, you're effectively opting out of the bulk of things that the JIT can do.

Yes, it's true that the "projects ship transpiled code" has some set of disadvantages – but that's orthogonal to the question of the choice of module system used for distribution.

@umidbekkarimov

This comment has been minimized.

umidbekkarimov commented Jul 24, 2016

@adamdicarlo

I don't think checking for a folder named src or es6 is a long term/general solution.

Webpack 2 still in beta, so it's just temporary workaround

@taion

Babel doesn't need to process anything in node_modules. By convention, an ES module build is the same as the CJS build, with the only exception being the module system. The rest of the ESNext features should still be transpired.

Yep, but modules like redux-form or moment use /src dir in jsnext:main

@MeirionHughes

This comment has been minimized.

MeirionHughes commented Aug 25, 2017

can someone just clarify that:

  • if I create a library with both dist/commonjs/index.js and dist/es2015/index.js, and
  • the library has in it's package.json:
  "main": "dist/commonjs/index.js",
  "module": "dist/es2015/index.js",
  • then, when I consume library in a webpack-built app, webpack will resolve to dist/es2015/index.js by default?
@hccampos

This comment has been minimized.

hccampos commented Sep 6, 2017

@MeirionHughes it looks that way, which is unfortunate for us. Since we are using the Angular CLI which has no transpiling other than Typescript, any modules which specify a module field will be imported as es2015 modules. And a lot of times things will only really break when you run it in an older browser that doesn't support class, something which you normally don't do everyday when developing.

@scopsy

This comment has been minimized.

scopsy commented Oct 1, 2017

@hccampos Hey Hugo,
I'm currently running in an issue where a library I'm using is dependent on a package that uses "module" field in its package.json file.
When compiling ng build --aot --prod I'm getting an error:

Unexpected token: name (CalendarVietnamese) [0.a821737870a81bd01043.chunk.js:8779,6]

When I removed the "module" from that package compilation works fine.

Any suggestions?

@hccampos

This comment has been minimized.

hccampos commented Oct 1, 2017

@scopsy the only solutions I know of at the moment are:

  1. Eject the webpack config and fix it manually.
  2. Fork the library, the update package.json and use the fork in your project.

We are using option 2 and just maintaining forks of the original repos for libraries that don't work with the Angular CLI

@scopsy

This comment has been minimized.

scopsy commented Oct 1, 2017

@hccampos When ejecting the webpack config what needs to be changed there?

@gaearon

This comment has been minimized.

Contributor

gaearon commented Oct 26, 2017

Since we are using the Angular CLI which has no transpiling other than Typescript, any modules which specify a module field will be imported as es2015 modules. And a lot of times things will only really break when you run it in an older browser that doesn't support class, something which you normally don't do everyday when developing.

I think we might be conflating two different things here. The module entry point should point to code with ES6 modules but not necessarily other ES6 features. People who want their libraries to be in ESM format can/should still precompile other ES6 features so that older browsers don't break.

@donaldpipowitch

This comment has been minimized.

donaldpipowitch commented Oct 27, 2017

People who want their libraries to be in ESM format can/should still precompile other ES6 features so that older browsers don't break.

I asked for this as a feature request to support this as a native webpack feature a while ago, if someone is interested in this topic: #2933.

@hccampos

This comment has been minimized.

hccampos commented Oct 27, 2017

@gaearon absolutely! That is what MobX does, for example. However, more and more libraries seem to be popping up which don't transpile the rest to es5, breaking builds which run without babel/bubble. The worst part is that you only notice the breakage when testing on older browsers, which usually happens on a CI environment or manually after deploy.

saki7 added a commit to saki7/nagato that referenced this issue Oct 29, 2017

Enable ES2015's (un-transpiled) module imports while supporting Webpa…
…ck's tree shaking.

This is currently *not* supported by Webpack (see webpack/webpack#1979 (comment) and webpack/webpack#2933 for rationale).

We workaround this by exposing our babel config to the wild (i.e. js/nagato/babel-options.js). This way we can give full controls for both bundling (i.e. 'tree shaking' in Webpack) and module building (i.e. 'transpiling') to the library users (I hope).

We just can't enforce our users to use some huge-sized arbitrary bundle.

Users with ES2015+ (or whatever) environment shall `require()` this config file inside their 'webpack.config.js', and use it as a hash object for the `babel-loader`'s `option: ` option. This could be achieved by looking into the `module: ` option in `package.json`; which (I believe) is the default behavior for Webpack when you use the native `import Something from 'other-external-library'` syntax.

If this is not desirable, use the fully-transpiled .js file inside our distributed npm package. This could be achieved by referring to the old-school `"main"` value inside the package.json.

Disclaimer:
By using this method we abandon Webpack-specific aggresive transpilation features for our entire library. This means we can't use Webpack-specific custom `import`s (i.e. importing non-JavaScript files like images (.png, .jpg, etc.) inside our library (.js)).

Additional notes:
This issue described in the disclaimer section can be workarounded by specifying your library-specific `npm run build` action inside the `prepare` section of package.json.

gimdongwoo added a commit to jsdevkr/axui-datagrid that referenced this issue Nov 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment