我试图关注Angular 2的official AoT guide,并且我在我的应用程序中使用Moment.js。 Moment.js位于我的 packages.json 文件中,我使用的是版本2.15.0。到目前为止,我一直在这样导入它:
import * as moment from 'moment';
但是当我到达必须运行汇总的部分时,我最终会出现以下错误:
无法调用命名空间('时刻')
这似乎与我根据this导入时刻的方式有关。那么,我该怎么做呢? 我似乎无法以任何其他方式导入时刻。如果我使用
import moment from 'moment'
我收到编译错误
外部模块'''''没有默认导出
答案 0 :(得分:20)
我终于设法摆脱了这两个错误。确实要避免:
无法调用命名空间('时刻')
您需要使用:
import moment from 'moment'
然后避免
“时刻”没有默认导出
您必须添加到tsconfig.json(compilerOptions)中:
"allowSyntheticDefaultImports": true
编辑2016年11月17日
我还必须将以下内容添加到我的rollup-config.js文件中:
plugins: [
nodeResolve({jsnext: true, module: true}),
commonjs({
include: [
'node_modules/rxjs/**',
'node_modules/moment/**'
]
}
}),
uglify()
]
答案 1 :(得分:7)
以下是我用打字稿(2.1.6)和汇总(0.41.4)来完成工作的时间。
要导入时刻,请保持标准方式:
import * as moment from 'moment';
import moment from 'moment';
对于没有默认导出的包是非标准的,它会在运行时导致错误:moment_1.default is not a function
在打字稿中使用时刻与任意时刻一样,并调用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')
答案 2 :(得分:4)
我们在ng-packagr中遇到了类似的问题,该问题使用汇总来生成可以在npm repo中发布的模块。 我们的项目是使用@ angular-cli(使用webpack)构建的。
我们有两个使用asteriks方法导入的依赖项:
public static BufferedReader createInputStream (Socket socket) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
return br;
}
public static PrintWriter createOutputStream (Socket socket) throws IOException {
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
return pw;
}
工作正常,用作:
import * as dataUrl from 'dataurl';
另一个导入错误(无法调用命名空间),因为导出的对象将用作函数:
dataUrl.parse(url)
我们可以通过将导出的初始化函数分配给另一个const并在代码中使用它来解决此问题:
import * as svgPanZoom from 'svg-pan-zoom';
svgPanZoom(element); <== error: Cannot call a namespace
我们还如上所述更改了tsconfig.json配置。
版本: ng-packagr:1.4.1 汇总:0.50.0 打字稿:2.3.5 @ angular / cli:1.4.8 webpack:3.7.1
希望得到这个帮助,
罗布
答案 3 :(得分:3)
我遇到了上述相同的问题。
import * as moment from 'moment';
- 在通过systemjs开发和加载时工作,但在汇总时没有。
import moment from '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);
}
要在其他课程中使用片刻,我只需导入该函数并将其调用,就像我直接导入片刻一样:
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添加到页面某处,因为它不幸地不会包含在汇总构建文件中。
答案 4 :(得分:0)
自版本2.13.0起,
import * as moment from 'moment';
答案 5 :(得分:0)
经过this thread,window()
应该有效。
答案 6 :(得分:0)
我尝试了上面的所有解决方案,但没有一个对我有效。有用的是
import moment from 'moment-with-locales-es6';
答案 7 :(得分: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';
与汇总工具一起使用的原因
include: [
'node_modules/rxjs/**',
]
和ES6模块导入。
是的,使用ES6包装器(例如moment-es6
等)是简单的解决方案。但这总是需要一刻。
同时,针对此问题还有一个更简单的解决方案-将您的导入行从Dev替换为Prod。
例如,Gulp可以在某些步骤中使用gulp-replace
:
return gulp.src([
...
])
.pipe(replace('import * as moment from \'moment\';', 'import moment from \'moment\';'))
...;