web-dev-qa-db-fra.com

Utilisation de Rollup pour Angular 2's AoT compiler and importing Moment.js

J'essaie de suivre le guide AoT officiel pour Angular 2, et j'utilise Moment.js dans mon application. Moment.js est sur mon packages.json , et j'utilise la version 2.15.0. Je l'ai importée comme ceci jusqu'à présent:

import * as moment from 'moment';

Mais quand j'arrive à la partie où je dois exécuter le rollup, je me retrouve avec l'erreur suivante:

Impossible d'appeler un espace de noms ('moment')

Ce qui semble être lié à la façon dont j'importe le moment selon this . Alors, comment suis-je censé faire ça? Je n'arrive pas à importer le moment d'une autre manière. Si j'utilise

import moment from 'moment'

J'obtiens l'erreur de compilation

Le module externe '' moment '' n'a pas d'exportation par défaut

29
Vitor Machado

J'ai finalement réussi à me débarrasser des deux erreurs. En effet pour éviter:

Impossible d'appeler un espace de noms ('moment')

Vous devez utiliser:

import moment from 'moment'

Alors pour éviter

"moment" n'a pas d'export par défaut

Vous devez ajouter dans votre tsconfig.json (compilerOptions):

"allowSyntheticDefaultImports": true

MODIFIER 17/11/2016

J'ai également dû ajouter ce qui suit à mon fichier rollup-config.js:

plugins: [
  nodeResolve({jsnext: true, module: true}),
  commonjs({
    include: [
        'node_modules/rxjs/**',
        'node_modules/moment/**'
      ]
    }
  }),
  uglify()
]
22
j3r6me

J'ai trouvé une bonne solution pour le problème actuel:

Npm-install additional package moment-es6 qui fournit une exportation par défaut. Importez ensuite depuis 'moment-es6' au lieu de 'moment':

import moment from 'moment-es6';

  • Pour une utilisation avec systemjs, ajoutez ce qui suit à la section de carte systemjs.config.js:
    'moment-es6': 'npm:moment-es6/index.js'

  • ajouter 'node_modules/moment-es6/**' aux include de la section commonjs de votre rollup configs (rollup-plugin-commonjs)

13
akaegi

Voici ce que j'ai fait pour faire fonctionner le moment avec TypeScript (au 2.1.6) et le cumul (0.41.4).

  1. Pour importer un moment, conservez la méthode standard:

    import * as moment from 'moment';

import moment from 'moment'; N'est pas standard pour un package sans exportation par défaut, il en résultera une erreur lors de l'exécution: moment_1.default is not a function

  1. Dans TypeScript, utilisez moment avec en convertissant moment comme n'importe quel, et appelez la fonction default:

    var momentFunc = (moment as any).default ? (moment as any).default : moment;
    var newFormat = momentFunc(value).format( format );
    

moment(value).format(format) entraînera une erreur lors de l'agitation de l'arborescence de cumul: Cannot call a namespace ('moment')

7
Anthony Brenelière

Nous avons eu un problème similaire avec ng-packagr qui utilise le cumul pour générer un module qui peut être publié dans un référentiel npm. Notre projet a été construit en utilisant @ angular-cli (en utilisant webpack).

Nous avons 2 dépendances qui sont importées à l'aide de la méthode asteriks:

 import * as dataUrl from 'dataurl';

Fonctionne bien, est utilisé comme:

 dataUrl.parse(url)

Une autre importation a donné l'erreur (impossible d'appeler un espace de noms) car l'objet exporté doit être utilisé en tant que fonction:

 import * as svgPanZoom from 'svg-pan-zoom';
 svgPanZoom(element); <== error: Cannot call a namespace

Nous pourrions contourner cela en affectant la fonction d'initialisation exportée à un autre const et l'utiliser dans le code:

 import * as svgPanZoomImport from 'svg-pan-zoom';
 const svgPanZoom = svgPanZoomImport;

 svgPanZoom(element);

Nous avons également effectué le changement de configuration tsconfig.json comme décrit ci-dessus.

Versions: ng-packagr: 1.4.1 cumul: 0.50.0 TypeScript: 2.3.5 @ angular/cli: 1.4.8 webpack: 3.7.1

J'espère que cette aide,

Rob

4
Rob Gansevles

J'avais les mêmes problèmes que ceux décrits ci-dessus.

import * as moment from 'moment'; - a fonctionné lors du développement et du chargement via systemjs, mais pas lors du rollup.

import moment from 'moment'; - a fonctionné dans une compilation cumulative mais pas pendant le développement.

Pour éviter d'avoir à modifier le code en fonction du type de build, j'ai simplement ajouté moment en tant que global et créé une fonction d'aide que j'importe où je dois l'utiliser au lieu d'importer moment.

Cela signifie que le même code fonctionne pour les deux types de scénarios. Ce n'est pas particulièrement joli cependant, s'il y a une meilleure façon s'il vous plaît laissez-moi/nous savoir!

Voici la fonction d'assistance, ajoutée à son propre fichier momentLoader.ts

import { default as mom } from 'moment';
export default function moment(args?: any): mom.Moment {
    let m = window["moment"];
    if (!m) { 
        console.error("moment does not exist globally.");
        return undefined;
    }
    return m(args);
}

Pour utiliser moment dans d'autres classes, j'importe simplement la fonction et je l'appelle comme si j'avais importé directement moment:

import moment from '../../momentLoader';

let d = moment().utc("1995-12-25");

let m = moment("1995-12-25");

Pour que systemjs le charge en tant que global, je viens de suivre ces étapes. http://momentjs.com/docs/#/use-it/system-js/

Dans mon cas, la configuration actuelle de systemjs ressemble à ceci:

let meta = {
    'lib:moment/moment.js': { format: 'global' }
};

System.config({
    paths: paths,
    map: map,
    packages: packages,
    meta: meta
});

System.import('lib:moment/moment.js');

Pour la compilation cumulative, vous devrez vous assurer que moment.js est ajouté quelque part à la page via une balise de script, car il ne sera malheureusement pas inclus dans le fichier de compilation cumulative.

3
Nick Cameron

En passant ce fil , import moment from 'moment'; devrait marcher.

0
Tycho

J'ai essayé toutes les solutions ci-dessus, mais aucune n'a fonctionné pour moi. Ce qui a fonctionné

import moment from 'moment-with-locales-es6';
0
Adrian Ber

J'ai eu le même problème avec l'utilisation de momentJs (2.24) dans mon projet Angular 5 (5.2.9) (mis à niveau à partir de Ng2) avec Gulp et Rollup (0.58.0) pour la génération de prod.

Comme les gars l'ont mentionné plus tôt ici import * as moment from 'moment'; ne fonctionne que pour le développement (via SystemJS) avec des moments référents dans la liste des packages:

{
  name: 'moment',
  path: 'node_modules/moment/min/moment.min.js'
}

L'autre cas est l'utilisation de Rollup (Production build) - momentJs a son code comme module ES6 (en moment/src), mais il exporte de manière différente (puis exportation habituelle). C'est pourquoi import moment from 'moment'; fonctionne avec Rollup's

include: [
  'node_modules/rxjs/**',
]

et importation de modules ES6.

Oui, pour utiliser l'encapsuleur ES6 (tel que moment-es6 ou plus) est une solution simple. Mais cela nécessite toujours des moments. En même temps, il existe une solution plus simple à ce problème: remplacez votre ligne d'importation de Dev vers Prod. Par exemple, Gulp peut utiliser gulp-replace à un moment donné:

return gulp.src([
     ...
    ])
    .pipe(replace('import * as moment from \'moment\';', 'import moment from \'moment\';'))
     ...;
0
PIoneer_2

Depuis la version 2.13.0,

import * as moment from 'moment';

0
Zubair Lawrence