support output.libraryTarget: 'module'

I'm submitting a feature request
It would be nice, if output.libraryTarget could support the ES2015 module format.
What is the motivation / use case for changing the behavior?
Say I develop a fancy component called fancy-component with webpack. I use a very custom config with specific loader settings e.g. for inlining images and stuff like that. My module exports FancyComponent and BigFancyComponent.
A friend develops a single page application and uses rollup to do that. He knows nothing about webpack, but wants to use my FancyComponent, but not BigFancyComponent. He installs fancy-component and imports FancyComponent. BigFancyComponent should not be included in the build (because of tree shaking).
As far as I know this is currently not possible. My friend would need fancy-component in a format using ES2015 modules. But currently these include webpack specific loader logic. I really need to publish fancy-component without webpack specific logic, but with ES2015 modules.

I definitely see the merit in this. @sokra I don't think we have a way already to export vanilla es2015 / es modules. I think that maybe this can be part of the rollup story (module combining/(and this splitting exporting)).

Is there anything I can do to help with that? Can I tackle this problem myself as someone who is unfamiliar with webpacks code base? Or is this a rabbit hole into the guts of webpack? :)

For a feature like this we should write up the design for the feature. Questions I think should be answerered first:

if someone uses CJS/AMD/non-esm dependencies in their library, how does webpack convert this into esm modules?
Should externals be leveraged for lib dependencies?

Once we have the behavior designed then you can go straight into adding the test cases.

Seems to be like big step. Could we introduce some workaround in the meantime? Like emitting plain non-bundled commonjs modules without __webpack_require__, webpackBootstrap, etc.?
Use case is similar. I want to build a project with webpacks powerful loaders and I want to output some sort of modules without webpack specific logic, so that they can be consumed more easily by third party build tools. (Or webpack itself, too! E.g. I can't consume CommonJS modules outputted from webpack right now and use process.env. A good example: https://github.com/facebook/react is created as CommonJS and they use ``process.env.NODE_ENV. Their "main"` file points to the CommonJS entry. They can only do that, because they don't use webpack in the first place. If they would want to include a loader somewhere, they currently couldn't emit a target like they have right now which doesn't force others to use webpack, too.)

Turns out... it looks like I already can output CommonJS modules and keep process.env. (From my knowledge using CommonJS - or ES2015 modules in the future - and allowing environment variables is the lowest common denominator between current popular bundlers.)
You need to set output.libraryTarget: 'commonjs2' (I guess most webpack users know this) and you need to set something like new DefinePlugin({ 'process.env.FOO': 'process.env.FOO' }) (that was new to me). So it should be possible to create a lib with webpack which can still be consumed by other bundlers without loosing the feature of setting environment variables.
The only feature which isn't supported in that way is tree shaking, which brings me back to the original feature request.

@donaldpipowitch thanks for bringing this up, very useful indeed, I would love to contribute too, I am going to try to learn the current code base first...

Would love to this implemented!

I think we can workaround this issue by writing a plugin that performs Code Spliting based on ES (or TS) files from source directory. If each source chunk is extracted to a single file, it should be ES2015 compliant. Maybe it would require more content manipulation to remove some webpack overhead from those output files. i'll try to implement something in the next few days, stay tuned.

Have there been any updates to this issue in the past year? Is it being tracked elsewhere?

Having to learn both webpack and rollup is no fun! Would love to have this implemented in webpack.

@sokra @TheLarkInn hey guys. if one (me) wanted to start looking at how to resolve this issue would you have any suggestions? any ideas of how much would need to change to support this?
i'd be keen to lend some time if you could put me on the right path :-)

It seems to me like Webpack is going to need functionality for compiling CommonJS and other formats to ES Modules, am I correct? I've been diving deep into this for the past few days. It seems like the whole world has traditionally been compiling from other formats to CommonJS. There is a popular babel plugin that does this. That problem seems to have been solved quite well by the community. But we need to go the other way, from CommonJS (or other formats) to ES Modules.
I'm not sure how much compilation/transpilation Webpack does itself, but that might be outside of its scope. Perhaps a Babel plugin would be the best choice here. Then the functionality could be leveraged by all libraries that need to go from CommonJS -> ES Modules. There is some prior art:
Basic Babel plugin for going from CommonJS -> ES Modules (basic, I've already run into a few blocking bugs, no community): https://www.npmjs.com/package/babel-plugin-transform-commonjs-es2015-modules
Advanced Rollup plugin for going from CommonJS -> ES Modules (seems very popular, most likely works very well, not very portable outside of Rollup. Might be easy to integrate within Webpack if Webpack has Rollup integration): https://github.com/rollup/rollup-plugin-commonjs
As I see it, this functionality should be created independent of Webpack and then incorporated as a dependency, through either a Bable plugin (most ideal), or perhaps a Rollup plugin (already implemented, might need to finagle).
Disclaimer, I'm not a heavy Webpack user nor in the Webpack community, these are just my thoughts as I've been trying to tackle the issue of CommonJS -> ES Modules

I think webpack must wait until CJS / ESM interop has been standarized into node. There are plenty projects that made opinionated choices about it and it could break the existing codebases if things got spec-ed differently.

Hello,
I have a library fully written in Es6, and due to webpack limitations I'm not able to propose my library in es6 module that would enable treeshaking feature on for clients

@moroine For library, I would recommend using rollup. And webpack for applications.
Rich Harris (rollup's creator) wrote about it: Webpack and Rollup: the same but different.

It seems to me like Webpack is going to need functionality for compiling CommonJS and other formats to ES Modules

I would restrict exporting to ES module (output.libraryTarget: 'module') to libraries written with  ES modules only

Important use case for this: ES6 modules are now supported natively, but many packages in NPM still use CommonJS export syntax, which means they can't be imported by the browser directly. A strategy I was going to use was to bundle all my node modules up with webpack - eliminating all the disparate export syntaxes - and then just follow the ES6 syntax in my own code. This is apparently impossible, and I don't understand why.
Someone above mentioned something called rollup. Sounds like I may be dropping webpack altogether.

@bsmith-cycorp For libraries, Rollup does seem like our only option right now. That's what I did. Wasn't eager to learn new bundler, but it wasn't too hard.

Here's a little workaround I managed to config:
const Path = require('path');
const path = Path.resolve(__dirname, 'dist');
const EditableSourcesWebpackPlugin = require('editable-sources-webpack-plugin');

{
	entry: "./src/index.js",
	output: {
		filename: "module.js",
		path,
		library: 'x',
		libraryTarget : "window",
	},

	plugins : [
		// export default the compiled module
		new EditableSourcesWebpackPlugin(
			/^module\.js$/,
			sourceCode => ("export default " + sourceCode.slice('window["x"] ='.length)),
		)
	],

	// disable uglify
	optimization: {
		minimizer: []
	},
}

It first export as a global variable window.x, and then change start of the output  source code window["x"] =  into export default.

Is there any news about this?

Feel free to send a PR

Need this feature to publish component with blob url replace web worker require, when using worker-loader

It looks like v5 can potentially solve this ♥

In the future, an alternative code runtime can be used to avoid wrapping the bundle in a IIFE and allow ESM style exports. This will allow ESM as target.

https://github.com/webpack/changelog-v5/blob/master/README.md#runtime-modules

I've spent two days honing our Webpack configuration to build super-optimized UMD-modules, but when I needed to also build it for ESM, well, looks like I'm out of luck and need to start everything from the beginning...
In TypeScript compiler you need to change only a single option to switch from one module format to another. It was some kind of a shock for me to find out that Webpack can't emit modules in ESM format at all.

Just wanted to point out that the new rxjs@6 has switched from deep imports of the required operators to importing all operator names from a single module.
import "rxjs/add/operator/map"; // old way: this added 'map' to the environment
import { map } from "rxjs/operators"; // new way, imports 'map' as a function

Failing to correctly tree-shake rxjs will now lead to huge bundle sizes, and the developers are aware of that. In their documentation, they are now warning that

Using rxjs/operators without making changes to your build process can result in larger bundles. See Known Issues section below.

And they even provide guidance for configuring webpack and a helper.
Unfortunately, all of that is useless if you bundle a library that uses rxjs and is itself built with webpack: the entire rxjs package will be bundled because of non-analyzable CJS require.

Unfortunately, all of that is useless if you bundle a library that uses rxjs and is itself built with webpack: the entire rxjs package will be bundled because of non-analyzable CJS require.

I believe this is a main reason why Rollup is still an only solution for such case. In our organization, we have to maintain two build systems just to be able to publish our code in multiple formats.

Anyway, PR welcome

Am I correct to assume that, for achieving this feature, we need scope hoisting? Looking at the documentation it looks like it is only enabled in production and, most importantly, it has a lot of edge cases.

I've spent two days honing our Webpack configuration to build super-optimized UMD-modules, but when I needed to also build it for ESM, well, looks like I'm out of luck and need to start everything from the beginning...
In TypeScript compiler you need to change only a single option to switch from one module format to another. It was some kind of a shock for me to find out that Webpack can't emit modules in ESM format at all.

It was nearly shocking to me, either. I couldn't create an ES2015 module by Webpack build. It would be great if there is a good solution to Webpack like rollup.

I think it will be possible with webpack@5

Hi @evilebottnawi, 👋
Webpack@5 is still under development? I would like to know when I can use Webpack@5 in my projects. Actually I'm excited to hear about it from you.

@proIT324 in development, and doesn't support output.libraryTarget: 'module', but we refactor code so it will be possible

Hey, @evilebottnawi! is there a roadmap for version 5? It would be very interesting to see what future holds for us.

@evilebottnawi  👍
Sounds great!

Is there any news about when this is going to be ready for use in production?
I've been spending the past three days setting up my Webpack configuration to make my React UI kit consumable as a NPM package. I finally get it working, I include one component in my test project to test if everything works and run a build.
When I inspected the bundle I noticed that all of my components where in there while never being included and/or used in my test project. I was shocked to put in lightly.
I think it's really strange that Webpack even has entire parts of their documentation that revolve around authoring libaries while without the support of making your library three-shakeable using Webpack for this is basically useless.

It is in our roadmap for webpack@5 (not initial), sorry for delay, a lot of work and issues should be fixed and very few developers who want to help

Hello guys, is there any way to help with this feature? I believe it's an essential feature for all the library makers that invested a lot of time in learning Webpack internals and do not want to change the building tool to Rollup.

@knrdhz : Without intending any least disrespect to the maintainers of webpack, nor to deny the special optimizations it may offer, as a regular Rollup user, I find that to be precisely a justification for using Rollup (along with a few crucial plugins) in the first place; it doesn't take a lot of time for others to learn or modify it.
On the other hand, if Webpack came to support this feature, perhaps I as a Rollup user could be persuaded that the time investment to learn Webpack would be worth it as it could meet my ESM needs as well as offer optimizations.

@brettz9: Indeed, although I find the proliferation of tools needed to run my project unproductive.
For all the lost souls who ended up here with us waiting  for the progress, I have found a solution proposed by @purtuga: a Webpack plugin allowing you to author ES module. I tested it briefly and it seems to be providing the very feature we are all looking for: https://github.com/purtuga/esm-webpack-plugin

For all the lost souls who ended up here with us waiting for the progress, I have found a solution proposed by @purtuga: a Webpack plugin allowing you to author ES module. I tested it briefly and it seems to be providing the very feature we are all looking for: https://github.com/purtuga/esm-webpack-plugin

The plugin only adds export statements to the end of files in order to allow using ES6 imports.
It doesn't make the library tree-shakable, which is what everybody is looking for.
It's explained here: https://github.com/purtuga/esm-webpack-plugin#when-using-the-generated-esm-library-un-used-exports-are-not-removed-from-final-output-not-three-shaken

@knrdhz Thank you for wanting to help. Unfortunately, it is not easy to say exactly what and where to do it. The code base is very large and have to many changes. A better way is to send a PR with basic implementation and get feedback through it. If you have questions about the basic implementation, you can ask them here.

There is no doubt that once webpack supports output esm, I will NEVER use rollup again —— I guess lots of people have the same idea as me.

Will webpack 5 be able to output ES modules? The updated webpack documentation contains two options that indicate optimizations for the export keyword. Those two options are new to the docs and do not work with webpack 4:
optimization.providedExports
Tells webpack to figure out which exports are provided by modules to generate more efficient code for export * from .... By default optimization.providedExports is enabled.
optimization.usedExports
Tells webpack to determine used exports for each module. This depends on optimization.providedExports. Information collected by optimization.usedExports is used by other optimizations or code generation i.e. exports are not generated for unused exports, export names are mangled to single char identifiers when all usages are compatible. Dead code elimination in minimizers will benefit from this and can remove unused exports.

@Baedda I think webpack 5 will support module output according to https://webpack.js.org/configuration/experiments/#root

@chenxsan I have tried to make an ES module work with webpack 5.0.0-beta.13 and the following webpack config, but right now it doesn't seem to work yet.
output: {
    module: true
},
experiments: {
    mjs: true,
    outputModule: true
},

But it is really nice to hear that esm support is planned for the future. Can't wait for webpack 5 to be released :)

Just a +1 for this feature, IMHO it is very important for library authors... While other bundlers (perhaps too many) exist, and some can do the trick (i.e. rollup), I find webpack the most complete and production-ready solution out there. But the fact that this feature is missing unfortunately creates room for its competitors to emerge, and the ecosystem to get even more fragmented...

just linking another related feature request: outputting non-bundled files https://github.com/webpack/webpack/issues/2561

I appreciate all the work the Webpack team and contributors are putting in. But that this feature receives so little attention is a bummer. With all major browsers supporting ES modules, Webpack currently stands in the way of leveraging the possibilities modules give us.
A lot of work is being put into a proprietary "Module Federation" #10352 solution which could also be implemented to a large degree using standard ES modules and import maps. I wish half the effort that flows into #10352 would go into implementing ESM support.
Webpack is still the best and most widely used bundler. But with such a huge feature gap it's also slowly becoming a burden for people who have a large codebase depending on it and at the same time wanting to use ESM.

After light reading without diving into the details, module federation sounds like... ES Modules, or at least something that could be built on top of ES Modules. I didn't dive deep into it though.
With native ES Modules, whatever module we import after a route change will be re-used if a previous route has already used that code. So, module federation seems to be built into ES Modules already.
What am I missing?

For any TypeScript authors that just want modules now, try this:
npm i -D rollup-plugin-terser rollup-plugin-typescript2 rollup

Then add a rollup.config.js in your project root:
import path from "path";
import { terser } from "rollup-plugin-terser";
import typescript from "rollup-plugin-typescript2";

export default [
  {
    input: path.resolve(__dirname, "src/Index.ts"),
    output: [
      {
        file: path.resolve(__dirname, "dist/index.js"),
        format: "cjs"
      },
      {
        file: path.resolve(__dirname, "dist/index.es.js"),
        format: "es"
      }
    ],
    external: ["react", "react-dom/server", "@eo-locale/core"],
    plugins: [
      typescript(),
      terser({
        toplevel: true,
        compress: {
          passes: 3,
          pure_getters: true,
          unsafe: true
        },
        output: {
          comments: false
        }
      })
    ]
  }
];

Then just run
rm -rf dist && rollup --config ./rollup.config.js

Note: you might need to change the module property in your tsconfig. I used  "ESNext".

Be patient output.libraryTarget: 'module' is on our roadmap I will be implement for stable webpack@5 release

I made a demo with version 5.0.0-beta.22 but it doesn't seem to work. @evilebottnawi am I doing something wrong or isn't it operational yet in the latest beta?
$ npm install
$ npm run build

ERROR in test.js from Terser
'return' outside of function [test.js:60,9]
    at ee (/test/node_modules/terser/dist/bundle.min.js:1:19541)
    at c (/test/node_modules/terser/dist/bundle.min.js:1:28244)
    at /test/node_modules/terser/dist/bundle.min.js:1:32480
    at /test/node_modules/terser/dist/bundle.min.js:1:28976
    at /test/node_modules/terser/dist/bundle.min.js:1:50966
    at ce (/test/node_modules/terser/dist/bundle.min.js:1:51103)
    at gr (/test/node_modules/terser/dist/bundle.min.js:1:339538)
    at minify (/test/node_modules/terser-webpack-plugin/dist/minify.js:166:7)
    at Object.transform (/test/node_modules/terser-webpack-plugin/dist/minify.js:183:18)
    at execFunction (/test/node_modules/jest-worker/build/workers/processChild.js:140:17)

@coemans It is still under development, bug error is very strange, I want too look at this

@sokra I think we should merge output.module and output.libraryTarget in one option output.format to avoid misleading

Just for info, if somebody stumbles upon this:
es module output didn’t made it into webpack 5 yet.
Alt least not up until now (webpack 5.2.0).

This will be one of the next features we will work on.

So, this issue can be close safely?

For libraries - no

Hello,
What tasks are still pending to resolve this ? I would love to help on this, but I don't know what's left to do.

experiments.outputModule not work，here is a codesandbox demo:
https://codesandbox.io/s/outputmodule-test-uog4c?file=/src/main.js
output onthing~
anybody give me an example, txs!!!

experiments.outputModule not work，here is a codesandbox demo:
https://codesandbox.io/s/outputmodule-test-uog4c?file=/src/main.js
output onthing~
anybody give me an example, txs!!!

experiments.outputModule not work，here is a codesandbox demo:
https://codesandbox.io/s/outputmodule-test-uog4c?file=/src/main.js
output onthing~
anybody give me an example, txs!!!

experiments.outputModule not work，here is a codesandbox demo:
https://codesandbox.io/s/outputmodule-test-uog4c?file=/src/main.js
output onthing~
anybody give me an example, txs!!!

So<EMAIL_ADDRESS>support ESModule now? This issue can be close safely?

So<EMAIL_ADDRESS>support ESModule now? This issue can be close safely?

No, sorry @linxiaowu66 - see this issue:
https://github.com/webpack/webpack/issues/8895#issuecomment-713852053

No, sorry @linxiaowu66 - see this issue:
https://github.com/webpack/webpack/issues/8895#issuecomment-713852053

In progress...
We will start with very basic support, which has a few limitation:

No circular dependencies with externals
A little bit of not really needed runtime
No live-bindings of exports
Not statically analyse-able bundles (no nested bundling)
When top-level-await is used, it must also be supported by the target environment
No runtime chunk
All modules are converted into strict mode (maybe there will be a warning which lists non-strict modules)

But it would allow:

ESM exports from entrypoint
externals that are ESM too
chunk loading via native import()
Initial splitChunks loading via ESM import
Module WebWorkers
Module Federation remote loading via ESM

So this should cover basic needs for applications or some libraries that are consumed at runtime.
The next step would be to get rid of the first 3 limitations when the following conditions are met:

entrypoint is an ESM
exports are not reexported from modules that can't be concatenated with the entrypoint (like CJS, splitChunks)

For other use cases (like bundling a library for consumption via bundler), there is another option we are considering:
No chunking and emitting processed modules as ESM instead.
Instead of joining the modules together into chunks webpack would emit the modules directly (converting them to esm, sometimes wrapping them in functions, module ID => path).

@sokra  Any updates on this? Last I've seen comment wise is from February and I haven't seen much else after sifting through PRs.
I hesitate to overstate the case, however this is one of the most requested features for webpack I can think of. if it had a special library mode like you mentioned, for building shared libraries efficiently, and a separate ESM export mode for production, it would solve so many problems for alot of folks.

I'm working on that, but was distracted by some other stuff. Expect something in the next few days...

@sokra any updates?

Ready for testing https://github.com/webpack/webpack/releases/tag/v5.41.0

I tried the 5.41.0 release, unfortunately I'm still getting this error:
ERROR in external "lit-element"
The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'
Error: The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'

This is with the following config:
        output: {
            path: path.resolve(__dirname, "./dist/js"),
            filename: "[name].js",
            chunkFilename: "[name].js",
            library: {
                type: "module"
            },
            chunkLoading: "import",
            chunkFormat: "module"
        },
        externalsType: "module",
        experiments: {
            outputModule: true
        },

You still on old vesion

I'm on 5.41.0, and lit is definitely ES Module format as I am using it elsewhere directly.

Are you sure? Please provide example, I'm pretty sure that webpack prefer to use non es format due invalid main/exports or other fields in package.json

Yes very sure that lit-element is an es module format, here's a snippet from its package.json:
{
  "name": "lit-element",
  "version": "2.4.0",
  "description": "A simple base class for creating fast, lightweight web components",
  "license": "BSD-3-Clause",
  "homepage": "https://lit-element.polymer-project.org/",
  "repository": "Polymer/lit-element",
  "type": "module",
  "main": "lit-element.js",
  "module": "lit-element.js",
  "directories": {
    "test": "test"
  },
  "files": [
    "/lib/",
    "/src/",
    "!/src/demo/",
    "!/src/test/",
    "/lit-element.d.ts",
    "/lit-element.d.ts.map",
    "/lit-element.js",
    "/lit-element.js.map",
    "/ts3.4/"
  ],

Its a web component base class library, and its used extensively in ES module only environments.

Can you provide small repo I want to look at this

Sure thing, here you go:
https://github.com/benjamind/webpack-modules

Further investigation seems to indicate the module output works if I force the internal environment in the options to module:
        output: {
            path: path.resolve(__dirname, "./dist/js"),
            filename: "[name].js",
            chunkFilename: "[name].js",
            library: {
                type: "module"
            },
            chunkLoading: "import",
            chunkFormat: "module",
            environment: {
                module: true // force module environment
            }
        },

This stops the error, but doesn't result in a valid module output. It appears that for the ES Module externals we're not getting an appropriate chunkId set in the ChunkGraph. This then results in entries like this in the output bundle:
;// CONCATENATED MODULE: external "lit-element"
var x = y => { var x = {}; __webpack_require__.d(x, y); return x; }
var y = x => () => x
const external_lit_element_namespaceObject = x({ ["LitElement"]: () => __WEBPACK_EXTERNAL_MODULE_null__.LitElement, ["customElement"]: () => __WEBPACK_EXTERNAL_MODULE_null__.customElement, ["html"]: () => __WEBPACK_EXTERNAL_MODULE_null__.html });
;// CONCATENATED MODULE: ./src/index.ts

With the __WEBPACK_EXTERNAL_MODULE_null__ being undefined at runtime.

Thanks for feedback, we will fix it

The generated ES6 output contains the lines:
/******/ "use strict"
/******/                Object.defineProperty(exports, '__esModule', { value: true });

I think both lines are not necessary.

            chunkLoading: "import",
            chunkFormat: "module",
            environment: {
                module: true // force module environment
            }

output.module: true is the option you want to set, instead of these internal options. You also need to set experiments.outputModule: true to enable the experiment. Actually these internal options should also require enabling the experiment.

If you see an error like that:
The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'

you want to put only browsers that support ESM into your browserslist, or add an browserslist, or add target: ["web", "es2015"].

There also seem to be a bug that module externals doesn't work correctly when concatenated.

Note that it's still very experimental and work in progress. Still these feedback is very value-able.

The generated ES6 output contains the lines:
/******/ "use strict"
/******/                Object.defineProperty(exports, '__esModule', { value: true });

I think both lines are not necessary.

I don't see Object.defineProperty(exports, '__esModule', { value: true }) anymore in the output.
yes "use strict" is unnecessary and could be removed. Note that minimizing will also remove it.

For now set optimization.concatenateModules: false...

I call webpack --mode development using 5.42.0 with webpack.config.js:
...
export default {
    optimization: {
        concatenateModules: true
    },
    experiments: {
        outputModule: true
    },
    output: {
        library: {
            type: 'module'
        },
        filename: 'abc.js',
        publicPath: '/dist'
    },
    node: { global: false },
    module: {
        rules: [{
            test: /\.styl$/,
            use: [
                MiniCssExtractPlugin.loader,
                preprocessLoader,
                {
                    loader: 'css-loader'
                },
                {
                    loader: 'stylus-loader'
                }
            ]
        }, {
            test: /\.js$/,
            use: [
                preprocessLoader
            ],
            exclude: /node_modules|bower_components/
        }, {
            test: /\.png$/,
            use: 'url-loader'
        }]
    },
    devtool: false,
    plugins: [
        new ESLintPlugin({}),
        new MiniCssExtractPlugin({
            filename: 'abc.css'
        }),
        new webpack.BannerPlugin({
            banner: BANNER,
            entryOnly: true
        })
    ]
};

the resulting file contains:
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/        __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/        // define __esModule on exports
/******/        __webpack_require__.r = (exports) => {
/******/                if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/                        Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/                }
/******/                Object.defineProperty(exports, '__esModule', { value: true });
/******/        };
/******/ })();
/******/

so the line Object.defineProperty(exports, '__esModule', { value: true }); is there.
Since the purpose of IIFE is to protect from namespace pollution and since ES6 modules serve the same purpose, the IIFE-construct above is not necessary.
optimization.concatenateModules: false produces at the end bigger files, when inserted in an external project, using ES6/rollup, terser and then brotli, In my scenario optimization.concatenateModules: false produces bigger files than optimization.concatenateModules: true.  But before switching to ES6 in webpack, my files were even bigger without optimization.concatenateModules: true

@dilyanpalauzov yep, it is bug, we will fix it, so we have it in experiments :+1:

Thanks for the hard work: this generated module code has improved a lot.
I have a question though: what's the story about tree shaking?
After a test, I obtained the following bundle (excerpt).
var __webpack_exports__ = {};

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "K": () => (/* binding */ bar),
  "R": () => (/* reexport */ foo)
});

;// CONCATENATED MODULE: ./src/funcs.js

function foo(a, b) {
    return a + b;
}

;// CONCATENATED MODULE: ./src/index.js

function bar() {
    return "Hello world";
}

var __webpack_exports__bar = __webpack_exports__.K;
var __webpack_exports__foo = __webpack_exports__.R;
export { __webpack_exports__bar as bar, __webpack_exports__foo as foo };

The code populating the __webpack_exports__  makes it impossible to statically analyze the connection between exports and function declarations. An external process attempting to tree-shake this file would not be able to remove the unused functions.

The code populating the __webpack_exports__  makes it impossible to statically analyze the connection between exports and function declarations. An external process attempting to tree-shake this file would not be able to remove the unused functions.

Currently the focus is on creating applications or runtime-consumed libraries and not build-time-consumed libraries (tbh, they should be published unbundled anyway).
Nonetheless this need to be fixed not for tree-shaking support, but for live-binding support.

Currently the focus is on creating applications or runtime-consumed libraries and not build-time-consumed libraries (tbh, they should be published unbundled anyway).

Wait a second, but this is precisely (or a main driver) of why this feature is needed if, I'm not mistaken. This builds and outputs ESM modules which allows downstream build tooling to tree-shake out unused code. This is needed specifically at build time.

Currently the focus is on creating applications or runtime-consumed libraries and not build-time-consumed libraries (tbh, they should be published unbundled anyway).

Wait a second, but this is precisely (or a main driver) of why this feature is needed if, I'm not mistaken. This builds and outputs ESM modules to be published which allows downstream build tooling to tree-shake out unused code.

Nonetheless this need to be fixed not for tree-shaking support, but for live-binding support.

I think this needs to be fixed specifically for tree-shaking support as this is going to be the expected behavior from this feature (as we're already seeing).

Let's make it step by step. The first step is application support.
For real library support there will be a new mode that disables chunking and emit the modules directly (optionally concatenated).

Please update https://github.com/webpack/webpack/projects/8 with what is done and what needs to be done.
Shall new tickets be opened, like for the emitted “use strict”;?

@dilyanpalauzov here fix https://github.com/webpack/webpack/pull/13842

I just used libraryTarget: 'module' to wrap some various libraries from node_modules in to es6 style modules, for development purposes. It is made exactly what I want with no any problems.

@Megabyteceer Can you create reproducible test repo?

@alexander-akait  https://github.com/Megabyteceer/webpack_es6export_bug

@Megabyteceer bug, thanks for the report, just interesting why do you use libraryTarget: 'module' and dependOn together, what is use case?

In development time i use pure js with es6 modules without any bundlers. Problem is many external libraries has no es6 distributibes. I use webpack to convert such a libs in to es6 compatible modules.

@Megabyteceer thanks for information, make sense, I think we will fix it in near future

Should work with webpack@5. Feel free to report new issue with reproducible repo.

@vankop, @donaldpipowitch, @alexander-akait   can anyone please help me with the solution. this issue is closed now but I can't find a way to solve this problem
I am creating a my-common-ui library which will be consumed by applications. But when I import some components still everything from that my-common-ui library is included in the webpack file. (tree shaking is not working)
I am using webpack with typescript in react project.
Things I am using

react ui library with typescript
ts-loader in webpack
using barrel export in every folder's index.ts file

Things I have tried

"sideEffects": false, in package.json
library.type = "module" with experiments.outputModule = true

but still tree shaking is not working

CMIIW, tree shaking doesn't remove the code, but acts on the export statements instead, making the code unreachable (unless it's referenced within the module). Actual removal of the code is left to the minification phase of the build. Can you confirm that you're seeing the unshaken code post minification @jayeshchoudhary? Also, reproducible repo would be nice

CMIIW, tree shaking doesn't remove the code, but acts on the export statements instead, making the code unreachable (unless it's referenced within the module). Actual removal of the code is left to the minification phase of the build. Can you confirm that you're seeing the unshaken code post minification @jayeshchoudhary? Also, reproducible repo would be nice

I can still see the unused functions used in the production mode also

@jayeshchoudhary pls reduce your example to a small reproducible repo, I'll take a look

sure @vankop will do in sometime

Still valid, not finished

tried this repo with webpack.5.52.1 and export still not at the root level: https://github.com/Megabyteceer/webpack_es6export_bug

@Megabyteceer yes, but still exist

I am also facing the same situation as @jayeshchoudhary.
I've put together a repro here:
https://github.com/IsaacWalker/WebpackLibModuleTreeshakeRepro

@vankop
@IsaacWalker I also have same setup with couple of components in it. and I only want those components which are imported and tree shake rest of it
Have you used this in another application and imported just hello-world component.
What did you saw in the final bundle ?
Did only hello-world component comes in final bundle or both hello-world and my-button gets included

So there's two components exported from the library and both are included in the application regardless of whether or not only one is included.
The output of the library is this:
import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "HelloWorld": () => (/* reexport safe */ _hello_world__WEBPACK_IMPORTED_MODULE_0__.HelloWorld),
/* harmony export */   "MyButton": () => (/* reexport safe */ _my_button__WEBPACK_IMPORTED_MODULE_1__.MyButton)
/* harmony export */ });
/* harmony import */ var _hello_world__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var _my_button__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);

/***/ }),
/* 2 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "HelloWorld": () => (/* reexport safe */ _HelloWorld__WEBPACK_IMPORTED_MODULE_0__.HelloWorld)
/* harmony export */ });
/* harmony import */ var _HelloWorld__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);

/***/ }),
/* 3 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "HelloWorld": () => (/* binding */ HelloWorld)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);

/**
 * Hello World
 */
const HelloWorld = props => {
    return (react__WEBPACK_IMPORTED_MODULE_0__["default"].createElement("div", null,
        react__WEBPACK_IMPORTED_MODULE_0__["default"].createElement("a", null,
            "Hello ",
            props.name,
            "!")));
};

/***/ }),
/* 4 */
/***/ ((module) => {

var x = y => { var x = {}; __webpack_require__.d(x, y); return x; }
var y = x => () => x
module.exports = __WEBPACK_EXTERNAL_MODULE_react__;

/***/ }),
/* 5 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "MyButton": () => (/* reexport safe */ _MyButton__WEBPACK_IMPORTED_MODULE_0__.MyButton)
/* harmony export */ });
/* harmony import */ var _MyButton__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);

/***/ }),
/* 6 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "MyButton": () => (/* binding */ MyButton)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);

/**
 * My Button
 */
const MyButton = props => {
    return (react__WEBPACK_IMPORTED_MODULE_0__["default"].createElement("button", { type: "button" },
        "Click Me! ",
        props.text));
};

/***/ })
/******/ ]);
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ 	// Check if module is in cache
/******/ 	var cachedModule = __webpack_module_cache__[moduleId];
/******/ 	if (cachedModule !== undefined) {
/******/ 		return cachedModule.exports;
/******/ 	}
/******/ 	// Create a new module (and put it into the cache)
/******/ 	var module = __webpack_module_cache__[moduleId] = {
/******/ 		// no module.id needed
/******/ 		// no module.loaded needed
/******/ 		exports: {}
/******/ 	};
/******/
/******/ 	// Execute the module function
/******/ 	__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ 	// Return the exports of the module
/******/ 	return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ 	// define getter functions for harmony exports
/******/ 	__webpack_require__.d = (exports, definition) => {
/******/ 		for(var key in definition) {
/******/ 			if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 				Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 			}
/******/ 		}
/******/ 	};
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ 	__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = (exports) => {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "HelloWorld": () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_0__.HelloWorld),
/* harmony export */   "MyButton": () => (/* reexport safe */ _components__WEBPACK_IMPORTED_MODULE_0__.MyButton)
/* harmony export */ });
/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);

})();

var __webpack_exports__HelloWorld = __webpack_exports__.HelloWorld;
var __webpack_exports__MyButton = __webpack_exports__.MyButton;
export { __webpack_exports__HelloWorld as HelloWorld, __webpack_exports__MyButton as MyButton };

but looking back through the thread, what @sokra said leads me to believe this is not possible yet.
What we're looking for is a configuration that will output a result that is consumable by a bundler at build time (where treeshaking occurs), rather than one consumed dynamically in an environment where modules are supported like an application in a modern browser. The former is one of the primary scenarios supported by Rollup, so I think it will have to be done with that for now.
Another feature which is also called out and run into by Typescript is the fact that there is always a single entry chunk output, which conflicts with how Typescript produces d.ts files (to match src in ES module format). I don't believe this would be an issue with the mode mentioned: 'new mode that disables chunking and emit the modules directly'. I believe this is the preserve modules feature supported by Rollup.

@IsaacWalker this issue for ecma modules output, preserveModules is different and have another issue, firstly we need finish edge cases for ecma modules and then we will implement preserveModules option

@IsaacWalker completely got your point and I agree with it. Infact I have tried to bundle my library using rollup and it works perfectly.
I think rollup's output.format = "es" , preserveModules: true and multi entry points does the trick
@alexander-akait @vankop is there currently a way to solve this issue in webpack ?

@jayeshchoudhary impossible right now, to be honest, this is not an easy task, but it is in our roadmap

@alexander-akait thanks for quick response and your help help.
Will love to use this feature when it comes out.

I feel like this is closely related to my issue... That node allows you to import { something } from 'a_commonjs_module', but only if exports had been assigned to directly, with constant names. Webpack assigns to exports more cryptically, and overrides exports... Even exports = exports breaks this feature...
So I made this: https://github.com/alancnet/exports-library-plugin
It's hacky, and maybe only works for me... Offering it up here as a potential solution to people in this thread, and hopefully to catch the attention of someone who would be compelled to implement this properly in Webpack..
A better way to do this would be to have { library: { type: module } } and have it simply assign exports to exports directly. But the code surrounding library is very restrictive, so I consider my approach very sloppy... but it didn't exist before, and now it does.
Cheers!

From what I gathered from this thread, to fully take advantage of ESM through webpack, you need the following settings.
module.exports = {
  experiments: {
    outputModule: true,
  },
  output: {
    library: {
      // do not specify a `name` here
      type: 'module',
    },
    libraryTarget: 'module'
  },
  module: true
};

Do we need both `libraryTarget` and `library.type`?

Reading https://webpack.js.org/configuration/output/#librarytarget-module it doesn't appear to be that way? Although having one or the other or both yields a different output.

You don't need libraryTarget: 'module', libraryTarget is deprecated and maybe we will remove it in the next major release, also you don't need library if you bundle application, you need only experiments.outputModule and output.module

@vankop, @alexander-akait  I tested the new behaviour, and it seems to work. Thanks a lot for implementing it! However, I stumbled upon some minor problems when working with the new implementation.
First, when I try to specify lodash as a external dependency:
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    module: true,
    path: path.resolve(__dirname, 'dist'),
    filename: 'webpack-js-library.bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },
  resolve: {
    extensions: ['.js'],
  },
+  // NOTE: The code below does cause a error when uncommented.
+ externalsType: 'module',
+ externals: {
+   lodash: 'lodash',
+ },
  experiments: {
    outputModule: true,
  },
};

I get the following error:
ERROR in ./src/index.js + 2 modules
The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'
while analysing module external module "lodash" for concatenation
Error: The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'
while analysing module external module "lodash" for concatenation
    at ExternalModule._getSourceData (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/ExternalModule.js:580:12)
    at ExternalModule.codeGeneration (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/ExternalModule.js:616:27)
    at ConcatenatedModule._analyseModule (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/optimize/ConcatenatedModule.js:1654:29)
    at ConcatenatedModule.codeGeneration (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/optimize/ConcatenatedModule.js:1100:9)
    at /home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Compilation.js:3281:22
    at /home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Cache.js:93:5
    at Hook.eval [as callAsync] (eval at create (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/tapable@2.2.1/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Cache.get (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Cache.js:75:18)
    at ItemCacheFacade.get (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/CacheFacade.js:118:15)
    at Compilation._codeGenerationModule (/home/ricks/Development/personal/webpack-js-library/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Compilation.js:3274:9)

Is specifying external dependencies already supported when using the outputModule feature?
Second,  with the new behaviour, Webpack sees the helloWorld.js file as an orphan and does not include it in the bundle.
How to reproduce

Clone the example repository.
Install pnpm.
Install the pnpm dependencies.
Try to build the library using the pnpm build command.

What I already tried
I tried adding the "type": "module" flag to the package.json file like is done in this blog post. However, this does not solve this issue and requires me to specify file extensions for all the .js and .jsx files.

Sounds like your browsers target doesn't support ESM

@alexander-akait Thanks for your fast response. I was under the assumption that the babel-parser also handled the import conversion for packages defined as externals. After some trial and error, I, however, found the right syntax to specify the lodash package as an external dependency:
externalsType: 'module',
externals: {
    lodash: 'umd lodash',
  },

I think the error is caused by the fact that lodash does not use ES6 imports (see this blog. As a result I, should use the ES6 version of lodash (i.e. lodash-es) if I want to omit the umd prefix. I, therefore, tried the following syntax:
externals: {
    'lodash-es': 'lodash-es',
}

However, when doing this, I also get the error as mentioned earlier. This might be caused by the fact that lodash-es uses named imports. Using the 'lodash-es': 'umd lodash-es syntax again seems to work (see this example repo). I'm, however, not sure why I need to specify lodash-es as a umd module since it exports ES6 modules.
I checked the documentation but I can not find a good guide on how to create a ES6 compatible library with webpack (i.e. guides#ecma-script-modules, guides#experimentsoutputmodule, guides#author-libraries and configuration#output). As I think my problems are not related to a bug in the new implementation, I will open a StackOverflow question instead.

Can you create simple reproducible example and I will show you how to fix it or we open an issue if it will be not broken, unfortunately I receive a lot of questions every day and it is much easier for me to help if I see an example of what they want to get and what they actually get, thanks

@alexander-akait Thanks a lot for trying to help me. I cleaned up my reproducible example so that it only contains the required code (see webpack5-esm-library-example).
What I'm trying to achieve is quite basic. Since I am a big fan of Webpack and Webpack now (experimentally) supports ESM modules, I want to convert an ESM library that uses rollup to Webpack. While doing so, I, however, run into some problems. The first problem I'm facing is that I can not find a way to make the library available to others. The second problem is that I can not find the right syntax to exclude external (i.e. optional) packages from the bundle. I checked the documentation about externals, but I have a hard time understanding how to apply it to an ESM library.
Make the library available to be consumed by others
In accordance with the documentation I set the output.library.type to "module". When I try to use the bundle inside my package, it seems to work fine (i.e. node local_importer.js); however, when I try to use it in the CRA demo project, I receive the following error in the chrome console:

Show error
Uncaught TypeError: Cannot set properties of undefined (setting 'runtime')
    at Module.../dist/main.mjs (bundle.js:43152)
    at Module.options.factory (bundle.js:44035)
    at __webpack_require__ (bundle.js:43443)
    at fn (bundle.js:43706)
    at Module../src/App.js (bundle.js:68)
    at Module.options.factory (bundle.js:44035)
    at __webpack_require__ (bundle.js:43443)
    at fn (bundle.js:43706)
    at Module../src/index.js (bundle.js:179)
    at Module.options.factory (bundle.js:44035)

I import the HelloWorld function from the webpack5-esm-library-example module inside the App.js component.
Exclude lodash from the bundle
Let's use lodash library as an example library we want to specify as a Webpack external.  The example can be found on the webpack5-esm-library-example/tree/externals branch. I tried to do this for both lodash and lodash-es, but I got two types of errors. The first error is thrown when I use the following syntax in my webpack.config.js file:
externalsType: "module",
  externals: {
    lodash: "lodash", // NOTE: Throws `The target environment doesn't support EcmaScriptModule syntax` during build.
    // lodash: {
    //   commonjs: "lodash",
    //   amd: "lodash",
    //   root: "_", // indicates global variable
    // }, // NOTE: Throws `The target environment doesn't support EcmaScriptModule syntax` during build.
}

In this case I get the following build error:

Show error
ERROR in external "lodash"
The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'
Error: The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'
    at ExternalModule._getSourceData (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/ExternalModule.js:580:12)
    at ExternalModule.codeGeneration (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/ExternalModule.js:616:27)
    at /home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Compilation.js:3281:22
    at /home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Cache.js:91:34
    at Array.<anonymous> (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/cache/MemoryCachePlugin.js:45:13)
    at /home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Cache.js:91:19
    at Hook.eval [as callAsync] (eval at create (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/tapable@2.2.1/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:19:1)
    at Cache.get (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Cache.js:75:18)
    at ItemCacheFacade.get (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/CacheFacade.js:118:15)
    at Compilation._codeGenerationModule (/home/ricks/Development/personal/webpack5-esm-library-example/node_modules/.pnpm/webpack@5.65.0_webpack-cli@4.9.1/node_modules/webpack/lib/Compilation.js:3274:9)
 @ ./src/ldCapitalize.js 1:0-23 3:9-21
 @ ./src/index.js 3:0-49 3:0-49

This error goes away if I use the following syntax in my webpack.config.js file:
  externalsType: "module",
  externals: {
    lodash: "umd lodash", // NOTE: Builds but throws `ReferenceError: __WEBPACK_EXTERNAL_MODULE_lodash__ is not defined` during run.
  }

In this case, the bundle builds, but I now get an error when I try to consume the library in my package (i.e. node local_importer.js):

Show error
file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:17
module.exports = __WEBPACK_EXTERNAL_MODULE_lodash__;
                 ^

ReferenceError: __WEBPACK_EXTERNAL_MODULE_lodash__ is not defined
    at Object.lodash (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:17:18)
    at __webpack_require__ (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:81:40)
    at eval (webpack://webpack5-library-example/./src/ldCapitalize.js?:6:64)
    at Object../src/ldCapitalize.js (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:47:1)
    at __webpack_require__ (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:81:40)
    at eval (webpack://webpack5-library-example/./src/index.js?:9:74)
    at Object../src/index.js (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:37:1)
    at __webpack_require__ (file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:81:40)
    at file:///home/ricks/Development/personal/webpack5-esm-library-example/dist/main.mjs:121:36
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)

The first problem I'm facing is that I can not find a way to make the library available to others.

As I understand you want to rewrite module system and output ESM and keep file structure of a library, it is still on our roadmap and unsupported yet, but anyway you can generate ESM code for library and you have valid code.

The second problem is that I can not find the right syntax to exclude external (i.e. optional) packages from the bundle.

In this case we should use import ... from ... to load externals, but your target is not supporting it (no browserslist file found and no target was specified, so we use target: 'web', no information about ESM), it can be misleading, but you need specify es* because we don't know which syntax allowed for generated code
You can fix it using:
// Dynamic import is a part of ES 2020
target: ['web', 'es2020']

Even more, you don't need externalsType, it will be module by default, if you set library.type: "module"

however, when I try to use it in the CRA demo project, I receive the following error in the chrome console:

What is CRA version? They released webpack v5 support recently, just want to check it out. Also I strongly recommend do not bundle libraries itself, It just doesn't make sense, Node.js supports ESM, most of applications (for browsers) use bundler, therefore, they will decide for themselves whether they need to convert to ESM or not. Bundling libraries is not good idea at the current time (Yes it may still be needed if you want to continue supporting commonjs/umd if you have ESM code or versa vice). Also bundling libraries reduces their potential optimizations. Just write ESM.
externalsType: "module" and umd lodash is bad idea, you say - load it as umd using ESM, yes, it will not work, maybe we should handle this case and output an error
Anyway bundled library still should to work in CRA, do you have something special in CRA and how you load you library. And why you need bundle library?

@alexander-akait, thanks again for the fast response. I just noticed that the demo submodule was not included in example I now (force) updated the example repo.

As I understand, you want to rewrite the module system and output ESM and keep the file structure of a library, ...

My main goal is to use the react-piano library, which is built with Rollupjs react library, in a CRA v5 app. This library is not defined as an ESM module (i.e. no "type": "module" in the package.json) but does use the ESM import syntax. It uses babel to convert this syntax to "targets": { "node": "6", "browsers": [">0.25%"] }. It uses Rollupjs to make this library available both in umd and es format.
I forked this library since I want to replace the class-based components with functional components and convert them to typescript. I choose first to replace rollup with Webpack since I am more familiar with Webpack. I, however, have no preference for how to export this library. I want to be able to use jsx and sass syntax in the library while using it in a CRA v5 app. Ideally, like the original library, it should also be available for node and  >0.25%.

Also I strongly recommend do not bundle libraries itself, It just doesn't make sense, Node.js supports ESM, most of applications (for browsers) use bundler, therefore, they will decide for themselves whether they need to convert to ESM or not.

What setup and output format would you advise for my library? Should I remove Webpack and write a pure ESM library. In that case, I think I have to use babel to do the jsx conversion and sass for the scss to css conversion?

Anyway bundled library still should to work in CRA, do you have something special in CRA and how you load you library. And why you need bundle library?

I'm using CRA v5 released seven days ago. Adding the 'es2020' target fixed my errors when trying to est the lodash-es ESM module as an external. Thanks a lot! The only problem I'm still experiencing is that I get a runtime error into the chrome console when I try to use it in the CRA v5 demo project.

@alexander I did some more research and found this GIST about pure ESM modules that cleared up a lot of the misunderstandings I have. I think I now understand what you meant with your previous comment.

Also, I strongly recommend do not bundle libraries itself, It just doesn't make sense, Node.js supports ESM, most applications (for browsers) use bundler; therefore, they will decide for themselves whether they need to convert to ESM or not.

With ESM modules, a bundler is not trivial anymore. We can easily create an ESM library without a bundler (see webpack5-esm-library-example/tree/no-webpack. This module will work with most browsers and all non-deprecated Node versions.
We, therefore, do not need Webpack to create ESM libraries. We, however, can use Webpack for creating an ESM library if we want to use features that are not natively supported in ES2015 (e.g. style sheet injection and JSX). If we want to do this, we have to:

Convert your webpack.config.js to an ESM module.
Enable the experiments.outputModule option to ensure Webpack outputs ECMASCript module syntax when possible.
Enable output.module to ensure that javascript files are outputted as ESM modules.
If you want your library to be consumed by others, make sure to set the output.library.type flag to module.
Point the package.json exports property to your outputted bundle.
If you want your ESM library to work with a CRA app, you must also specify the "browser": "./build/index.js", entry in your package.json. One known issue is #10933.

An example can be found in rickstaa/webpack5-esm-library-example/tree/webpack-react-css. When we choose this method, we have to make sure that we add external third-party libraries to the externals field of the Webpack config.

Anyway bundled library still should to work in CRA, do you have something special in CRA and how you load you library. And why you need bundle library?

I found the cause of my bundle not working with the CRA. It was because I used Webpack in development mode. The ESM library works fine in production mode (i.e. npm run build) but in development mode (i.e. npm run build:dev), I get the following error:

Show error
ReactRefreshEntry.js:23 Uncaught TypeError: Cannot set properties of undefined (setting 'runtime')
    at Module.../dist/webpack5-esm-library-example.bundle.mjs (ReactRefreshEntry.js:23)
    at Module.options.factory (react refresh:6)
    at __webpack_require__ (bootstrap:24)
    at fn (hot module replacement:61)
    at Module../src/App.js (logo.svg:34)
    at Module.options.factory (react refresh:6)
    at __webpack_require__ (bootstrap:24)
    at fn (hot module replacement:61)
    at Module../src/index.js (App.js:30)
    at Module.options.factory (react refresh:6)
../dist/webpack5-esm-library-example.bundle.mjs @ ReactRefreshEntry.js:23
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
fn @ hot module replacement:61
./src/App.js @ logo.svg:34
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
fn @ hot module replacement:61
./src/index.js @ App.js:30
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:7

This error can be reproduced on rickstaa/webpack5-esm-library-example/tree/webpack-react. I'm not sure if this is a bug in Webpack or a problem with my setup. I will try to investigate why this happens.

Thanks, I will look at this in near future

Amazing. No hurries, thanks again for looking at my problem! Can I ask you one last quick question:

You can fix it using:
// Dynamic import is a part of ES 2020
target: ['web', 'es2020']

Why did you specify both web and es2020? Shouldn't specifying es2015 be enough since most modern browsers support this version? Which target would you recommend bundling an ESM library with Webpack for use in CRA v5 apps?

ES2020 is version of ECMA (i.e. JavaScript) language, web is browser and it is a platform, for example you use node/electron/'webworker'/etc, you even mix them, but note - not all combinations supported, so you need to specify language and platform. What is better? Depends on which browsers you want to support. You can use browserslist config file for this, it will be more predictable.

Ah, thanks a lot! I understand it now. I was under the impression that when you specified es2015, it would apply to all platforms, but this makes more sense since some combinations might not yet be supported.

@alexander-akait Here is some extra information I found today while debugging the above problem.

The issue looks related to #11277, but should have been fixed when<EMAIL_ADDRESS>was released. In my setup contrary to your comment in https://github.com/webpack/webpack/issues/11277#issuecomment-991714971, Webpack version used is v5.65.0 both in the library and the app (see https://github.com/rickstaa/webpack5-esm-library-example/tree/webpack-react-jsx-transform-ejected).
The issue seems to be thrown while executing the ReactRefreshEntry.js script of the react-refresh-webpack-plugin and might be related to https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/328.
I also noticed that the problem only exists when I compile the library in development mode while using the npm start command for the CRA app that consumes the library. The issue disappears when I use npm build for the CRA app.

It, therefore, looks like the issue is because I have two runtimes in my setup, one from the library and one from the CRA that consumes the library.  However, I am not sure if it is a Webpack, CRA or Babel problem.
I use this setup (i.e. Babel -> Webpack -> CRA app) since I want to create an ESM React Component library. I need Babel for the JSX transpilation, and Babel is very easy to set up when using Webpack. I will replace Babel with ts-loader in the future. I use the development mode to debug my library while using hot module replacement.
I just wanted to put this here might you have time to look at this problem in the future. For now, happy holidays! 🎄

module.exports = {
  experiments: {
    outputModule: true,
  },
  output: {
    module: true,
  },
};

So this is what I've been using now, however it only works with...
{
  output: {
    chunkLoading: false
  }
}

or else you'll get...
ERROR in webpack/runtime/import chunk loading
Cannot read properties of undefined (reading 'getChunkConditionMap')

ERROR in webpack/runtime/import chunk loading
Cannot read properties of undefined (reading 'getChunkConditionMap')

ERROR in webpack/runtime/import chunk loading
Cannot read properties of undefined (reading 'getChunkConditionMap')

@rodoabad Yep, bug, we need to fix it

Thanks, @alexander-akait!

@rodoabad Can you show browserslist content, I think there is problem - environment is not supported ESM, we just need to improve error message here, just want to check

@alexander-akait our browserslist is very aggressive.
module.exports = [
    'last 2 Chrome versions',
    'last 2 Edge versions',
    'last 2 Firefox versions'
];

Give me time I will check it :+1:

@alexander-akait no worries man! You do this on your free time. By all means take your time.

@rodoabad strange, I can't reproduce it using fresh setup, do you have more configuration, also can you run npm ls webpack?

I was also unable to reproduce it...
since it say import chunk loading it uses import() for chunk loading, so browser support for that is detected.
getChunkConditionMap is a method on the ChunkGraph, so that should definitely exist...

Yep, me too, maybe non official plugin

After going through all aspects, here is my configuration，
module.exports = {
  target: [
    'web',
    'es2020'
  ],
  output: {
    path: './dist',
    filename: 'index.esm.js',
    library: {
      type: 'module'
    }
  },
  experiments: {
    outputModule: true
  },
  externalsType: 'module',
  externals: {
    vue: {
      commonjs: 'vue',
      commonjs2: 'vue',
      amd: 'vue',
      root: 'Vue',
      module: 'vue'
    },
    react: {
      commonjs: 'react',
      commonjs2: 'react',
      amd: 'react',
      root: 'React',
      module: 'react'
    },
    'react-dom': {
      commonjs: 'react-dom',
      commonjs2: 'react-dom',
      amd: 'react-dom',
      root: 'ReactDOM',
      module: 'react-dom'
    }
  },
}

@maskletter Do you have the same problem?

@maskletter你有同样的问题吗？

@maskletter Do you have the same problem?

I haven't done a lot of tests yet. I'm just trying. I haven't reported any errors at present

@maskletter Do you have the same problem?

I haven't done a lot of tests yet. I'm just trying. I haven't reported any errors at present

I've reproduce this issue
Minimal reproductible repo is available here https://github.com/daividh/webpack-issue

Just made a test with module libraryTarget.
It don't seems to work in combination with dependOn.
This leads to such an error:
ERROR in main.js
main.js from Terser plugin
"Export" statement may only appear at the top level [main.js:57,9]

Config
    entry: {
      'lib/shared/shared': {
        import: 'lit'
      },
      main: {
        import: './src/main.js',
        dependOn: 'lib/shared/shared'
      }
    },

    output: {
      path: path.resolve(__dirname, "dist"),
      filename: '[name].js',
      library: {
        type: "module",
      },
    },
    experiments: {
      outputModule: true,
    },

@msteller-connyun can you provide reproducible repo?

here's the link to a demo repo of the issue:
https://github.com/msteller-connyun/issue-webpack5-module-dependOn
If you remove dependOn: 'lib/shared/shared', it will work.

@alexander-akait You asked me if I could reproduce the error. I finally figured out why I keep having the meta error.
It was because in my HTML Webpack Plugin, it was defaulting to defer instead of module.
For anyone reading this that's using the HTML Webpack Plugin, make sure to update that as well.
It was a pretty big oversight for that, I thought it would automatically switch if module: true was set.
I believe everything is working now and we'll try and publish one of our internal apps for this to see how things fare.

Update, when I do have this setup. I get this error.
Path variable [chunkhash] not implemented in this context: [name].[chunkhash].js

I had to use fullhash instead.
// base.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const rules = require('./rules');

const isDevelopment = process.env.NODE_ENV !== 'production';

module.exports = {
    // cache: {
    //     type: 'filesystem'
    // },
    experiments: {
        outputModule: true
    },
    module: {
        rules
    },
    output: {
        clean: true,
        filename: isDevelopment ? '[name].js' : '[name].[chunkhash].js',
        module: true
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: isDevelopment ? '[name].css' : '[name].[chunkhash].css'
        }),
        ...[isDevelopment && new ReactRefreshWebpackPlugin()].filter(Boolean)
    ],
    resolve: {
        extensions: ['.js', '.ts', '.tsx', '.json']
    },
    stats: {
        colors: true
    }
};

// rules.js
const {loader: miniCssExtractLoader} = require('mini-css-extract-plugin');
const autoprefixer = require('autoprefixer');

const isDevelopment = process.env.NODE_ENV !== 'production';

module.exports = [
    {
        test: /\.(png|svg|jpg|jpeg|gif|woff|woff2|eot|ttf|otf)$/i,
        type: 'asset'
    },
    {
        exclude: /node_modules/,
        test: /\.(js|jsx|ts|tsx)$/i,
        use: [
            {
                loader: require.resolve('babel-loader'),
                options: {
                    plugins: [isDevelopment && require.resolve('react-refresh/babel')].filter(Boolean)
                }
            }
        ]
    },
    {
        test: /\.(sa|sc|c)ss$/i,
        use: [
            miniCssExtractLoader,
            {
                loader: require.resolve('css-loader'),
                options: {
                    importLoaders: 2,
                    modules: {
                        auto: true,
                        localIdentName: isDevelopment ? '[path][name]__[local]' : '[hash:base64]'
                    }
                }
            },
            {
                loader: require.resolve('postcss-loader'),
                options: {
                    postcssOptions: {
                        plugins: [
                            autoprefixer()
                        ]
                    }
                }
            },
            {
                loader: require.resolve('sass-loader'),
                options: {
                    sassOptions: {
                        quietDeps: true
                    }
                }
            }
        ]
    }
];

// build.config.js
// Unpublished Work © 2018-2021 Deere & Company

const baseConfig = require('./base');
const {merge} = require('webpack-merge');
const path = require('path');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');

const buildConfig = {
    mode: 'production',
    devtool: 'source-map',
    entry: './src/index.js',
    output: {
        path: path.join(process.cwd(), 'dist')
    },
    optimization: {
        minimize: true,
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin({
                minify: TerserWebpackPlugin.esbuildMinify
            })
        ],
        runtimeChunk: true,
        splitChunks: {
            chunks: 'all',
            minSize: 10000,
            maxSize: 250000
        }
    }
};

module.exports = merge(baseConfig, buildConfig);

@rodoabad

It was a pretty big oversight for that, I thought it would automatically switch if module: true was set.

Hm, I think it should work as you written, feel free to open an issue

v

Just interesting why not contenthash?

I ran into an issue today where runtimeChunk: single led to the following code being generated:
(__webpack_require__) => {
  var __webpack_exec__ = (moduleId) =>
    __webpack_require__((__webpack_require__.s = moduleId));
  var __webpack_exports__ = __webpack_exec__(5930);
  var __webpack_exports__Color = __webpack_exports__.Il;
  var __webpack_exports__ConfigTypes = __webpack_exports__.yQ;
  var __webpack_exports__DesignBlockType = __webpack_exports__.Ju;
  var __webpack_exports__MimeType = __webpack_exports__.HY;
  var __webpack_exports__Role = __webpack_exports__.uU;
  var __webpack_exports__default = __webpack_exports__.ZP;
  export {
    __webpack_exports__Color as Color,
    __webpack_exports__ConfigTypes as ConfigTypes,
    __webpack_exports__DesignBlockType as DesignBlockType,
    __webpack_exports__MimeType as MimeType,
    __webpack_exports__Role as Role,
    __webpack_exports__default as default,
  };
};

with Terser rightfully complaining that the export statement can only appear at the toplevel.
This error was not occurring with devTool: 'eval', and manifested only in the production build.
I can provide further details if that helps.

@janv Looks like bug, can you provide example? Thanks

@alexander-akait I managed to create a minimal example: https://github.com/janv/webpack-esm-runtimechunk-error

@janv adding these configuration should help:
  output: {
    chunkLoading: 'import',
    chunkFormat: 'module',
  },

Alternatively that would help target: 'node12.17'
Seems like we are detecting an environment that doesn't support import(), so we are not choosing ESM as chunk loading/chunk format, but only ESM chunk format correctly supports library: { type: "module" } with runtime chunk.
I guess we probably should automatically choose chunkFormat: 'module' when using library: { type: "module" }.

Thank you very much! This helped indeed to solve that particular problem.
However, it uncovered another issue: In our particular project, we have entry chunks that depend on each other.
This leads to a situation, where webpack generates code that contains two export defaults! This also strikes me as something that should not be happening. A possible solution might be to always export __webpack_require__ as a named export, not as a default export.
I have again recreated a minimal example here (same repo, different branch): https://github.com/janv/webpack-esm-runtimechunk-error/tree/duplicate-export-default

janv
I would like to ask how to use the generated chunk file，when i import the chunk in another project, an error occurred

Looks like import assertions are being stripped out from external modules. These are needed to import JSON files under nodejs v18.x.
import tlds from "tlds" assert { type: "json" };

Becomes:
import * as __WEBPACK_EXTERNAL_MODULE_tlds__ from "tlds";

To be honest I didn't troubleshoot this too much. I'm running Webpack v5.73.0 with a pretty in depth configuration that I'm migrating to module output. It's possible babel or someone else is stripping them before it gets to Webpack but I thought I would raise it here. I can work around it by bundling the small handful of JSON files.

@laverdet sounds like a critical bug, can you open an issue?

I have followed the documentation, read through much of this issue, tried several of the solutions others have seen work but I still cannot get a library built with webpack to be tree-shakable.
Currently this is all there is to that library configuration (also has sideEffects: false in the package.json):
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
	entry: path.resolve(__dirname, './src/index.js'),
	mode: 'production',
	module: {
		rules: [
			{
				include: path.resolve(__dirname, './src'),
				test: /\.(js|ts|tsx)$/,
				use: ['babel-loader'],
			},
		],
	},
	optimization: {
		minimize: false,
		mangleExports: false,
	},
	output: {
		filename: 'index.js',
		path: path.resolve(__dirname, './dist'),
		library: {
			type: 'module',
		},
		chunkFormat: 'module',
		module: true,
	},
	resolve: {
		extensions: ['.tsx', '.ts', '.js', '.jsx'],
	},
	experiments: {
		outputModule: true,
	},
	devtool: false,
	target: ['web', 'es2020'],
};

I've set up a repository with a both a Webpack app and a Vite app that consume test libraries built by most of the modern JS build tools (Babel, ESBuild, Vite, Webpack) and it correctly treeshakes the exports from all of the libraries except for the one built with Webpack. We see the same when importing the library built with Webpack into a Vite app.
I feel like I may be missing something obvious here but can't seem to get it to work with Webpack.

@WalterWeidner Why you need webpack to build ESM library? I think better to keep source code in ESM in nowdays

@WalterWeidner Why you need webpack to build ESM library? I think better to keep source code in ESM in nowdays

There may be many reasons someone needs to build their source code to deliver their ESM library. Off the top of my head could be to deliver to JS code for Vue/React/Angular/etc components, compiled typescript, bundling/externalizing particular dependencies, and reducing potential conflicts with various configs. Compiling typescript with tsc might suffice for simple TS modules, but it gets more complicated with delivering a framework specific component library from Vue SFCs, React JSX, or Angular component files.

@WalterWeidner Why you need webpack to build ESM library? I think better to keep source code in ESM in nowdays

Libraries with source code in TypeScript need a build pipeline and simple tsc doesn't work for many use cases listed here. Besides, it'd be nice to be able to leverage the webpack ecosystem for plugins like ImageMinimizer while still delivering an ESM library the users can tree-shake.
Achieving any of these use-cases isn't impossible today but would get a lot easier with webpack.

@WalterWeidner Why you need webpack to build ESM library? I think better to keep source code in ESM in nowadays

There is some consensus that consuming a library made of a single "Flat ESM" module (FESM) is more performant for downstream tools than consuming a library made up of tons of small ESM modules.
Angular strongly advocates using FESM, shipping all their packages with ESM bundles as a primary format and also advising developers to do the same for their libraries. Of course, the tooling used today requires additional post-processing via Rollup.

@WalterWeidner Why you need webpack to build ESM library? I think better to keep source code in ESM in nowdays

I am curious about why the output configuration options for library exists in Webpack if you feel this way. Is it meant to accomplish something different? It was always my assumption that its purpose was for something like what I am trying to do.

@WalterWeidner Yeah, I see your problem, library original was design for commonjs/umd/etc, when we don't have ESM, when we implement ESM library (with keep original tree and we have paln to do it), anyway can you create reproducible example and desribe the problem, I will look, thank you

@WalterWeidner Yeah, I see your problem, library original was design for commonjs/umd/etc, when we don't have ESM, when we implement ESM library (with keep original tree and we have paln to do it), anyway can you create reproducible example and desribe the problem, I will look, thank you

@alexander-akait pulling this repository and then running yarn && yarn build should output what I am seeing. The whole purpose of that repository is to help pinpoint the trees-haking issues we were seeing in a very basic environment. If that's not what you need I am happy to spin up something else to help get to root of the problem more quickly.

@WalterWeidner Yeah, I see your problem, we generate __webpack_require__.d, and that is prevent us for tree shaking, we should improve it for libraries

@WalterWeidner Yeah, I see your problem, we generate __webpack_require__.d, and that is prevent us for tree shaking, we should improve it for libraries

How likely is this to be implemented? We might need to adjust our build to use something else if this is unlikely to happen.

Any updates? I want to use it for libraries, too


onLeave isn't fired when onPositionChange does

        <Waypoint
          onPositionChange={position => console.log(position)}
          scrollableAncestor={typeof window !== 'undefined' && window}
          onEnter={this.showHeaderButtons}
          onLeave={this.hideHeaderButtons} />

onLeave fires when scrolling normally.
But when scrolled to the bottom of the page and then refreshing the page the browser scrolls to the bottom when the page has been loaded and while onPositionChange fires correctly with the above updated position onLeave doesn't get called at all.

(in case you're interested why do I use scrollableAncestor it's because of react-sticky for the sticky header)

So, the cause seems to be this code:
    if (currentPosition === POSITIONS.inside) {
      this.props.onEnter.call(this, callbackArg);
    } else if (previousPosition === POSITIONS.inside) {
      this.props.onLeave.call(this, callbackArg);
    }

Obviously enough, when a page has just been refreshed there's no previousPosition therefore onLeave doesn't fire.
Is it the intended behaviour and this bug won't be ever fixed, or should that else condition be modified to:
    if (currentPosition === POSITIONS.inside) {
      this.props.onEnter.call(this, callbackArg);
    } else if (!previousPosition || previousPosition === POSITIONS.inside) {
      this.props.onLeave.call(this, callbackArg);
    }

@halt-hammerzeit , I believe this expected behavior with the current API of React Waypoint.
Your proposed solution solves your use case, but makes any and all waypoints that are mounted outside of the frame fire onLeave. That doesn't make much sense to me, and I think we would get many more issues if we changed it to function that way.
To me, the contract of onLeave is simply that it was once in the frame, and now it is no longer in the frame. If it is mounted outside of the frame, then onLeave shouldn't be called.
I believe the source of this problem is an incorrect assumption about the initial state of the web app. You are assuming that when your app is mounted, the page will always be scrolled to the very top of the page. This example here demonstrates that a browser could auto-scroll before the waypoint mounts.
With this knowledge, you should be able to write a workaround that works for your use case. If not, then perhaps something like an onMount callback could be added, which has the position of the waypoint at mount time. Then you could conditionally check if a waypoint that you assumed would start in-frame is starting out of frame.
I'm also seeing a similarity between this issue and this particular comment in the scrollspy thread: https://github.com/brigade/react-waypoint/issues/112#issuecomment-234811604 . They're not exactly the same, but it's possible that accepting children ( #152 ) could help with this.

Ok, thanks for the detailed answer.
I'll still with this workaround then, and anyone coming from Google can use it too, since it's 100% working in this scenario

I'm curious to hear @lencioni 's and @trotzig 's take on this issue. They may be in favor of this change you're describing, or they might have other solutions that could help.

Well, they could introduce a React property for that, for example.
If they find that a common issue.

While I understand that this is a little confusing, I think the assessment made by @jmeas is right. I appreciate you reporting your findings though @halt-hammerzeit, and for providing a workaround.

Should we add some information to the readme about this?

I was thinking that, @lencioni . I can PR a thing up later today, unless you'd like to take a stab at it.

As an aside, I could be convinced of there being a callback as a prop that is fired immediately when the component mounts, which is passed the initial position. To implement this, we would need the callback prop to be called after this line.
An example API would be:
<Waypoint
  onMount={initialPosition => console.log(`This waypoint mounted at ${initialPosition}`)}
  onEnter={this.onEnter}/>

I'm not convinced that we need this right now, but if someone could show that it:

enables them to do something they cannot do with a workaround
enables them to clean up a really messy workaround to be much cleaner

then I'd likely be :+1: for this new prop.


Getting started tour

In the getting started UI currently we provide 3 steps, however each takes the user directly there rather than teaching them how to use the app.
Replace the current links to instead activate tours, where users are guided in how to complete the action.

 Onboarding 3.0


Feature Request: API

Great project and thanks for keeping it updated.
I think it would be great if this project can abstract it's data calls via an API.
For me own project, I'm going to start working on adding a separate project to host the API as a separate client, however, I've seen other Clean Architectures, like the one I came from Blazor Starter Kit, layer out the data calls.
I'll try my best to adda PR for this, but I'm not confident in my skills just yet for a project like this.

I believe adding an extra API layer in a Blazor Server project may add unnecessary complexity.


init changeset

Notes for Reviewers
This PR fixes #
Signed commits

[ ] Yes, I signed my commits.

closing for now


Pod/Deployment doesn't restart although recognized by the operator

Versions
Server Version: version.Info{Major:"1", Minor:"18+", GitVersion:"v1.18.17-gke.1901", GitCommit:"b5bc948aea9982cd8b1e89df8d50e30ffabdd368", GitTreeState:"clean", BuildDate:"2021-05-27T19:56:12Z", GoVersion:"go1.13.15b4", Compiler:"gc", Platform:"linux/amd64"}
Operator: v0.1.0
Problem
Pod does not restart even though the secret was updated
Expected result
Pod should restart as soon as the secret is updated, instead only the secret gets updated
Logs
│ 2021-07-15T19:28:44.164Z    INFO    controllers.DopplerSecret    [/] Secrets have been modified    {"dopplersecret": "external-secrets/dopplersecret-test", "verifyTLS": true, "host": "https://api.doppler.com", "oldVersion": "W/\"70d6dcadc0177a11c86e856195e8be2c1078975aaa2fb7ab37ae1db4b5aa03ec\"", "newVersion": "W/\"f37c20815bb0f7c177425f50e14e8051588f0c011e5 │
│ 2021-07-15T19:28:44.170Z    INFO    controllers.DopplerSecret    [/] Successfully updated existing Kubernetes secret                                                                                │
│ 2021-07-15T19:28:44.178Z    INFO    controllers.DopplerSecret    Finished reconciling deployments    {"dopplersecret": "external-secrets/dopplersecret-test", "numDeployments": 1}

Configs
apiVersion: secrets.doppler.com/v1alpha1
kind: DopplerSecret
metadata:
  name: dopplersecret-test # DopplerSecret Name
  namespace: external-secrets
spec:
  tokenSecret: # Kubernetes service token secret (namespace defaults to doppler-operator-system)
    name: doppler-token-secret
    namespace: doppler-operator-system
  managedSecret: # Kubernetes managed secret (will be created if does not exist)
    name: doppler-test-secret
    namespace: external-secrets # Should match the namespace of deployments that will use the secret
---
apiVersion: v1
kind: Pod
metadata:
  name: doppler-busybox
  namespace: external-secrets
  annotations:
    secrets.doppler.com/reload: 'true'
spec:
  containers:
  - name: busybox
    image: busybox:glibc
    command:
      - sleep
      - "3600"
    envFrom:
      - secretRef:
          name: doppler-test-secret

Hi @rchenzheng! 👋
Thanks for sending this in and providing excellent details! The problem here is that the Doppler operator currently monitors deployment resources, not pods. Here's an example deployment that uses reloading: https://github.com/DopplerHQ/kubernetes-operator/blob/main/config/samples/deployment-envfrom.yaml
You should be able to change your pod definition to a deployment definition by moving the current spec into the template field.
Is there any reason why you might want to use a pod instead of a deployment?

Hi @rchenzheng! 👋
Thanks for sending this in and providing excellent details! The problem here is that the Doppler operator currently monitors deployment resources, not pods. Here's an example deployment that uses reloading: https://github.com/DopplerHQ/kubernetes-operator/blob/main/config/samples/deployment-envfrom.yaml
You should be able to change your pod definition to a deployment definition by moving the current spec into the template field.
Is there any reason why you might want to use a pod instead of a deployment?

This is currently a POC, but I'd like if it could support all type of workloads since my use cases make use of most.
ie. statefulsets, daemonsets, replicasets, etc...

Ah, understood -- thanks for the feedback! I'll bring up those use cases with the team.

Ah, understood -- thanks for the feedback! I'll bring up those use cases with the team.

I think it'd a fairly common use case, is there any timeline for adding support?

We don't have a timeline currently for adding support for other Kubernetes workloads.
In the meantime though, one solution would be to use the Doppler operator to sync secrets from Doppler to Kubernetes and use another reloading solution (such as Reloader) to automatically restart your workloads when those secrets change.

Would like to request this also. Usually you have an annotation on the pod spec that a controller would update and that would trigger a restart.


k4LCIOReader crashes when used in standalone application

Our goal is to implement the k4LCIOreader as a standalone application to read and convert LCIO files. We have run into a Segmentation Fault in edm4hep::ReconstructedParticleCollectionData::setReference, when trying this on miniDST files. Below is a list of commands to reproduce the error.
First you clone the github repository with the minimal reproducer and afterwards source the setup file from the nightlies.hsf to get the environment set up.
git clone --branch lcioedmconv https://gitlab.desy.de/ftx-sft-key4hep/edmconverter.git

source /cvmfs/sw-nightlies.hsf.org/spackages5/key4hep-stack/master-2022-08-03/x86_64-centos7-gcc11.2.0-opt/gmz2k/setup.sh

After that is done you build the reproducer.
cd edmconverter

mkdir build

cd build

cmake ..

make

download the miniDST file
cd ..

wget https://desycloud.desy.de/index.php/s/5LmrjGWqziQfMe7/download/rv01-16-p10_250.sv01-14-01-p00.mILD_o1_v05.E250-TDR_ws.I106479.Pe2e2h.eL.pR-00001-ILDminiDST.slcio

The programm is run with gdb to get the seg fault. Without gdb the programm just freezes in our case.
cd build

gdb -ex run --args ./minimalrep "../rv01-16-p10_250.sv01-14-01-p00.mILD_o1_v05.E250-TDR_ws.I106479.Pe2e2h.eL.pR-00001-ILDminiDST.slcio"

We are unsure whether this issue arises because the miniDST format has some Collections dropped. Or also because it has subset Collections. The Collection used in this case is not a subset Collection, but in a test case using a subset Collection the subset flag did not propagate through the program to the point where the references where set and the same seg fault came up.

The same issue also happened with a few other data tiers.
In another attempt I replaced the store.get function with k4reader.getCollection. This finished without any issue.
It seems things break as soon as podio tries to resolve relations. Does this mean that the k4LCIOReader does not handle relations?

What do you mean by relations? LCRelation collections, or something else?

In this case relations are the OneToOneRelations/OneToManyRelations between edm4hep types, e.g. the crash above is when the ReconstructedParticles try to resolve their relations to the Vertex (in startVertex).

But the crash also happens when you use k4reader.getCollection (I think this you have to do in any case)?

I added the a changed version using k4reader.getCollection to the github called working_minimalrep.
By just doing every step the same as before and just replacing this line:
gdb -ex run --args ./minimalrep "../rv01-16-p10_250.sv01-14-01-p00.mILD_o1_v05.E250-TDR_ws.I106479.Pe2e2h.eL.pR-00001-ILDminiDST.slcio"
with this line:
gdb -ex run --args ./working_minimalrep "../rv01-16-p10_250.sv01-14-01-p00.mILD_o1_v05.E250-TDR_ws.I106479.Pe2e2h.eL.pR-00001-ILDminiDST.slcio"
The new Version gets run. It exits normally without any issues.

I also tried calling k4reader.getCollection and only afterwards call store.get. This also crashes.