I'm setting up a project (typescript, webpack) with a couple of js libraries, configured as externals in webpack. They should not be part of the bundle, instead provided by script tags within the html.
But when trying to use them in my class, they resolve to undefined.
An error occurs when trying to set up the fabric js library as an external within a (typescript + webpack ) project. Fabric should not be bundled in the output file since it will be the responsibility of the consumer to provide (eg. through a browser script tag).
Note: jQuery initially had an issue (as an external) but is now resolved, and works as expected. Fabric on the other hand does not.
fabric has been configured as an external so that it will not be included in the webpack bundle.
Here's how...
...
externals: {
jquery: 'jQuery',
fabric: 'fabric',
},
...
npm install @types/jquery -D
npm install @types/fabric -D
<script src="js/lib/jquery.min.js"></script>
<script src="js/lib/fabric.min.js"></script>
import { fabric } from "fabric";
import $ from 'jquery';
fabric resolves to undefined within the class App.ts with the error:
TypeError: Cannot read property 'Canvas' of undefined
Please don't recommend ProvidePlugin or installing Babel.
More about webpack "externals": https://webpack.js.org/configuration/externals/
jQuery is now working as an external library. I was not referencing the actual jquery global "jQuery" in the externals setup. I had "JQuery" (with a capital J). That's now resolved and jquery is working. Thanks @Aluan
Fabric on the other hand seems to be a different issue altogether.
What you're looking for is called shimming
. Webpack docs cover this extensively here: https://webpack.js.org/guides/shimming/
Edit to add example:
In your webpack.config.js
plugins
array:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
EDIT: I pulled down your code and got it working. Here are the steps:
ts-loader
chokes on shims, so use babel's @babel/preset-typescript
-- otherwise you'll need to find a way to tell the ts compiler to ignore them. This will get you started:npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-typescript core-js@3
.babelrc
and add the following:{
"presets": [
"@babel/preset-typescript",
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3"
}
]
]
}
webpack.config.js
: plugins: [
new ProvidePlugin({
$: "jquery",
jQuery: "jquery",
fabric: "fabric"
})
]
Also update ts-loader
, changing it to babel-loader
.
Now in your code, you'll need to prefix your shimmed libraries with window
:
constructor(private readonly selector: string, canvasHeight: number, canvasWidth: number) {
window.$(`#${selector}`).replaceWith(`<canvas id="${selector}" height=${canvasHeight} width=${canvasWidth}> </canvas>`);
this.canvas = new window.fabric.Canvas(`${selector}`, { selection: false });
}
It turns out that the issue with fabric is from fabric itself! The reason fabric is resolving to undefined (when being configured as an external on webpack) is related to the way that fabric exposes its library for consumption. It's an issue they need to fix.
I've added an issue on the official fabric github page
But there is a quick solution for us. Just import using CommonJS like this:
const fabric = require('fabric');
Now it works!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.