29

我正在尝试遵循 Angular 2 的官方 AoT 指南,并且在我的应用程序中使用 Moment.js。Moment.js 在我的packages.json文件中,我使用的是 2.15.0 版本。到目前为止,我一直在这样导入它:

import * as moment from 'moment';

但是当我到达必须运行汇总的部分时,我最终会遇到以下错误:

无法调用命名空间(“时刻”)

这似乎与我根据导入时刻的方式有关。那么,我该怎么做呢?我似乎无法以任何其他方式导入时刻。如果我使用

import moment from 'moment'

我得到编译错误

外部模块“时刻”没有默认导出

4

9 回答 9

22

我终于设法摆脱了这两个错误。确实要避免:

无法调用命名空间(“时刻”)

你需要使用:

import moment from 'moment'

然后避免

“时刻”没有默认导出

您必须添加到您的 tsconfig.json (compilerOptions):

"allowSyntheticDefaultImports": true

编辑 17/11/2016

我还必须将以下内容添加到我的 rollup-config.js 文件中:

plugins: [
  nodeResolve({jsnext: true, module: true}),
  commonjs({
    include: [
        'node_modules/rxjs/**',
        'node_modules/moment/**'
      ]
    }
  }),
  uglify()
]
于 2016-10-31T16:08:52.703 回答
13

我为手头的问题找到了一个很好的解决方案:

npm-install 附加包moment-es6提供默认导出。然后从 'moment-es6' 而不是从 'moment' 导入:

import moment from 'moment-es6';

  • 要与 systemjs 一起使用,请将以下内容添加到 systemjs.config.js 映射部分:
    'moment-es6': 'npm:moment-es6/index.js'

  • 添加'node_modules/moment-es6/**'include您的汇总配置 commonjs 部分 (rollup-plugin-commonjs)

于 2017-05-08T12:25:08.860 回答
7

这是我使用 typescript(2.1.6)和 rollup(0.41.4)制作工作时刻所做的。

  1. 要导入时刻,请保持标准方式:

    import * as moment from 'moment';

import moment from 'moment';对于没有默认导出的包来说是非标准的,它会在运行时导致错误:moment_1.default is not a function

  1. 在打字稿中,通过将 moment 转换为 any 来使用 moment,并调用default函数:

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

moment(value).format(format)将导致汇总树抖动错误:Cannot call a namespace ('moment')

于 2017-02-16T09:43:02.137 回答
5

我们在 ng-packagr 中遇到了类似的问题,它使用汇总生成可以在 npm 存储库中发布的模块。我们的项目是使用 @angular-cli(使用 webpack)构建的。

我们有 2 个使用 asteriks 方法导入的依赖项:

 import * as dataUrl from 'dataurl';

工作正常,使用如下:

 dataUrl.parse(url)

另一个导入给出了错误(无法调用命名空间),因为导出的对象将用作函数:

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

我们可以通过将导出的初始化函数分配给另一个 const 并在代码中使用它来解决这个问题:

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

 svgPanZoom(element);

如上所述,我们还进行了 tsconfig.json 配置更改。

版本:ng-packagr:1.4.1 汇总:0.50.0 打字稿:2.3.5 @angular/cli:1.4.8 webpack:3.7.1

希望这有帮助,

于 2017-10-23T13:40:17.437 回答
3

我遇到了上述相同的问题。

import * as moment from 'moment';- 在通过 systemjs 开发和加载时工作,但不是在汇总期间工作。

import moment from 'moment';- 在汇总构建中工作,但不是在开发期间。

为了避免必须根据构建类型更改代码,我只是将 moment 作为全局添加并创建了一个辅助函数,我在需要使用它的任何地方导入它而不是导入 moment。

这意味着相同的代码适用于两种类型的场景。虽然不是特别漂亮,如果有更好的方法请告诉我/我们!

这是辅助函数,添加到它自己的文件中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);
}

要在其他类中使用 moment,我只需导入函数并调用它,就好像我直接导入了 moment:

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

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

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

为了让 systemjs 将其作为全局加载,我只是按照这些步骤操作。 http://momentjs.com/docs/#/use-it/system-js/

就我而言,systemjs 的时刻配置如下所示:

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

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

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

对于汇总构建,您必须确保通过脚本标记将 moment.js 添加到页面的某个位置,因为不幸的是它不会包含在汇总构建文件中。

于 2016-12-09T02:05:20.060 回答
1

通过这个线程import moment from 'moment';应该工作。

于 2016-10-02T15:24:28.383 回答
0

从 2.13.0 版开始,

import * as moment from 'moment';

于 2016-09-18T08:06:27.640 回答
0

我尝试了上述所有解决方案,但没有一个对我有用。起作用的是

import moment from 'moment-with-locales-es6';
于 2018-01-04T13:37:55.540 回答
0

在我的 Angular 5 (5.2.9) 项目(从 Ng2 升级)中使用 Gulp 和 Rollup (0.58.0) 进行产品构建时,momentJs (2.24) 的使用存在同样的问题。

正如前面提到的,这里import * as moment from 'moment'; 仅适用于在包列表中引用 momentJs 的开发(通过 SystemJS):

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

其他情况是汇总使用(生产构建)-momentJs 将其代码作为 ES6 模块(在 moment/src 中),但它以不同的方式导出(然后是通常的导出)。这就是为什么import moment from 'moment';使用 Rollup 的原因

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

和 ES6 模块导入。

是的,使用 ES6 包装器(例如moment-es6左右)是简单的解决方案。但它总是需要momentJs。同时对于这个问题还有一个更简单的解决方案 - 将您的导入行从 Dev 替换为 Prod。例如,Gulp 可以gulp-replace在某个步骤使用:

return gulp.src([
     ...
    ])
    .pipe(replace('import * as moment from \'moment\';', 'import moment from \'moment\';'))
     ...;
于 2019-01-25T12:21:43.223 回答