简体   繁体   中英

Using noty in Aurelia/Typescript application

I have been trying to use NOTY with an Aurelia/Typescript application. Installed the package using NPM and use requireJS to pull it into the application.

No matter what I try, I have not been able to get it to work. For importing it in the file I need the reference for, I tried the following two methods


Attempt# 1

import * as Noty from 'noty';

This seems to create the right references and I can see that in code. When I try to use it, I do not get any build errors and everything seems ok.

在此处输入图片说明

But when I run this code, I get an error that states - "Noty is not a constructor"


Attempt 2

import Noty from 'noty'

在此处输入图片说明

This approach complains about no default exported members.

Another variation that I tried is import { Noty } from 'noty'; This gave me a similar response

在此处输入图片说明


Not sure what I am missing but any suggestions to implement this is highly appreciated. TIA


UPDATE#1

Added in aurelia.json file在此处输入图片说明

Noty package not loaded 在此处输入图片说明

PS: Added link to NOTY if having a look at the index.d.ts file is needed.

It sounds like your package mapping for requireJS is pointing to the wrong file (possibly the index.d.ts file).

I just looked at the 'noty' NPM package, looks like your mapping for requireJS should be something like:

{ "name": "noty", "path": "../node_modules/noty/lib", "main": "noty.min" }

TypeScript cares about *.d.ts files, but requireJS isn't TypeScript, it handles loading files into the browser, so it only cares about Javascript files.

BTW you are forgiven for not immediately grokking the madness that is the web platform.

The noty lib has a named AMD define define('Noty',...) instead of normal anonymous define. It should work, but it seems my recent PR created a regression for cli-bundler on named AMD module, or maybe a new bug on named AMD module.

I will fix that regression. Update I did https://github.com/aurelia/cli/pull/1084

To work around now,

  1. create another file in your project patch/noty.js with content:
define('noty',['Noty'],function(m){return m;});

This patch creates alias from 'noty' to 'Noty'.

  1. add to aurelia.json prepend, has to be after requirejs .
  2. there is another problem with default main lib/noty.js :
ERROR [Bundle] Error: An error occurred while trying to read the map file at /Users/huocp/playground/nt/node_modules/noty/lib/es6-promise.map

It tries to load es6-promise.map but no such file.

Update: the error would not stop bundling.

{
    "name": "vendor-bundle.js",
    "prepend": [
      "node_modules/requirejs/require.js",
// add this line after requirejs
      "patch/noty.js"
    ],
    "dependencies": [
      "aurelia-bootstrapper",
      "aurelia-loader-default",
      "aurelia-pal-browser",
      {
        "name": "aurelia-testing",
        "env": "dev"
      },
      "text",
// optionally override noty main path, only if you want to get rid of the annoying es6-promise.map error
      {
        "name": "noty",
        "path": "../node_modules/noty",
        "main": "lib/noty.min"
      }

    ]
}

Then this import works, I tested.

import * as Noty from 'noty';

BTW, to forget about * as , use Microsoft recommended esModuleInterop compiler option. https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html

The issue you got probably comes from the way NOTY exports their main functionality, which i guess was done in commonjs way:

module.exports = NOTY;

To import it correctly in your code, you should use the import module syntax:

import * as NOTY from 'noty';

It's the same for many other libraries that still keep the export style of the traditional way.

Update:

Based on their type definition export: https://github.com/needim/noty/blob/master/index.d.ts#L2

declare module 'noty' {
  exports = Noty;
}

This means you should always do like your attempt 1. But this is how it is actually shipped https://github.com/needim/noty/blob/master/lib/noty.js#L9-L18

(function webpackUniversalModuleDefinition(root, factory) {
  if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if(typeof define === 'function' && define.amd)
    ...
  else if(typeof exports === 'object')
    exports["Noty"] = factory();
...

Note the last part exports["Noty"] = factory() . I suspect this is what picked up, not the first one. Which means it equals to named export Noty

So it's probably the mismatch between that export thing that caused you issue. I would suggest you do this:

import * as $NOTY from 'noty';

// wrong: const NOTY = $NOTY as any as typeof $NOTY;
// wrong: const NOTY = $NOTY.Noty as any as typeof $NOTY;
// or 
// wrong: const NOTY = new (options: $NOTY.OptionsOrSomeThing): $NOTY;
const NOTY = ($NOTY as any).Noty as new (options: $NOTY.OptionsOrSomeThing): $NOTY;

// do your code here with NOTY
new NOTY();

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM