WARNING: No name was provided for external module 'X' in output.globals – guessing 'X'
Asked Answered
H

1

21
WARNING: No name was provided for external module 'moment' in output.globals – guessing 'momentImported'
WARNING: No name was provided for external module 'odata-parser' in output.globals – guessing 'parser'

I receive this message when I try to bundle my library to Universal Module Definition. The warning can be fixed by adding umdModuleIds in ng-package.json.

The documentation gives us the following explanation:

When writing the UMD bundle, ng-packagr does its best to provide common default values for the UMD module identifiers. Also, rollup will do its best to guess the module ID of an external dependency. Even then, you should make sure that the UMD module identifiers of the external dependencies are correct. In case ng-packagr doesn't provide a default and rollup is unable to guess the correct identifier, you should explicitly provide the module identifier by using umdModuleIds in the library's package file section like so: ...

umdModuleIds:

A map of external dependencies and their correspondent UMD module identifiers. Map keys are TypeScript / EcmaScript module identifiers. Map values are UMD module ids. The purpose of this map is to correctly bundle an UMD module file (with rollup). By default, rxjs, tslib and @angular/* dependency symbols are supported.

How can I find or check for correctness the UMD ID of moment, odata-parser or any other module that must be added to the umdModuleIds?

Hymie answered 24/4, 2020 at 6:56 Comment(0)
T
30

I found the docs hard to understand, too. The ng-packagr umdModuleIds setting in ng-package.json is a mapping of import names to module IDs that UMD registers in the javascript global object.

By import name I mean, in your typescript code:

import * as moment from 'moment';

The string moment should be the key under umdModuleIds.

The value should match up with the global variable registered in the UMD bundle for the package. If you take a look in the JS file you're importing, you'll see the global.X value being set. For moment.js the code block is:

//! moment.js

;(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    global.moment = factory()
}(this, (function () { 'use strict';

The line global.moment = ... gives you what you need. So, to import moment correctly, your ng-package.json should include:

  "lib": {
    "entryFile": "src/public-api.ts",
    "umdModuleIds": {
      "moment": "moment"
    }
  }

In this case, it turns out that ng-packagr's guess is correct - the import name matches the UMD global variable, but you need to specify it explicitly for ng-packagr to know for sure.

There should be another (and better) way that you can fix this for NPM dependencies, which is to add the library dependencies to the library package.json file (the package.json in the same dir as the ng-package.json file). I would try that first - I believe ng-packagr correctly finds the UMD module ids when the dependency is included in the package.json.

However, in the case that you're using local libraries (libraries in the same angular workspace), or libraries which otherwise can't be analyzed by ng-packagr, it's necessary to look at the UMD ids and make sure they match up. For example, if you're using scoped/namespaced names for your internal libs, like @mycompany/util, you'll see that the UMD module IDs are registered like this:

File: ~/dist/util/bundles/mycompany-util.umd.js

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define('@mycompany/util', ['exports'], factory) :
    (global = global || self, factory((global.mycompany = global.mycompany || {}, global.mycompany.util = {})));
}(this, (function (exports) { 'use strict';

so given the line global.mycompany.util = you'll need to specify UMD module IDs like:

    "umdModuleIds": {
      "@mycompany/util": "mycompany.util"
      ...
    }
Toxemia answered 26/4, 2020 at 14:21 Comment(8)
Thank you for this. Could you cover the case in which one has @mycompany/product-name/ui-module-name as I've tried "@mycompany/product-name/ui-module-name": "mycompany['product-name']['ui-module-name'] to no avail, with the warning being No name was provided for external module '@mycompany/product-name/ui-module-name' in output.globals – guessing 'uiModuleName'Maria
Did you try looking at the first few lines of the @mycompany/product-name/ui-module-name umd.js file? You just need to match that in the dependee library's ng-package.json.Toxemia
I did, but unfortunately it was as I posted "mycompany['product-name']['ui-module-name']"Maria
That's equivalent to mycompany.product-name.ui-module-name - try that.Toxemia
Unfortunately no good either. It guesses uiModuleName but nothing I've tried has worked as yetMaria
Perhaps there's something missing in a tsconfig.json fileMaria
Updating angular to the v13 removed automatically umdModuleIds so I do think we shouldn't use it anymoreCairngorm
I agree @RaphaëlBalet - Angular 13 and up no longer build UMD output in Angular Package Format (angular.io/guide/angular-package-format), so this question and answer are irrelevant for ng 13+. However it's still relevant for older code.Toxemia

© 2022 - 2024 — McMap. All rights reserved.