Moment: Adicione instruções de uso com webpack

Criado em 22 jan. 2014  ·  31Comentários  ·  Fonte: moment/moment

Adicione à seção Onde usar instruções para integrar adequadamente o Moment.js com o webpack .

require('momentjs/moment.js') causa vários erros como este:

ERROR in ./app/bower_components/momentjs/lang/ar-ma.js
Module not found: Error: Cannot resolve module moment in /home/fernando/work/myproject/myproject-manage-app/app/bower_components/momentjs/lang
 @ ./app/bower_components/momentjs/lang/ar-ma.js 8:8-35

ERROR in ./app/bower_components/momentjs/lang/ar.js
Module not found: Error: Cannot resolve module moment in /home/fernando/work/myproject/myproject-manage-app/app/bower_components/momentjs/lang
 @ ./app/bower_components/momentjs/lang/ar.js 8:8-35

require ('momentjs/min/moment-with-langs.js') causa este aviso:

WARNING in ./app/bower_components/momentjs/min/moment-with-langs.js
Module not found: Error: Cannot resolve file or directory ./lang in /home/fernando/work/myproject/myproject-manage-app/app/bower_components/momentjs/min
 @ ./app/bower_components/momentjs/min/moment-with-langs.js 808:24-46
Documentation

Comentários muito úteis

Como @sokra sugeriu, adicionei o seguinte plugin para exigir apenas a localidade necessária. Observe também que o diretório lang em moment foi alterado para locale .

plugins: [
    new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|ko|ja|zh-cn)$/)
]

Todos 31 comentários

Eu nunca usei o Webpack, então não tenho certeza de quais seriam essas instruções. Você conseguiu dar conta? Em caso afirmativo, podemos adicionar suas instruções.

Obrigado pela resposta.

Ainda não, mas te mantenho informado.

Os arquivos de idioma estão procurando um módulo moment . Veja o cabeçalho:

    if (typeof define === 'function' && define.amd) {
        define(['moment'], factory); // AMD

moment é na verdade o nome correto para este módulo (veja package.json) e tudo funciona se você instalá-lo a partir do npm.

@fernandoacorreia Sua pasta se chama momentjs .

@icambron Por que não define(['../moment'], factory); como com CommonJs?

Seria melhor quando a ordem de CommonJs e AMD fosse consistente nos arquivos lang e no arquivo moment.js.


Por padrão, o webpack inclui todos os idiomas devido a esta instrução require('./lang/' + k); . Você pode substituir isso com ContextReplacementPlugin :

new webpack.ContextReplacementPlugin(/moment[\\\/]lang$/, /^\.\/(en-gb|de|pl)$/)

@sokra Obrigado por explicar sobre a inconsistência nas definições do módulo. @icambron pode dar uma olhada nessas sugestões?

A propósito, o diretório se chama momentjs porque eu o instalei seguindo as instruções aqui :

bower install --save momentjs

Estou declarando o nome do caminho ao exigir, como require ('momentjs/min/moment-with-langs.js') .

hmm ok... funciona se você usar as instruções do node.js.

@sokra Isso ajuda. Muito obrigado por depurar isso. Embora eu não queira instalá-lo via npm; Estou instalando todas as minhas dependências de frontend via bower e só procuro módulos em bower_components .

@icambron Para atualizar as instruções para torná-lo compatível com webpack (e, presumivelmente, outros carregadores de módulo), nos documentos altere esta linha:

bower install --save momentjs

para:

bower install --save moment=momentjs

As instruções do npm funcionaram para mim, mas não bower install --save moment=momentjs

@Sigfried Como é o seu arquivo bower.json ? O meu tem essa linha:

"moment": "momentjs#~2.5.1"

Meu webpack.config.js tem:

module.exports = {
  resolve: {
    alias: {
      moment: 'moment/moment.js',
    },
    modulesDirectories: ['app/bower_components']
  }
};

Estou exigindo momento como:

var moment = require('moment');

Estou usando uma estrutura de diretório padrão do Yeoman.

Isso fez isso por mim. Obrigado!
(Exceto que eu não estava usando o Yeoman e agora estou me perguntando se preciso começar a fazer isso... O ecossistema Javascript é incrível, passei os últimos três meses sem fazer nada além de economizar tempo! :)

Agora você pode usar bower install --save moment

@ichernev Isso soa bem. Nesse caso, acredito que atualizar a documentação de Onde usar resolveria esse problema.

Um pouco atrasado nisso, mas agora é possível usar o plug-in de fornecimento

    plugins: [
        new webpack.ProvidePlugin({
           "window.moment": "moment"
        }),
        new BowerWebpackPlugin()
    ]

Como @sokra sugeriu, adicionei o seguinte plugin para exigir apenas a localidade necessária. Observe também que o diretório lang em moment foi alterado para locale .

plugins: [
    new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|ko|ja|zh-cn)$/)
]

Item de documento adicionado como moment/momentjs.com#269. Vai rastrear lá.

Estou usando es6, typescript e regras tslint muito rígidas. Isto é o que acabei fazendo para entrar no projeto:

import "expor?momento!importa?this=>janela&exports=>falso&define=>falso!exporta?janela.momento!momento";

Acabei de criar uma pasta 'locale' vazia na mesma pasta que 'moment.min.js', para que inclua todos os arquivos js nessa pasta.

É um hack mas funciona.

Para carregar idiomas no Webpack preguiçosamente / dinamicamente você pode usar com bundle-loader :

Passo 1 - na configuração do webpack:

new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // to not to load all locales

Passo 2 - no código do cliente:

require('bundle!moment/locale/' + locale + '.js')(function () {
  moment().locale(locale).format('lll');
  // note that now you can use the locale even outside of this callback
});

No meu caso (webpack + npm install moment ) o problema foi com o webpack procurando por locales dentro da pasta src/lib/locale , porque era onde moment.js estava sendo pego.

Eu removi a pasta node_modules/moment/src completamente e importei o momento definindo sua localidade usando, por exemplo:

import moment from 'moment';
import 'moment/locale/en-gb';
moment.locale('en-gb');

Tudo funciona perfeitamente, sem avisos, e apenas as localidades que importo explicitamente são incluídas na compilação (mesmo sem usar o webpack.ContextReplacementPlugin conforme explicado neste comentário , que adicionei no início)

@micheleb a causa real para procurar nessa subpasta é a configuração incorreta de jsnext:main no package.json do momentjs, que é respeitado pelo webpack 2.

jsnext:main deve _não_ apontar para o código-fonte bruto, mas para uma compilação do módulo que usa a sintaxe do módulo ES6.

Isso pode ser contornado com o alias de 'moment' para 'moment/moment.js' (o commonjs "principal") na configuração do seu webpack ( resolve: { alias: { moment: 'moment/moment.js' } } ).

EDIT: Alternativamente, um uso do ContextReplacementPlugin que usa os dados de localidade do diretório src (ou seja, que solicita o mesmo módulo moment que jsnext:main ) é igual a:

new webpack.ContextReplacementPlugin(/^\.\/locale$/, context => {
  if (!/\/moment\//.test(context.context)) { return }
  // context needs to be modified in place
  Object.assign(context, {
    // include only CJK
    regExp: /^\.\/(ja|ko|zh)/,
    // point to the locale data folder relative to moment's src/lib/locale
    request: '../../locale'
  })
}),

Isso provavelmente poderia ser escrito sem usar o retorno de chamada, mas eu queria ter "mais certeza" de que isso se aplicaria apenas a uma solicitação ./locale dentro do módulo moment .

Certifique-se de que request não aponta para ../../../locale ; enquanto isso compila, resultará em 2 cópias inteiras de moment sendo empacotadas.

@sokra o que acontece se async: true for definido no contexto? Eu posso ver que os módulos são gerados como pedaços separados se eu fizer isso, mas qual é o comportamento de tempo de execução esperado; um acidente? Eu suponho que é true "por padrão" se for chamado para manipular um contexto require.ensure / System.import ?

isso foi corrigido? se não, deve ser reaberto?

Por que isso foi fechado? Este ainda é um problema que está ocorrendo.

@ajohnsonRH

"Acredito que atualizar a documentação resolveria esse problema."

"Adicionado item de documento como moment/momentjs.com#269. Será rastreado lá."

Portanto, o problema foi encerrado aqui porque foi substituído por um problema no site de documentação do Moment. Adoraríamos que alguém escrevesse um PR lá para resolver moment/momentjs.com#269.

@butterflyhug

Esta correção funcionou para mim:

  1. faça a instalação do npm
  2. abra vendor.ts e adicione a linha import 'moment'

Para referência:
Usando Angular2 v2.0.0, Webpack ^1.13.0

É possível não incluir toda a localidade sem adicionar configurações ao webpack? Estou usando o create-react-app e não tenho a capacidade de editar o arquivo de configuração do webpack.

Eu pesquiso em todos os lugares e sempre parece voltar a adicionar uma linha de configuração no webpack.
https://github.com/moment/moment/issues/2373
https://github.com/moment/moment/issues/2416

Concordo, acho que exigir as localidades deve ser apenas explícito, nunca implícito.

É tão óbvio de acordo com o número de problemas levantados aqui no momento, no webpack, no bower, npm, e o tempo gasto por todos para contorná-lo desde vários _anos_.

@ajohnsonRH

Eu instalei pacotes npm, mas quando eu faço

importe o momento do 'momento-fuso horário';

momento é sempre indefinido. Como isso?

Estou tendo esse mesmo problema usando o projeto Angular 2 CLI. Alguém já encontrou uma solução funcional?

Procurando pistas para um projeto Angular CLI também

Alguma pista para o Angular CLI?

Como você pode ver, perguntei há 4 meses sobre a CLI e nenhuma resposta, nossa solução foi simplesmente substituir moment por date-fns, e como também estamos usando chartjs em nosso projeto e tem uma dependência de momento, estamos no processo de substituindo isso também.

Esta página foi útil?
0 / 5 - 0 avaliações