I'm using webpack with typescript with the config its self in typescript. Instructions here
In my root I have webpack.config.base.ts
import webpack from "webpack";
const getConfig = ( appDir: string, distDir: string, env: any, args: any ): webpack.Configuration => {
const config: webpack.Configuration = {
entry: {
},
output: {
},
resolve: {
plugins: [
],
extensions: [".ts", ".tsx", ".js"]
},
devtool: "source-map",
module: {
rules: [
]
},
plugins: [
]
};
return config;
};
module.exports = getConfig;
I then have two projects each with their own webpack.config.ts
import webpack from "webpack";
import * as path from 'path';
const getConfig = require("../../webpack.config.base");
const appDir = __dirname;
const distDir = path.resolve(__dirname, "../AppOne.Web/wwwroot");
const getConfigFactory = (env: any, args: any): webpack.Configuration => getConfig(appDir, distDir, env, args);
module.exports = getConfigFactory;
This all works absolutely fine. Here's a full example of this factory getConfig = () => {} style.
My problem is when I try to change to change
const getConfig = require("../../webpack.config.base");
To an es6 import. This is even provided as a suggestion by VS code.

When I apply this change I get

Here's my tsconfig.json I already have [allowSyntheticDefaultImports][5] enabled. Suggested here.
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"moduleResolution": "node",
"jsx": "react",
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"target": "es5",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"typeRoots": [
"./node_modules/@types/",
"./types/"
],
"baseUrl": ".",
"paths": { }
},
"include": [
"./src/**/*.ts",
"./src/**/*.tsx"
]
}
But I added export default getConfig; anyway... and npm run build again. It still fails.
const getConfigFactory = (env: any, args: any): webpack.Configuration => getConfig(appDir, distDir, env, args);
^
TypeError: webpack_config_base_1.default is not a function
My final attempt before smashing my head into the table was to change
import getConfig from "../../webpack.config.base";
import * as base from "../../webpack.config.base";
Delete the export default getConfig; in the webpack.config.base.ts and export the const getConfig directly as export const getConfig. But at that point what's the point of module.exports = getConfig. Not to mention it also doesn't bloody work (same issue as before)
const getConfigFactory = (env: any, args: any): webpack.Configuration => base.getConfig(appDir, distDir, env, args);
^
TypeError: base.getConfig is not a function
What am I missing here? Why can't I simply replace const getConfig = require("../../webpack.config.base"); with import getConfig from "../../webpack.config.base"
PS.
Here's my "scripts" for running this
"build:appone": "webpack --mode=development --config ./src/AppOne.App/webpack.config.ts",
"build:apptwo": "webpack --mode=development --config ./src/AppTwo.App/webpack.config.ts",
I configured webpack with TypeScript for multiple environments (e.g. development and production) with a common base configuration. To do so, I utilize:
11.12.0)3.5.3)4.39.1)Suppose the following directory structure :
project/
├── ...
├── webpack.common.ts
├── webpack.development.ts
└── webpack.production.ts
Other directory structures (such as two nested projects as in your example) will work as well. Although, you may have to adapt the paths used in the examples below.
The base configuration of webpack, webpack.common.ts, looks as follows:
import webpack from 'webpack';
const configuration: webpack.Configuration = {
// Your common webpack configuration...
};
export default configuration;
The two webpack configurations for different environments extend this base configuration using the npm package webpack-merge. You can find its typings for TypeScript in the npm package @types/webpack-merge. To stick with the initial example, the webpack configuration for the development environment looks as follows:
import webpack from 'webpack';
import merge from 'webpack-merge';
import commonWebpackConfiguration from './webpack.common';
const configuration: webpack.Configuration = merge(commonWebpackConfiguration, {
mode: 'development'
// Your `development`-specific configuration...
});
export default configuration;
Meanwhile, the webpack configuration for the production environment is no different to the one used for the development environment in terms of import/export syntax.
As you may have noticed, I use the ES6 import/export syntax:
export default configuration;
and
import commonWebpackConfiguration from './webpack.common';
Consequently, there is no CommonJS syntax for imports and exports (e.g. module.exports or require) involved which keeps the webpack configuration files clean and allows for a seamless workflow. This is actually the recommended way to work with webpack and TypeScript as per webpack's documentation.
My problem is when I try to change
const getConfig = require("../../webpack.config.base");to an es6 import. This is even provided as a suggestion by VS code.
module.exports does indeed not have a default export (i.e. the object module.exports does not have any property named default) as the error you observed stated.
Using ES6 default export (i.e. export default) actually creates an export named default just like for other named exports (e.g. bar in the following). This can be illustrated compiling the following TypeScript snippet:
const helloWorld = () => {
console.log('Hello, world!');
};
const bar = 'foo';
export default helloWorld;
export { bar };
to JavaScript using tsc:
"use strict";
exports.__esModule = true;
var helloWorld = function () {
console.log('Hello, world!');
};
var bar = 'foo';
exports.bar = bar;
exports["default"] = helloWorld;
But I added
export default getConfig;anyway... andnpm run buildagain. It still fails.
In this case, adding allowSyntheticDefaultImports (which you already have) and esModuleInterop (which you miss) to your TypeScript configuration tsconfig.json both set to true would remedy that issue 1.
My final attempt before smashing my head into the table was to change
import getConfig from "../../webpack.config.base";to
import * as base from "../../webpack.config.base";Delete the
export default getConfig;in thewebpack.config.base.tsand export theconst getConfigdirectly asexport const getConfig. But at that point what's the point ofmodule.exports = getConfig.
Having
export const getConfig = () => {...};
and
module.exports = getConfig;
at the same time, will give you base === getConfig (as only module.exports = getConfig; takes effect). Consequently, calling base.getConfig gives undefined since your defined function getConfig does not have a property getConfig. Hence, "base.getConfig is not a function".
Why can't I simply replace
const getConfig = require("../../webpack.config.base");withimport getConfig from "../../webpack.config.base"?
const getConfig = require("../../webpack.config.base");
is a CommonJS import while
import getConfig from "../../webpack.config.base";
is an ES6 import. They cannot be used interchangeable since they are inherently different. You should choose to work with one of them, but not both at the same time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With