fhiegel
fhiegel

Reputation: 741

Webpack 5 : how to import assets as ES6 module?

I am using Webpack 5.20.1, with Asset Modules feature.

When I import my assets, I got an "undefined" instead of the URL of the expected resource.

webpack.config.js

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.(gif|png|jpe?g|svg|xml|json)$/i,
        type: 'asset/resource'
      }
    ]
  },
  ...

MyFile.ts

import * as Phaser from 'phaser';

import sky from '../assets/sky.png';

export class GameScene extends Phaser.Scene {

  public preload() {
    console.log("##### sky", sky); // got undefined
    this.load.image('sky', sky);
  }

}

I thought this use was legit.

Exploring transpiled bundle, I find an use of the path to default, when then asset is use. But no default in the export when the asset is build as module :

app.bundle.js (when using the asset)

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.GameScene = void 0;
var Phaser = __webpack_require__(/*! phaser */ "./node_modules/phaser/dist/phaser.js");
var sky_png_1 = __webpack_require__(/*! ../assets/sky.png */ "./src/assets/sky.png");
var GameScene = /** @class */ (function (_super) {
    __extends(GameScene , _super);
    function GameScene () {
        var _this = _super.call(this, sceneConfig) || this;
        _this.score = 0;
        return _this;
    }
    GargoylesScene.prototype.preload = function () {
        console.log("##### sky", sky_png_1.default); // There is 'default' keyword
        this.load.image('sky', sky_png_1.default); // There is 'default' keyword
    };

    return GameScene;
}(Phaser.Scene));
exports.GameScene = GameScene;

app.bundle.js (when defined asset as module)

/***/ "./src/assets/sky.png":
/*!****************************!*\
  !*** ./src/assets/sky.png ***!
  \****************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";
module.exports = __webpack_require__.p + "assets/47a86b192804f1490bee.png"; // There is NO 'default' keyword

/***/ }),

Where did I go wrong ?

How can I configure webpack to load my resources as expected?

Upvotes: 2

Views: 2231

Answers (2)

Ava Li
Ava Li

Reputation: 21

I know this has been a year ago, but in case anyone else is having this problem.

To solve this, you have to change how TS will compile imports by setting esModuleInterop to true. From the docs, you can also get by with just setting allowSyntheticDefaultImports to true, since esModuleInterop turns that to true under the hood.

Sample

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "CommonJS",
    "target": "es6",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "baseUrl": "./frontend/src",
    "strict": true
  },
  "include": ["./frontend/src", "./tests"]
}

Upvotes: 1

fhiegel
fhiegel

Reputation: 741

Found a workaround : use the * when importing assets.

MyFile.ts

import * as Phaser from 'phaser';

import * as sky from '../assets/sky.png'; // use `* as`

export class GameScene extends Phaser.Scene {

  public preload() {
    console.log("##### sky", sky); // got undefined
    this.load.image('sky', sky);
  }

}

will be transpiled into

app.bundle.js (when using the asset)

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.GameScene = void 0;
var Phaser = __webpack_require__(/*! phaser */ "./node_modules/phaser/dist/phaser.js");
var sky = __webpack_require__(/*! ../assets/sky.png */ "./src/assets/sky.png");
var GameScene = /** @class */ (function (_super) {
    __extends(GameScene , _super);
    function GameScene () {
        var _this = _super.call(this, sceneConfig) || this;
        _this.score = 0;
        return _this;
    }
    GargoylesScene.prototype.preload = function () {
        console.log("##### sky", sky);
        this.load.image('sky', sky);
    };
    
    return GameScene;
}(Phaser.Scene));
exports.GameScene = GameScene;

Upvotes: 3

Related Questions