I have a completely functional library package. I upgraded from Webpack 4 to Webpack 5, and all of a sudden my external packages return an empty object. I am at a complete loss of ideas. My config was already proper, including solution from:
Why webpack returns an empty object when requiring its output?
My module now exports this alone and i still have an issue:
import React from 'react';
const uxp = require('uxp');
export const ExportAsSection = () => {
console.log("UXP TEST:")
// empty object, although doing the same from a console shows the expected global object
console.log(uxp)
// Renders no issue
return (
<div>I am a panel</div>
);
};
My relevant config is this:
const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('../../webpack.config');
const config = {
context: __dirname,
entry: './src/index.tsx',
externals: {
lodash: 'lodash',
'react-dom': 'react-dom',
react: 'react',
uxp: 'commonjs2 uxp'
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(svg)$/i,
use: [
'babel-loader',
{
loader: 'react-svg-loader',
options: {
svgo: {
plugins: [
{
convertPathData: { noSpaceAfterFlags: false },
},
{
mergePaths: false,
},
{
removeViewBox: false,
},
],
},
},
},
],
},
],
},
output: {
filename: 'example-export.umd.js',
path: path.resolve(__dirname, 'dist'),
library: '@example/export',
},
};
module.exports = merge(baseConfig, config);
The base config is this:
const webpack = require('webpack');
const path = require('path');
const git = require('git-rev-sync');
const dev = process.env.MODE === 'development' ? '-dev' : '';
const production = process.env.MODE === 'production';
const pluginRev = `${git.short()}${dev}`;
module.exports = {
entry: './src/index.ts',
mode: production ? 'production' : 'development',
devtool: production ? false : 'eval-cheap-module-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: path.resolve(__dirname, './babel.config.json'),
},
},
{
loader: 'ts-loader',
options: {
allowTsInNodeModules: true,
},
},
],
},
],
},
plugins: [
new webpack.DefinePlugin({
PLUGIN_REV: JSON.stringify(pluginRev),
}),
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
}),
],
resolve: {
extensions: ['.tsx', '.ts', '.js'],
fallback: {
buffer: require.resolve('buffer'),
},
},
output: {
libraryTarget: 'umd',
},
};
The output UMD file also has this bit that looks seemingly correct:
/***/ "uxp":
/*!**********************!*\
!*** external "uxp" ***!
\**********************/
/***/ ((module) => {
module.exports = require("uxp");
/***/ }),
Update
I also sanity checked by downgrading to Webpack 4, and was unable to reproduce issue. I then went back to Webpack 5, with my Webpack 5 configuration, and made devtool: false
so it can build again from one conflicting, breaking change, and issue returned. So definitely something about upgrading here.
Update 2
I pared down all my code to just return a div from React so the UMD compiled JS was pretty readable. My UMD package is imported into a project using Webpack 4. When the compiled code is initially imported, self.require
, window.require
, and require
all return what I expect. By the time webpack's require method is called, require
no longer returns anything (altho self.require
and window.require
do. If I try to just do console.log(require)
at that point, I also get an exception like __webpack_modules__[moduleId]
although I can't find where on earth require
would be overridden in such a way. I am wondering if require
is manipulated one way via Webpack 4 and another via Webpack 5 and the conflict is causing my issues.
The issue is around how webpack overwrites require
. Having a webpack 5 bundle within a webpack 4 app caused these issues. I switched my app to Vite specifically to work around this.