使用Typescript和Webpack的Fabric.js:Canvas不是构造函数

col*_*elz 5 javascript babel fabricjs typescript webpack

我正在尝试将Fabric.js与Typescript和Webpack一起使用在Laravel 5.4应用程序中的一些其他模块,这些模块在浏览器中运行良好.@ types/fabric ist已安装且Typescript行为正确.打字稿和Webpack的新手我尝试了一些变种没有成功.

问题

result.js:198 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_fabric___default.a.Canvas is not a constructor
Run Code Online (Sandbox Code Playgroud)

变式A.

code.ts

import fabric from "fabric";
const canvas = new fabric.Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__default.a.Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

WEBPACK_IMPORTED_MODULE_1_fabric__default需要WEBPACK_IMPORTED_MODULE_1_fabric,这是一个以fabric作为键的对象.

const canvas = new fabric.fabric.Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

将适用于Webpack但不符合类型检查.

变体B

code.ts

import * as fabric from "fabric";
const canvas = new fabric.Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__["Canvas"]('my-canvas');
Run Code Online (Sandbox Code Playgroud)

WEBPACK_IMPORTED_MODULE_1_fabric包含一个带有fabric作为键的对象,因此情况与变体A类似.

变体C.

code.ts

import {Canvas} from "fabric";
const canvas = new Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

result.js

var canvas = new __WEBPACK_IMPORTED_MODULE_1_fabric__["Canvas"]('my-canvas');
Run Code Online (Sandbox Code Playgroud)

最后它与变体B相同.

webpack.mix.js的摘录

   .webpackConfig({
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                include: [
                    path.resolve('app/public/js'),
                    path.resolve('node_modules/countable')
                ],
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                exclude: [
                    path.resolve('resources/assets/ts/components')
                ],
                options: {
                    loaders: {
                        'scss': 'vue-style-loader!css-loader!sass-loader',
                        'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
                    }
                }
            },
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                exclude: /node_modules/,
                options: {
                    appendTsSuffixTo: [/\.vue$/],
                }
            },
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            '_': 'lodash',
            '$': 'jquery',
            'jQuery': 'jquery',
            'window.jQuery': 'jquery', 
        }),
        new LiveReloadPlugin()
    ],
    resolve: {
        extensions: ['.js', '.ts', '.vue', '.jsx', '.tsx', '.vuex'],
        alias: {
            'vue$': 'vue/dist/vue.esm.js',
        }
    }
Run Code Online (Sandbox Code Playgroud)

问题似乎是在Webpack中和/或babel-loader没有考虑结构名称空间.

所以问题是,是否有任何方法告诉Webpack以直接引用结构(或这种类型的导入库)的方式处理此导入,或者以Webpack很满意的方式将其导入到Typescript中?

col*_*elz 2

解决方案在于 webpack.mix.js 的配置。必须为fabric添加exports-loader来解决这个问题。添加了以下规则:

            rules: [
            ...
            {
                test: /fabric(\.min)?\.js$/,
                use: 'exports-loader?fabric',
            },
        ]
Run Code Online (Sandbox Code Playgroud)

和布料可以像变体a一样使用:

        import fabric from "fabric";
        const canvas = new fabric.Canvas('my-canvas');
Run Code Online (Sandbox Code Playgroud)

确保已安装导出加载程序。我在这里找到提示:https ://github.com/OfficeDev/office-ui-fabric-js/issues/258