Использование Rollup для Angular 2 компилятора AoT и импорта Moment.js
Я пытаюсь следовать официальному руководству AoT для Angular 2, и я использую Moment.js в своем приложении. Moment.js находится в моем файле packages.json, и я использую версию 2.15.0. Я импортировал его так:
import * as moment from 'moment';
Но когда я добираюсь до той части, где мне нужно запустить rollup, я получаю следующую ошибку:
Невозможно вызвать пространство имен ( "момент" )
Как представляется, это связано с тем, как я импортирую момент в соответствии с этим. Итак, как я должен это делать?
Кажется, я не могу импортировать момент другим способом. Если я использую
import moment from 'moment'
Я получаю ошибку компиляции
Внешний модуль '' moment '' не имеет экспорта по умолчанию
Ответы
Ответ 1
Мне наконец удалось избавиться от обеих ошибок. Чтобы избежать:
Невозможно вызвать пространство имен ( "момент" )
Вам нужно использовать:
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()
]
Ответ 2
Я нашел хорошее решение проблемы:
Npm-install дополнительный пакет moment-es6, который предоставляет экспорт по умолчанию.
Затем импортируйте из "момента-es6" вместо "момента":
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)
Ответ 3
Вот что я сделал, чтобы сделать рабочий момент с typescript (на 2.1.6) и свернуть (0.41.4).
import moment from 'moment';
является нестандартным для пакета без экспорта по умолчанию, это приведет к ошибке во время выполнения: moment_1.default is not a function
-
В typescript используйте момент с помощью момента каста как любой и вызовите функцию 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')
Ответ 4
У меня были те же проблемы, которые были описаны выше.
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");
Чтобы система загружала ее как глобальную, я просто выполнил следующие шаги.
http://momentjs.com/docs/#/use-it/system-js/
В моем случае момент config для 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');
Для сборки накопителя вам нужно будет убедиться, что момент .js добавлен на страницу где-то через тег script, так как он не будет включен в файл сборки накопительного файла к сожалению.
Ответ 5
У нас была аналогичная проблема с ng-packagr, которая использует rollup для создания модуля, который может быть опубликован в 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
Мы могли бы обойти это, назначив экспортированную функцию инициализации другому константе и используем ее в коде:
import * as svgPanZoomImport from 'svg-pan-zoom';
const svgPanZoom = svgPanZoomImport;
svgPanZoom(element);
Мы также изменили конфигурацию tsconfig.json, как описано выше.
Версия: ng-packagr: 1.4.1 свертывание: 0.50.0 typescript: 2.3.5 @angular/cli: 1.4.8 webpack: 3.7.1
Надеюсь на эту помощь,
Rob
Ответ 6
Начиная с версии 2.13.0,
import * as moment from 'moment';
Ответ 7
Переход этот поток, import moment from 'moment';
должен работать.
Ответ 8
Я попробовал все решения выше, но никто не работал у меня. Что работало
import moment from 'moment-with-locales-es6';
Ответ 9
У меня была такая же проблема с использованием momentJs (2.24) в моем проекте Angular 5 (5.2.9) (обновленном с Ng2) с Gulp и Rollup (0.58.0) для сборки prod.
Как уже упоминалось ранее, парни import * as moment from 'moment';
работает только для разработки (через SystemJS) со ссылкой на momentJs в списке пакетов:
{
name: 'moment',
path: 'node_modules/moment/min/moment.min.js'
}
Другой случай - использование объединения (производственная сборка) - моментальные коды имеют код ES6 (в момент /src), но экспортируются другим способом (тогда обычный экспорт). Вот почему import moment from 'moment';
работает с Rollup's
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\';'))
...;