Hi, thank you for the great tool.
I have a question. It might be a bug.
To import modules with pkg.module field (not main field) if possible, I wrote a webpack.config.js like:
module.exports = {
// ...
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']},
// ...
};
That worked fine in Webpack 3.
However, in Webpack 4, it seems that the specific is ignored when nested importing. That is, for example, a mod-A is imported with module field correctly, but a mod-B that the mod-A imports is imported with main field even if module field is given.
I added below, then that worked fine.
module.exports = {
// ...
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']},
module: {
rules: [
{
test: require('path').resolve(__dirname, 'node_modules'),
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']}
}
]
}
// ...
};
I found this: https://github.com/webpack/webpack/wiki/Changelog-WIP
Resolving can now be configured with
module.rules[].resolve. It's merged with the global configuration.
It seems that the default module.rules[].resolve is used when that is not specified, and the global configuration is ignored.
I tried resolve: {mainFields: []} as the module.rules[].resolve, and I expected that the empty mainFields list is merged with the global mainFields list, but an error "Module not found" occurred. That is, it seems that the global mainFields was ignored.
Is this correct behavior of Webpack 4?
And also, to import all modules with pkg.module field, are both the first and the second resolve required?
(Sorry, my English is poor.)
It looks like you just deleted our lovely crafted issue template. It was there for good reasons. Please help us solving your issue by answering the questions asked in this template.
Sorry, I try that.
Do you want to request a feature or report a bug?
Maybe, bug. (because I couldn't find document about this change from Webpack 3.)
What is the current behavior?
resolve.mainFields is ignored, and modules are imported with pkg.main.
If the current behavior is a bug, please provide the steps to reproduce.
To import modules with pkg.module field (not main field) if possible, I wrote a webpack.config.js like:
module.exports = {
// ...
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']},
// ...
};
That worked fine in Webpack 3.
However, in Webpack 4, it seems that the specific is ignored when nested importing. That is, for example, a mod-A that my script as entry imports is imported with module field correctly, but a mod-B that the mod-A imports is imported with main field even if module field is given.
I added below, then that worked fine.
module.exports = {
// ...
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']},
module: {
rules: [
{
test: require('path').resolve(__dirname, 'node_modules'),
resolve: {mainFields: ['module', 'jsnext:main', 'browser', 'main']}
}
]
}
// ...
};
I found this: https://github.com/webpack/webpack/wiki/Changelog-WIP
Resolving can now be configured with
module.rules[].resolve. It's merged with the global configuration.
It seems that the default module.rules[].resolve is used when that is not specified, and the global configuration is ignored.
I tried resolve: {mainFields: []} as the module.rules[].resolve, and I expected that the empty mainFields list is merged with the global mainFields list, but an error "Module not found" occurred. That is, it seems that the global mainFields was ignored.
What is the expected behavior?
Modules should be imported with resolve.mainFields when the field is given.
Also, the global configuration should be used when module.rules[].resolve is not specified.
Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.
Thanks for your report. It would be great if you reduce your issue to a small reproducible example. Best put this example into a github repository together with instructions how to get to the problem.
Ok, I will try that soon.
Please try this example.
https://github.com/anseki/webpack-issue6796-ex.git.node_modules directory and mod-a and mod-b example packages.Read source files that contains few lines.
entry.js: A file as entry point. It imports mod-a and mod-b.node_modules/mod-a/mod-a.js / mod-a.mjs: A package that has both main and module fields.node_modules/mod-b/mod-b.js / mod-b.mjs: A package that has both main and module fields. It imports mod-a.There are three import statements.
Run a command to install webpack and webpack-cli.
npm install
npm run conf1
npm run conf2
md5-6f6d33c5c3a469fbb3647e741b3e4b8d
npm run conf3
md5-0076430d9b72a94f694fae0a17731c5f
This is "entry.js".
CALL: ModA.method1()
This is "mod-a" package - "main" field - "mod-a.js".
CALL: ModB.method1()
This is "mod-b" package - "main" field - "mod-b.js".
CALL: ModA.method1()
This is "mod-a" package - "main" field - "mod-a.js".
md5-c7258dc1495f30e3d59cfbc54f3e8372
This is "entry.js".
CALL: ModA.method1()
This is "mod-a" package - "module" field - "mod-a.mjs".
CALL: ModB.method1()
This is "mod-b" package - "module" field - "mod-b.mjs".
CALL: ModA.method1()
This is "mod-a" package - "main" field - "mod-a.js".
md5-24bc470c63e23ea500b6779a92ae6c99
This is "entry.js".
CALL: ModA.method1()
This is "mod-a" package - "module" field - "mod-a.mjs".
CALL: ModB.method1()
This is "mod-b" package - "module" field - "mod-b.mjs".
CALL: ModA.method1()
This is "mod-a" package - "module" field - "mod-a.mjs".
In webpack 3, that works fine. That is, the conf2 works the same as the conf3.
.mjs has a separate set of mainFields which do not include module, because of compatibility with node.js.
If you want to override the mainFields of .mjs files to need to use module.rules. I don't recommend overriding these configuration, because you loose the compatibility with node.js.
module.rules: [
{
test: /\.mjs$/,
resolve: { mainFields: [...] }
}
]
Ah, I see.
So, what is the compatibility with Node.js?
Do you mean that only the main field is referenced if the entry.js is run in Node.js before it is compiled by Webpack?
In other words, does the compiled file have no problem about compatibility even if it is run in Node.js because import statements were already removed by Webpack?
Anyway, ignoring the resolve.mainFields is an unexpected behavior.
Also, we confuse because that works fine in Webpack 3 but it doesn't work in Webpack 4.
If this is correct behavior, I think that it should be documented at least.
I guess that some problems are made by third import that differs from others, because we usually don't check a file-extension of packages. We will configure the resolve.mainFields regardless of file-extension.
I understand that the .mjs has a separate set of mainFields, but that can't be overridden by an upper level configuration like the conf2, it is unexpected.
Maybe, almost users expect the resolve: {mainFields: ['module']} make import statements load files via module field regardless of file-extension.
And also, we usually know environments that our program should run. For example, we compile apps by Webpack for web browsers.
We must consider the compatibility with Node.js only when we write a program that supports both Node.js and web browser.
This is really unexpected. I am working with .mjs for browser code, too and only found out by going through the code why importing THREE.js or dat.gui did not work as expected. While I consider the packages mentioned in webpack/webpack#6459 to be broken, I do understand that they are being accomodated. This is probably not completely solvable until some real standard concerning main fields has involved (like separate fields for non-transpiled/transpiled, ES5, ES6, ..., ESM, CJS, ...), but should at least be documented clearly.
@chenxsan We need docs this https://github.com/webpack/webpack/blob/master/lib/config/defaults.js#L992, i.e. options for resolver can be configured by dependency, i.e. you can setup different options for mjs/cjs/new URL('./file.ext', import.meta.url)/etc. I think example with different options for mjs and cjs and new URL() will be enough (because popular)
Most helpful comment
.mjshas a separate set ofmainFieldswhich do not includemodule, because of compatibility with node.js.If you want to override the
mainFieldsof.mjsfiles to need to usemodule.rules. I don't recommend overriding these configuration, because you loose the compatibility with node.js.