web-dev-qa-db-ja.com

Angular TypeScriptライブラリでモーメントJSを使用するときのエラー

私は jvandemo/generator-angular2-library をスターターとして使用してAngular(2+)コンポーネントライブラリを構築しています。これは Rollup を使用していますモジュールビルダーとして。ライブラリで作成しているコンポーネントは MomentJS を使用します。

MomentJSを含めることで、さまざまなビルドの問題が発生しました。

最初に使用したのはimport moment from 'moment';モーメントをコンポーネントにインポートしますが、ビルド時に次のエラーが発生します。

[17:26:28] Starting 'ngc'...
Error at /Users/chris/angular-library/.tmp/components/my-library/my-component.component.ts:6:8: Module '"/Users/chris/my-library/node_modules/moment/moment"' has no default export.

私は発見しました this SO questionimport * as moment from 'moment';ただし、それによって、

'moment' is imported by build/components/my-component.component.js, but could not be resolved – treating it as an external dependency

events.js:182
      throw er; // Unhandled 'error' event
      ^
Error: Cannot call a namespace ('moment')
    at error (/Users/chris/angular-library/node_modules/rollup/dist/rollup.js:185:14)

私が知る限り、これらのオプションは2つしかなく、どちらも機能しないのですが、何が欠けていますか?

編集

この問題 を、最小限のレプリケーション手順を含むライブラリのGithubリポジトリに追加しました

16
Chris Brown

エラーは非常に明確で具体的です

エラー:エラー(/Users/chris/angular-library/node_modules/rollup/dist/rollup.js:185:14)で名前空間( 'moment')を呼び出せません

これは、ESモジュール仕様に準拠しています。

つまり、* as nsによって作成されたものなどのモジュール名前空間オブジェクトが呼び出されない可能性があるため、以下は、モーメントや呼び出すものをインポートする無効な方法です。

import * as moment from 'moment';

正しい形式は、ngcがエラーを発生させている形式です。

import moment from 'moment';

最初にこれを機能させるには、--allowSyntheticDefaultImportsフラグを指定する必要があります。

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true
  }
}

ngcがオプションを認識すると仮定すると、まだ解決できない問題があります。

上記のフラグは、合成を実行するSystemJSやWebpackなどのツールのユーザー向けであり、そのようなコードでタイプチェックを行うことができます。

TypeScript 2.7以降では、--esModuleInteropフラグを指定して、トランスパイレーションプロセスの一部として言語に合成を提供させることができます。

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

TypeScriptのバージョン2.7より前のバージョンおよびを使用している場合、CommonJS、AMD、またはUMDモジュールにコンパイルする場合(--module commonjs)正しいインポート構文はむしろ

import moment = require('moment');

import = require構文はTypeScript固有の構成要素であり、現在はほとんど不要です。これは、AMD、CommonJS、またはUMDモジュールのモジュールエクスポートのタイプの値の両方を取得するために存在します。 「and」は重要です。これは、constvar、またはlet = requireの呼び出しによって、値スペースに名前が作成されるだけで、タイプスペースには名前が作成されないためです。

31
Aluan Haddad

Angular6と現在の@ angular/cliを使用して、2018 +でこれを見つけた人は誰でも:

今日私はこれに遭遇し、- 解決策はこちら を見つけました。

import * as moment_ from 'moment';
const moment = moment_;

これで、ライブラリはコンパイルできます。

4
PeS

サンプルディレクティブでは、以下を使用したときにコンパイルに問題はありませんでした。

import { Directive, ElementRef } from '@angular/core';
import * as moment from '../node_modules/moment/moment';
@Directive({
  selector: '[sampleDirective]'
})
export class SampleDirective {

  constructor(private el: ElementRef) {
    moment.isDate('test');
  }

}

ファイルは、ルートのサブディレクトリであるビルドディレクトリからコンパイルされます。ここで言及されている「これ」についてさらに警告が表示されます。

https://github.com/rollup/rollup/issues/794

ライブラリは外部であるとgulfileで言う必要があります。

  external: [
    '@angular/core',
    '@angular/common',
    'moment'
  ],

そして、githubリンクから、onwarnブロックを両方のロールアップセクションに追加する必要があります。これは、セクション 'rollup:umd'および 'rollup:fesm'です。

onwarn: function(warning) {
    // Skip certain warnings

    // should intercept ... but doesn't in some rollup versions
    if ( warning.code === 'THIS_IS_UNDEFINED' ) { return; }

    // console.warn everything else
    console.warn( warning.message );
},

それであなたはさらに先に進みますか?

1
PeterS