带有 es6 导入的 Module.exports 用于 typescript 中的 webpack.config.ts

Posted

技术标签:

【中文标题】带有 es6 导入的 Module.exports 用于 typescript 中的 webpack.config.ts【英文标题】:Module.exports with es6 import for webpack.config.ts in typescript 【发布时间】:2019-10-20 07:47:23 【问题描述】:

我正在使用带有 typescript 的 webpack,其配置在 typescript 中。指令here

在我的根目录下我有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;

然后我有两个项目,每个项目都有自己的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;

这一切都很好。 Here's这个工厂getConfig = () => 风格的完整示例。

我的问题是当我尝试改变来改变时

const getConfig = require("../../webpack.config.base");

到 es6 导入。这甚至是 VS 代码作为建议提供的。

当我应用此更改时,我得到

这是我的tsconfig.json 我已经启用了[allowSyntheticDefaultImports][5]。建议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"
  ]

但我还是添加了export default getConfig;……然后又添加了npm run build。它仍然失败。

const getConfigFactory = (env: any, args: any): webpack.Configuration => getConfig(appDir, distDir, env, args);
                                                                                  ^
TypeError: webpack_config_base_1.default is not a function

我在把头撞到桌子之前的最后一次尝试是改变

import getConfig from "../../webpack.config.base";
import * as base from "../../webpack.config.base";

删除webpack.config.base.ts中的export default getConfig;,将const getConfig直接导出为export const getConfig。但那时module.exports = getConfig 的意义何在。更不用说它也没有血腥的工作(和以前一样的问题)

const getConfigFactory = (env: any, args: any): webpack.Configuration => base.getConfig(appDir, distDir, env, args);
                                                                              ^
TypeError: base.getConfig is not a function

我在这里缺少什么?为什么我不能简单地将const getConfig = require("../../webpack.config.base"); 替换为import getConfig from "../../webpack.config.base"

附言。

这是我的"scripts" 用于运行它

    "build:appone": "webpack --mode=development --config ./src/AppOne.App/webpack.config.ts",
    "build:apptwo": "webpack --mode=development --config ./src/AppTwo.App/webpack.config.ts",

【问题讨论】:

【参考方案1】:

什么有效?

我用 TypeScript 为多个环境(例如 developmentproduction)配置了 webpack 和通用的基本配置。为此,我利用:

Node.js(版本11.12.0TypeScript(版本3.5.3webpack(版本4.39.1

目录结构

假设如下目录结构:

project/
├── ...
├── webpack.common.ts
├── webpack.development.ts
└── webpack.production.ts

其他目录结构(例如您的示例中的两个嵌套项目)也可以使用。不过,您可能必须调整以下示例中使用的路径。

TypeScript 配置

webpack 的基本配置webpack.common.ts 如下所示:

import webpack from 'webpack';

const configuration: webpack.Configuration = 
  // Your common webpack configuration...
;

export default configuration;

针对不同环境的两个 webpack 配置使用 npm package webpack-merge 扩展了这个基本配置。你可以在npm package @types/webpack-merge 中找到它的 TypeScript 类型。继续使用最初的示例,development 环境的 webpack 配置如下所示:

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;

同时,production 环境的 webpack 配置在 import/export 语法方面与用于development 环境的配置没有什么不同。

进口和出口

您可能已经注意到,我使用 ES6 import/export 语法:

export default configuration;

import commonWebpackConfiguration from './webpack.common';

因此,没有用于导入和导出的 CommonJS 语法(例如 module.exportsrequire),这可以保持 webpack 配置文件的清洁并允许无缝工作流。根据webpack's documentation,这实际上是使用 webpack 和 TypeScript 的推荐方式。


为什么您的配置不起作用

第一次尝试

我的问题是当我尝试改变时

const getConfig = require("../../webpack.config.base");

到 es6 导入。这甚至是 VS 代码作为建议提供的。

module.exports 确实没有默认导出(即对象module.exports 没有任何名为default 的属性),正如您观察到的错误所述。 使用 ES6 默认导出(即export default)实际上会创建一个导出named default,就像其他命名导出一样(例如下面的bar)。这可以通过编译以下 TypeScript sn-p 来说明:

const helloWorld = () => 
  console.log('Hello, world!');
;
const bar = 'foo';

export default helloWorld;
export  bar ;

javascript 使用 tsc:

"use strict";
exports.__esModule = true;
var helloWorld = function () 
    console.log('Hello, world!');
;
var bar = 'foo';
exports.bar = bar;
exports["default"] = helloWorld;

第二次尝试

但我还是添加了export default getConfig;……然后又添加了npm run build。它仍然失败。

在这种情况下,将allowSyntheticDefaultImports(你已经拥有)和esModuleInterop(你错过)添加到你的TypeScript配置tsconfig.json都设置为true可以解决这个问题1.

第三次尝试

我在把头撞到桌子之前的最后一次尝试是改变

import getConfig from "../../webpack.config.base";

import * as base from "../../webpack.config.base";

删除webpack.config.base.ts中的export default getConfig;,将const getConfig直接导出为export const getConfig。但到那时,module.exports = getConfig 的意义何在。

拥有

export const getConfig = () => ...;

module.exports = getConfig;

同时,会给你base === getConfig(因为只有module.exports = getConfig;生效)。因此,调用base.getConfig 会得到undefined,因为您定义的函数getConfig 没有属性getConfig。因此,“base.getConfig 不是函数”。

导入语法互操作性

为什么我不能简单地将const getConfig = require("../../webpack.config.base"); 替换为import getConfig from "../../webpack.config.base"

const getConfig = require("../../webpack.config.base");

是一个 CommonJS 导入,而

import getConfig from "../../webpack.config.base";

是一个 ES6 导入。它们不能互换使用,因为它们本质上是不同的。您应该选择使用其中之一,但不能同时使用两者。

【讨论】:

以上是关于带有 es6 导入的 Module.exports 用于 typescript 中的 webpack.config.ts的主要内容,如果未能解决你的问题,请参考以下文章

JS模块导入导出规范-CommonJS | ES6 -规范案例

ES6导入导出import | export | export default-使用案例

ES6导入导出import | export | export default-使用案例

module.exports---exports---export default与import---require区别和联系

module.exports exportsexport export default的区别

使用Node.js需要与ES6导入/导出