I’m building a Webpack project that makes use of a class exported by another Webpack project. The whole project’s structure looks something like this:
dist
| app.js // Generated by Webpack from src/app.js
src
| app.js
subproject
| dist
| | app.js // Generated by Webpack from subproject/src/app.js
| src
| | app.js
| package.json
| webpack.config.js
index.html
package.json
webpack.config.js
The superproject’s app.js
uses import Subproject from 'subproject'
to import a class exported by the subproject.
When the subproject is built using Webpack’s production
mode, this works fine. But when I switch the subproject to development
mode, the superproject no longer seems to get what it needs when importing the subproject:
Uncaught TypeError: subproject__WEBPACK_IMPORTED_MODULE_0___default() is not a constructor
Similarly, if I keep the subproject in production
, but change the superproject to production
as well, it also fails:
Uncaught TypeError: __webpack_require__.r is not a function
My main question is: Why is this happening? Any thoughts, questions, or answers you can share are helpful.
But also: Is exporting the subproject as a commonjs
module a bad idea? Is loading it in the superproject with the import
keyword a bad idea? Is this just not something development
mode supports? Is there something about my setup here that just looks wildly out of whack?
Replicating the issue
To replicate the issue, let’s try something simple:
subproject/src/app.js
exports a class with a single method returning 'foobar'
:
export default class Subproject {
test() {
return 'foobar';
}
}
src/app.js
imports the subproject and tries to use it:
import Subproject from 'subproject';
const subobj = new Subproject();
console.log( subobj.test() );
This should log foobar
to the console.
webpack.config.js
is straightforward:
const path = require('path');
const root = __dirname;
const src = path.resolve( root, 'src' );
module.exports = {
mode: 'development', // <-- THIS WORKS
// mode: 'production', // <-- THIS DOESN'T
context: src,
resolve: {
preferRelative: true,
extensions: [ '.js' ],
modules: [
path.resolve( src, 'modules' ),
'node_modules',
],
alias: {
'subproject': path.resolve( root, 'subproject' ),
},
},
entry: {
'app': 'app.js',
},
output: {
filename: '[name].js',
path: path.resolve( root, 'dist' ),
publicPath: '/dist/',
clean: true,
},
optimization: { runtimeChunk: 'single' },
};
As is subproject/webpack.config.js
:
const path = require('path');
const root = __dirname;
const src = path.resolve( root, 'src' );
module.exports = {
mode: 'production', // <-- THIS WORKS
// mode: 'development', // <-- THIS DOESN'T
context: src,
resolve: {
preferRelative: true,
extensions: [ '.js' ],
modules: [
path.resolve( src, 'modules' ),
'node_modules',
],
},
entry: { 'app': 'app.js' },
output: {
filename: '[name].js',
library: { type: 'commonjs' },
clean: true,
},
optimization: { runtimeChunk: 'single' },
};
subproject/package.json
defines main: 'dist/app.js'
.
An index.html
loads the runtime and the app:
<script src="/dist/runtime.js" charset="utf-8"></script>
<script src="/dist/app.js" charset="utf-8"></script>
You’ll need to build the subproject first, then the superproject. Finally, visit index.html
to see what you’ve wrought.