2016-09-15 4 views
26

Я пытаюсь следовать за official AoT guide для Angular 2, и я использую Moment.js в своем приложении. Moment.js находится на моем файле packages.json, и я использую версию 2.15.0. Я импортировать его, как это до сих пор:Использование Rollup для компилятора AoT для Angular 2 и импорт Moment.js

import * as moment from 'moment'; 

Но когда я доберусь до той части, где я должен запустить накопительный пакет, я в конечном итоге со следующей ошибкой:

Cannot call a namespace ('moment')

который, кажется, быть связанным с тем, как я импортирую момент в соответствии с this. Итак, как я должен это делать? Я пока не могу импортировать момент другим способом. Если я использую

import moment from 'moment' 

Я получаю ошибку компиляции

External module ''moment'' has no default export

+0

Вы могли понять это? – jjj

+0

Не совсем ...:/ –

+0

+1 Имея ту же проблему с 'import * как HighchartsMore от" highcharts/highcharts-more "; HighChartsMore (Highcharts) ' – Tair

ответ

17

Мне, наконец, удалось избавиться от обеих ошибок. Действительно, чтобы избежать:

Cannot call a namespace ('moment')

Вы должны использовать:

import moment from 'moment'

Тогда, чтобы избежать

"moment" has no default export

Вы должны добавить в свой tsconfig.json (compilerOptions):

"allowSyntheticDefaultImports": true

EDIT 17/11/2016

Я также должен был добавить следующее в мой накопительный-config.js файл:

plugins: [ 
    nodeResolve({jsnext: true, module: true}), 
    commonjs({ 
    include: [ 
     'node_modules/rxjs/**', 
     'node_modules/moment/**' 
     ] 
    } 
    }), 
    uglify() 
] 
+2

Это работает для конфигурации накопителя AoT, но НЕ работает с использованием systemjs в режиме debug/dev build. –

+1

@MarkPerry Да, я все еще пытаюсь использовать SystemJS и Webpack. Но эта тема была связана с свертыванием. Я дам вам знать, найду ли что-нибудь для SystemJS. – j3r6me

+1

Отмечено это как принятый ответ, потому что он исправляет AoT, но мне действительно нужно решение, которое будет работать как для AoT, так и JIT без изменений ... –

0

В версии 2.13.0,

import * as moment from 'moment';

+0

Это дает Модуль [...] не имеет экспортированного элемента по умолчанию '. –

3

У меня были те же проблемы, описанные выше.

import * as moment from 'moment'; - работал при разработке и загрузке через систему, но не во время свертывания.

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 добавляется на страницу где-то с помощью тега сценария, к сожалению, он не будет включен в файл buildup build.

+1

У меня такая же проблема, как и у вас, и я действительно не понимаю, почему все не жалуются на это ... Создание дополнительной функции загрузки является абсурдным требованием, особенно когда мы уже используем множество разных загрузчиков! –

+0

Только что потратили весь вечер, пытаясь развернуть мой сайт, и только теперь я решил проблему благодаря вашему драгоценному сообщению. Я сделал то же самое для lodash: // lodash-loader.ts import {default as _lodash} из "lodash"; экспорт окна по умолчанию ["_"] как _lodash.LoDashStatic; – Etchelon

+0

Утонченная идея, но я считаю совершенно неприемлемым использование этого. Я просто хочу использовать внешнюю библиотеку ради Христа. * вздох, такие моменты, как эти (не предназначенные для каламбуров) заставляют меня сожалеть об использовании Angular 2 ... –

5

Вот что я сделал, чтобы сделать рабочий момент с машинописным текстом (на 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. В машинописном использовании момент с помощью литья mo Мента, как любой, и вызовите 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')

+0

Спасибо! Это сработало для меня. 'import * как momentLib из« момента »;' 'const moment = (momentLib как любой) .default? (instantLib как any) .default: momentLib; ' –

11

Я нашел хорошее решение проблемы под рукой:

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 (Накопительный-плагин-CommonJS)

+0

Интересно, это сработало для системных js и машинописных текстов (без дополнительного флага компилятора), но rollup дает мне ошибку:' 'default 'не экспортируется node_modules \ moment-es6 \ index.js' –

+0

Я думаю, мне просто нужно указать [named export] (https://github.com/rollup/rollup-plugin-commonjs#custom-named-exports) - правильно? –

2

У нас была аналогичная проблема с нг-packagr, который использует накопительный пакет для создания модуля, который может быть опубликован в реестре 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 

Мы могли бы обходным путем это, назначая экспортируемую функцию инициализации в другую сопзЬ и использовать его в коде:

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

svgPanZoom(element); 

Мы также сделали изменения tsconfig.json конфигурации, как описано выше.

Версия: нг-packagr: 1.4.1 Накопительные: 0.50.0 машинописи: 2.3.5 @ угловой/кли: 1.4.8 WebPack: 3.7.1

Надеется, что это поможет,

Rob

0

Я пробовал все решения выше, но никто не работал для меня. Что работало

import moment from 'moment-with-locales-es6';