将 Rollup 用于 Angular 2 的 AoT 编译器并导入 Moment.js
Using Rollup for Angular 2's AoT compiler and importing Moment.js
我正在尝试遵循 Angular 2 的 official AoT guide,并且我在我的应用程序中使用了 Moment.js。 Moment.js 在我的 packages.json 文件中,我使用的是 2.15.0 版。到目前为止,我一直是这样导入的:
import * as moment from 'moment';
但是当我到达必须 运行 汇总的部分时,我最终遇到以下错误:
Cannot call a namespace ('moment')
这似乎与我根据 this 导入时刻的方式有关。那么,我该怎么做呢?
我似乎无法以任何其他方式导入时刻。如果我使用
import moment from 'moment'
我收到编译错误
External module ''moment'' has no default export
从版本 2.13.0 开始,
import * as moment from 'moment';
按照 this thread、import moment from 'moment';
应该可行。
我终于设法摆脱了这两个错误。确实要避免:
Cannot call a namespace ('moment')
您需要使用:
import moment from 'moment'
那就避免
"moment" has no default export
你必须添加到你的 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()
]
我遇到了与上述相同的问题。
import * as moment from 'moment';
- 在通过 systemjs 开发和加载时有效,但在汇总期间无效。
import moment from 'moment';
- 在汇总构建中工作但在开发期间不工作。
为了避免必须根据构建类型更改代码,我只是将 moment 添加为全局变量并创建了一个辅助函数,我在需要使用它的任何地方导入它而不是导入 moment。
这意味着相同的代码适用于两种类型的场景。虽然不是特别漂亮,如果有更好的方法请让me/us知道!
这是辅助函数,已添加到它自己的文件中 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 添加到页面的某处,因为不幸的是它不会包含在汇总构建文件中。
这是我使用打字稿(2.1.6)和汇总(0.41.4)制作工作时刻的方法。
要导入时刻,保持标准方式:
import * as moment from 'moment';
import moment from 'moment';
是 non-standard 对于没有默认导出的包,它会在运行时导致错误:moment_1.default is not a function
在 typescript 中使用 moment with by cast moment as any,并调用 default
函数:
var momentFunc = (moment as any).default ? (moment as any).default : moment;
var newFormat = momentFunc(value).format( format );
moment(value).format(format)
会导致 rollup tree shaking 出错:Cannot call a namespace ('moment')
我找到了解决手头问题的好方法:
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/**'
添加到汇总配置 commonjs 部分 (rollup-plugin-commonjs) 的 include
我们在 ng-packagr 中遇到了类似的问题,它使用 rollup 生成可以在 npm 存储库中发布的模块。
我们的项目是使用@angular-cli(使用 webpack)构建的。
我们有 2 个使用星号方法导入的依赖项:
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
网络包:3.7.1
希望对您有所帮助,
罗布
我尝试了以上所有解决方案,但 none 对我有用。有效的是
import moment from 'moment-with-locales-es6';
在我的 Angular 5 (5.2.9) 项目(从 Ng2 升级)中使用 momentJs (2.24) 时遇到同样的问题,使用 Gulp 和 Rollup (0.58.0) 用于产品构建。
正如前面提到的那些人import * as moment from 'moment';
仅适用于在包列表中引用 momentJs 的开发(通过 SystemJS):
{
name: 'moment',
path: 'node_modules/moment/min/moment.min.js'
}
其他情况是 Rollup 用法(生产构建)——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\';'))
...;
我正在尝试遵循 Angular 2 的 official AoT guide,并且我在我的应用程序中使用了 Moment.js。 Moment.js 在我的 packages.json 文件中,我使用的是 2.15.0 版。到目前为止,我一直是这样导入的:
import * as moment from 'moment';
但是当我到达必须 运行 汇总的部分时,我最终遇到以下错误:
Cannot call a namespace ('moment')
这似乎与我根据 this 导入时刻的方式有关。那么,我该怎么做呢? 我似乎无法以任何其他方式导入时刻。如果我使用
import moment from 'moment'
我收到编译错误
External module ''moment'' has no default export
从版本 2.13.0 开始,
import * as moment from 'moment';
按照 this thread、import moment from 'moment';
应该可行。
我终于设法摆脱了这两个错误。确实要避免:
Cannot call a namespace ('moment')
您需要使用:
import moment from 'moment'
那就避免
"moment" has no default export
你必须添加到你的 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()
]
我遇到了与上述相同的问题。
import * as moment from 'moment';
- 在通过 systemjs 开发和加载时有效,但在汇总期间无效。
import moment from 'moment';
- 在汇总构建中工作但在开发期间不工作。
为了避免必须根据构建类型更改代码,我只是将 moment 添加为全局变量并创建了一个辅助函数,我在需要使用它的任何地方导入它而不是导入 moment。
这意味着相同的代码适用于两种类型的场景。虽然不是特别漂亮,如果有更好的方法请让me/us知道!
这是辅助函数,已添加到它自己的文件中 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 添加到页面的某处,因为不幸的是它不会包含在汇总构建文件中。
这是我使用打字稿(2.1.6)和汇总(0.41.4)制作工作时刻的方法。
要导入时刻,保持标准方式:
import * as moment from 'moment';
import moment from 'moment';
是 non-standard 对于没有默认导出的包,它会在运行时导致错误:moment_1.default is not a function
在 typescript 中使用 moment with by cast moment as any,并调用
default
函数:var momentFunc = (moment as any).default ? (moment as any).default : moment; var newFormat = momentFunc(value).format( format );
moment(value).format(format)
会导致 rollup tree shaking 出错:Cannot call a namespace ('moment')
我找到了解决手头问题的好方法:
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/**'
添加到汇总配置 commonjs 部分 (rollup-plugin-commonjs) 的include
我们在 ng-packagr 中遇到了类似的问题,它使用 rollup 生成可以在 npm 存储库中发布的模块。 我们的项目是使用@angular-cli(使用 webpack)构建的。
我们有 2 个使用星号方法导入的依赖项:
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 网络包:3.7.1
希望对您有所帮助,
罗布
我尝试了以上所有解决方案,但 none 对我有用。有效的是
import moment from 'moment-with-locales-es6';
在我的 Angular 5 (5.2.9) 项目(从 Ng2 升级)中使用 momentJs (2.24) 时遇到同样的问题,使用 Gulp 和 Rollup (0.58.0) 用于产品构建。
正如前面提到的那些人import * as moment from 'moment';
仅适用于在包列表中引用 momentJs 的开发(通过 SystemJS):
{
name: 'moment',
path: 'node_modules/moment/min/moment.min.js'
}
其他情况是 Rollup 用法(生产构建)——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\';'))
...;