-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
Bug report
async *firstFunction() {
const { generateSummary } = await import(
/* webpackInclude: /[/]selectors[/](?!.*\.test).*\.m?js$/ */
/* webpackChunkName: "store-selectors" */
/* webpackMode: "lazy-once" */
`./selectors/${this.type}.mjs`
);
console.log(typeof generateSummary) // = "function"
}
async *secondFunction() {
const {entityActionQueue} = await import(
/* webpackInclude: /[/]selectors[/](?!.*\.test).*\.m?js$/ */
/* webpackChunkName: "store-selectors" */
/* webpackMode: "lazy-once" */
`./selectors/${this.type}.mjs`
);
console.log(entityActionQueue) // =undefined
const logFunctions = await import(
/* webpackInclude: /[/]selectors[/](?!.*\.test).*\.m?js$/ */
/* webpackChunkName: "store-selectors" */
/* webpackMode: "lazy-once" */
`./selectors/${this.type}.mjs`
);
console.log(logFunctions) // = { generateSummary: function, [randomLetter]: function } // <-- the randomLetter turns out to be the entityActionQueue function, but is mangled.
}
If I have two functions (within the same file) dynamically importing another file (also same file), but a different function for that file, I get as result that the second function name is mangled. See the code above.
However, if I import the full module and use the magic comment webpackExports, the second function name remains, as expected. See working example below:
async *firstFunction() {
const selectorModule = await import(
/* webpackInclude: /[/]selectors[/](?!.*\.test).*\.m?js$/ */
/* webpackChunkName: "store-selectors" */
/* webpackMode: "lazy-once" */
/* webpackExports: ["generateSummary", "entityActionQueue"] */
`./selectors/${this.type}.mjs`
);
console.log(typeof selectorModule.generateSummary) // = "function"
}
async *secondFunction() {
const selectorModule = await import(
/* webpackInclude: /[/]selectors[/](?!.*\.test).*\.m?js$/ */
/* webpackChunkName: "store-selectors" */
/* webpackMode: "lazy-once" */
/* webpackExports: ["generateSummary", "entityActionQueue"] */
`./selectors/${this.type}.mjs`
);
console.log(typeof selectorModule.entityActionQueue) // = "function"
}
What is the current behavior?
As described as comment in the code above, only through webpackExports the exported functions can be specified (and function correctly). I would expect webpack to recognize that multiple exports from the same file are being requested.
If the current behavior is a bug, please provide the steps to reproduce.
I wouldn't be surprised in the webpack config I'm using is needed for reproduction (I have set 'modern' settings).
import path from "node:path";
import { fileURLToPath } from "url";
import TerserPlugin from "terser-webpack-plugin";
import fs from "node:fs";
import webpack from "webpack";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const releaseDir = {
"lambda": path.resolve(__dirname, "dist/lambda"),
};
const globalConfig = {
mode: "production",
experiments: {
outputModule: true,
futureDefaults: true,
asyncWebAssembly: true,
topLevelAwait: true,
layers: true,
},
context: __dirname,
output: {
filename: 'index.js',
clean: true,
module: true,
scriptType: "module",
chunkFormat: "module",
enabledLibraryTypes: ['module'],
ignoreBrowserWarnings: true,
environment: {
module: true,
nodePrefixForCoreModules: true,
dynamicImport: true,
bigIntLiteral: true,
},
library: {
type: "module",
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': "process.env",
})
],
devtool: "source-map",
cache: {
type: "filesystem",
compression: 'gzip',
hashAlgorithm: 'sha1',
cacheDirectory: path.resolve(__dirname, './node_modules/.cache/webpack'),
},
optimization: {
checkWasmTypes: false,
removeAvailableModules: true,
usedExports: true,
minimize: false, // IMPORTANT: this is set to false, I have the issue with this setting set to both false as true.
realContentHash: true, // Should always be set in production mode, enforcing it.
minimizer: [
{
apply: (compiler) => {
new TerserPlugin({
extractComments: false,
terserOptions: {
parse: {},
compress: {
defaults: true,
passes: 4, // Adjusted
ecma: 2024, // Adjusted
module: true,// Adjusted
},
mangle: true,
module: true, // Adjusted
ecma: 2024, // Adjusted
output: null,
format: null,
toplevel: false,
nameCache: null,
ie8: false,
keep_classnames: true, // Adjusted, we like our class names
keep_fnames: false,
safari10: false,
},
}).apply(compiler);
},
},
],
},
externalsType: 'import',
externalsPresets: {
node: true
},
};
const configurations = (env) => {
return [
{
...globalConfig,
name: "lambda",
target: "node20",
entry: {
lambda: path.resolve(__dirname, "./index.mjs"),
},
cache: {
...globalConfig.cache,
memoryCacheUnaffected: true,
},
output: {
...globalConfig.output,
path: releaseDir.lambda,
filename: "[name].mjs",
},
optimization: {
...globalConfig.optimization,
runtimeChunk: "single",
moduleIds: 'deterministic', // Default in production mode, enforcing it
splitChunks: {
cacheGroups: {
// Create one chunk for all node_modules packages
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
}
}
];
}
export default configurations;
What is the expected behavior?
That with the first example code the dynamically imports are recognized by webpack and both functions are properly exported (no function name changes), in this case: { generateSummary: function, entityActionQueue: function }
Other relevant information:
webpack version: 5.94.0
Node.js version: NodeJS 20.16
Operating System: Fedora
Additional tools:
- webpack-cli: 5.1.4