New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add usage instructions with webpack #1435

Closed
fernandoacorreia opened this Issue Jan 22, 2014 · 31 comments

Comments

Projects
None yet
@fernandoacorreia

fernandoacorreia commented Jan 22, 2014

Add to the section Where to use it instructions for properly integrating Moment.js with webpack.

require('momentjs/moment.js') causes several errors like this:

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') causes this warning:

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
@icambron

This comment has been minimized.

Show comment
Hide comment
@icambron

icambron Jan 22, 2014

Member

I've never used Webpack, so I'm unsure what those instructions would be. Were you able to figure it out? If so, we could add your instructions.

Member

icambron commented Jan 22, 2014

I've never used Webpack, so I'm unsure what those instructions would be. Were you able to figure it out? If so, we could add your instructions.

@fernandoacorreia

This comment has been minimized.

Show comment
Hide comment
@fernandoacorreia

fernandoacorreia Jan 22, 2014

Thanks for the reply.

Not yet, but I'll keep you posted.

fernandoacorreia commented Jan 22, 2014

Thanks for the reply.

Not yet, but I'll keep you posted.

@sokra

This comment has been minimized.

Show comment
Hide comment
@sokra

sokra Jan 23, 2014

The language files are looking for a module moment. See header:

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

moment is actually the correct name for this module (see package.json) and everything just works if you install it from npm.

@fernandoacorreia Your folder is named momentjs.

@icambron Why not define(['../moment'], factory); as with CommonJs?

It would be better when the order of CommonJs and AMD is consistent in the lang files and the moment.js file.


By default webpack includes all languages because of this statement require('./lang/' + k);. You can override this with the ContextReplacementPlugin:

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

sokra commented Jan 23, 2014

The language files are looking for a module moment. See header:

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

moment is actually the correct name for this module (see package.json) and everything just works if you install it from npm.

@fernandoacorreia Your folder is named momentjs.

@icambron Why not define(['../moment'], factory); as with CommonJs?

It would be better when the order of CommonJs and AMD is consistent in the lang files and the moment.js file.


By default webpack includes all languages because of this statement require('./lang/' + k);. You can override this with the ContextReplacementPlugin:

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

This comment has been minimized.

Show comment
Hide comment
@fernandoacorreia

fernandoacorreia Jan 23, 2014

@sokra Thanks for explaining about the inconsistency in the module definitions. @icambron can you take a look at these suggestions?

By the way, the directory is named momentjs because I installed it following the instructions here:

bower install --save momentjs

I'm declaring the pathname when requiring, like require ('momentjs/min/moment-with-langs.js').

fernandoacorreia commented Jan 23, 2014

@sokra Thanks for explaining about the inconsistency in the module definitions. @icambron can you take a look at these suggestions?

By the way, the directory is named momentjs because I installed it following the instructions here:

bower install --save momentjs

I'm declaring the pathname when requiring, like require ('momentjs/min/moment-with-langs.js').

@sokra

This comment has been minimized.

Show comment
Hide comment
@sokra

sokra Jan 23, 2014

hmm ok... it works if you use the node.js instructions.

sokra commented Jan 23, 2014

hmm ok... it works if you use the node.js instructions.

@fernandoacorreia

This comment has been minimized.

Show comment
Hide comment
@fernandoacorreia

fernandoacorreia Jan 23, 2014

@sokra That helps. Thanks a lot for debugging this. Although I don't want to install it via npm; I'm installing all my frontend dependencies via bower and I only search for modules in bower_components.

@icambron To update the instructions to make it compatible with webpack (and, presumably, other module loaders), in the docs change this line:

bower install --save momentjs

to:

bower install --save moment=momentjs

fernandoacorreia commented Jan 23, 2014

@sokra That helps. Thanks a lot for debugging this. Although I don't want to install it via npm; I'm installing all my frontend dependencies via bower and I only search for modules in bower_components.

@icambron To update the instructions to make it compatible with webpack (and, presumably, other module loaders), in the docs change this line:

bower install --save momentjs

to:

bower install --save moment=momentjs
@Sigfried

This comment has been minimized.

Show comment
Hide comment
@Sigfried

Sigfried Feb 1, 2014

The npm instructions worked for me, but not bower install --save moment=momentjs

Sigfried commented Feb 1, 2014

The npm instructions worked for me, but not bower install --save moment=momentjs

@fernandoacorreia

This comment has been minimized.

Show comment
Hide comment
@fernandoacorreia

fernandoacorreia Feb 1, 2014

@Sigfried What does your bower.json file look like? Mine has this line:

"moment": "momentjs#~2.5.1"

My webpack.config.js has:

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

I'm requiring moment as:

var moment = require('moment');

I'm using a standard Yeoman directory structure.

fernandoacorreia commented Feb 1, 2014

@Sigfried What does your bower.json file look like? Mine has this line:

"moment": "momentjs#~2.5.1"

My webpack.config.js has:

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

I'm requiring moment as:

var moment = require('moment');

I'm using a standard Yeoman directory structure.

@Sigfried

This comment has been minimized.

Show comment
Hide comment
@Sigfried

Sigfried Feb 3, 2014

That did it for me. Thanks!
(Except I wasn't using Yeoman and now I'm wondering if I need to start doing that... The Javascript ecosystem is amazing, I've spend the last three months doing nothing but saving time! :)

Sigfried commented Feb 3, 2014

That did it for me. Thanks!
(Except I wasn't using Yeoman and now I'm wondering if I need to start doing that... The Javascript ecosystem is amazing, I've spend the last three months doing nothing but saving time! :)

@ichernev

This comment has been minimized.

Show comment
Hide comment
@ichernev

ichernev Feb 11, 2014

Contributor

Now you can use bower install --save moment

Contributor

ichernev commented Feb 11, 2014

Now you can use bower install --save moment

@fernandoacorreia

This comment has been minimized.

Show comment
Hide comment
@fernandoacorreia

fernandoacorreia Feb 18, 2014

@ichernev That sounds good. In this case, I believe that updating the Where to use it documentation would resolve this issue.

fernandoacorreia commented Feb 18, 2014

@ichernev That sounds good. In this case, I believe that updating the Where to use it documentation would resolve this issue.

@full-of-foo

This comment has been minimized.

Show comment
Hide comment
@full-of-foo

full-of-foo Jan 8, 2016

Bit late on this, but now one can use the provide plugin

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

full-of-foo commented Jan 8, 2016

Bit late on this, but now one can use the provide plugin

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

This comment has been minimized.

Show comment
Hide comment
@kadishmal

kadishmal Feb 22, 2016

As @sokra suggested, I have added the following plugin in order to require only the necessary locale. Also notice that lang directory in moment has been changed to locale.

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

kadishmal commented Feb 22, 2016

As @sokra suggested, I have added the following plugin in order to require only the necessary locale. Also notice that lang directory in moment has been changed to locale.

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

This comment has been minimized.

Show comment
Hide comment
@mj1856

mj1856 Feb 24, 2016

Member

Added doc item as moment/momentjs.com#269. Will track there.

Member

mj1856 commented Feb 24, 2016

Added doc item as moment/momentjs.com#269. Will track there.

@grbush

This comment has been minimized.

Show comment
Hide comment
@grbush

grbush Jun 9, 2016

I'm using es6, typescript, and very tight tslint rules. This is what I ended up doing to get moment into the project:

import "expose?moment!imports?this=>window&exports=>false&define=>false!exports?window.moment!moment";

grbush commented Jun 9, 2016

I'm using es6, typescript, and very tight tslint rules. This is what I ended up doing to get moment into the project:

import "expose?moment!imports?this=>window&exports=>false&define=>false!exports?window.moment!moment";

@neyer

This comment has been minimized.

Show comment
Hide comment
@neyer

neyer Jun 29, 2016

I just created an empty 'locale' folder in the same folder as 'moment.min.js', so that it includes all of the js files in that folder.

It's a hack but it works.

neyer commented Jun 29, 2016

I just created an empty 'locale' folder in the same folder as 'moment.min.js', so that it includes all of the js files in that folder.

It's a hack but it works.

@zdila

This comment has been minimized.

Show comment
Hide comment
@zdila

zdila Jul 14, 2016

To load languages in Webpack lazy / dynamically you can use with bundle-loader:

Step 1 - in webpack configuration:

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

Step 2 - in the client code:

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
});

zdila commented Jul 14, 2016

To load languages in Webpack lazy / dynamically you can use with bundle-loader:

Step 1 - in webpack configuration:

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

Step 2 - in the client code:

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
});
@micheleb

This comment has been minimized.

Show comment
Hide comment
@micheleb

micheleb Aug 19, 2016

In my case (webpack + npm install moment) the issue was with webpack looking for locales inside the src/lib/locale folder, because that's where moment.js was being picked up.

I removed the node_modules/moment/src folder altogether, and import moment setting its locale using e.g.:

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

Everything works perfectly, no warnings, and only the locales I import explicitly are included in the build (even without using the webpack.ContextReplacementPlugin as explained in this comment, which I added at first)

micheleb commented Aug 19, 2016

In my case (webpack + npm install moment) the issue was with webpack looking for locales inside the src/lib/locale folder, because that's where moment.js was being picked up.

I removed the node_modules/moment/src folder altogether, and import moment setting its locale using e.g.:

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

Everything works perfectly, no warnings, and only the locales I import explicitly are included in the build (even without using the webpack.ContextReplacementPlugin as explained in this comment, which I added at first)

@Kovensky

This comment has been minimized.

Show comment
Hide comment
@Kovensky

Kovensky Sep 27, 2016

@micheleb the actual cause for looking in that subfolder is the incorrect setting of jsnext:main in momentjs's package.json, which is respected by webpack 2.

jsnext:main should not point to the raw source code, but to a build of the module that does use ES6 module syntax.

This can be worked around by aliasing 'moment' to 'moment/moment.js' (the commonjs "main") in your webpack config (resolve: { alias: { moment: 'moment/moment.js' } }).

EDIT: Alternatively, a use of the ContextReplacementPlugin that uses the locale data from the src dir (i.e. that requests the same moment module as jsnext:main) is similar to:

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'
  })
}),

This probably could be written without using the callback, but I wanted to be "more sure" that this would only apply to a ./locale request inside the moment module.

Make sure the request doesn't point to ../../../locale; while that will compile, it will result in 2 whole copies of moment being bundled.

@sokra what happens if async: true gets set in the context? I can see that the modules are generated as separate chunks if I do that, but what is the expected runtime behavior; a crash? I assume it is true "by default" if it's called for handling a require.ensure / System.import's context?

Kovensky commented Sep 27, 2016

@micheleb the actual cause for looking in that subfolder is the incorrect setting of jsnext:main in momentjs's package.json, which is respected by webpack 2.

jsnext:main should not point to the raw source code, but to a build of the module that does use ES6 module syntax.

This can be worked around by aliasing 'moment' to 'moment/moment.js' (the commonjs "main") in your webpack config (resolve: { alias: { moment: 'moment/moment.js' } }).

EDIT: Alternatively, a use of the ContextReplacementPlugin that uses the locale data from the src dir (i.e. that requests the same moment module as jsnext:main) is similar to:

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'
  })
}),

This probably could be written without using the callback, but I wanted to be "more sure" that this would only apply to a ./locale request inside the moment module.

Make sure the request doesn't point to ../../../locale; while that will compile, it will result in 2 whole copies of moment being bundled.

@sokra what happens if async: true gets set in the context? I can see that the modules are generated as separate chunks if I do that, but what is the expected runtime behavior; a crash? I assume it is true "by default" if it's called for handling a require.ensure / System.import's context?

@leebenson

This comment has been minimized.

Show comment
Hide comment
@leebenson

leebenson Oct 10, 2016

was this fixed? if not, should it be re-opened?

leebenson commented Oct 10, 2016

was this fixed? if not, should it be re-opened?

@ajohnsonRH

This comment has been minimized.

Show comment
Hide comment
@ajohnsonRH

ajohnsonRH Nov 2, 2016

Why was this closed? This is still an occurring issue.

ajohnsonRH commented Nov 2, 2016

Why was this closed? This is still an occurring issue.

@butterflyhug

This comment has been minimized.

Show comment
Hide comment
@butterflyhug

butterflyhug Nov 2, 2016

Member

@ajohnsonRH

"I believe that updating the documentation would resolve this issue."

"Added doc item as moment/momentjs.com#269. Will track there."

So, the issue was closed here because it's been superseded by an issue in Moment's documentation website. We'd love for someone to write a PR there to resolve moment/momentjs.com#269.

Member

butterflyhug commented Nov 2, 2016

@ajohnsonRH

"I believe that updating the documentation would resolve this issue."

"Added doc item as moment/momentjs.com#269. Will track there."

So, the issue was closed here because it's been superseded by an issue in Moment's documentation website. We'd love for someone to write a PR there to resolve moment/momentjs.com#269.

@ajohnsonRH

This comment has been minimized.

Show comment
Hide comment
@ajohnsonRH

ajohnsonRH Nov 2, 2016

@butterflyhug

This fix worked for me:

  1. do the npm install
  2. open vendor.ts and add the line import 'moment'

For reference:
Using Angular2 v2.0.0, Webpack ^1.13.0

ajohnsonRH commented Nov 2, 2016

@butterflyhug

This fix worked for me:

  1. do the npm install
  2. open vendor.ts and add the line import 'moment'

For reference:
Using Angular2 v2.0.0, Webpack ^1.13.0

@orditeck

This comment has been minimized.

Show comment
Hide comment
@orditeck

orditeck Nov 18, 2016

Is it possible to not includes all the locale without adding configurations to webpack? I'm using create-react-app and I don't have the ability to edit the webpack config file.

I search everywhere and it always seems to come back to adding a config line in webpack.
#2373
#2416

orditeck commented Nov 18, 2016

Is it possible to not includes all the locale without adding configurations to webpack? I'm using create-react-app and I don't have the ability to edit the webpack config file.

I search everywhere and it always seems to come back to adding a config line in webpack.
#2373
#2416

@vperron

This comment has been minimized.

Show comment
Hide comment
@vperron

vperron Dec 7, 2016

Agreed, I think requiring the locales should be explicit only, never implicit.

It's so obvious according to the number of issues raised here in moment, in webpack, in bower, npm, and the time spent by everyone to circumvent it since several years.

vperron commented Dec 7, 2016

Agreed, I think requiring the locales should be explicit only, never implicit.

It's so obvious according to the number of issues raised here in moment, in webpack, in bower, npm, and the time spent by everyone to circumvent it since several years.

@trsh

This comment has been minimized.

Show comment
Hide comment
@trsh

trsh Jan 2, 2017

@ajohnsonRH

I installed npm packs, but when I do

import moment from 'moment-timezone';

moment is always undefined. How that?

trsh commented Jan 2, 2017

@ajohnsonRH

I installed npm packs, but when I do

import moment from 'moment-timezone';

moment is always undefined. How that?

@johnjameshopley

This comment has been minimized.

Show comment
Hide comment
@johnjameshopley

johnjameshopley Oct 11, 2017

I am having this same problem using Angular 2 CLI project. Has anyone found a working solution yet?

johnjameshopley commented Oct 11, 2017

I am having this same problem using Angular 2 CLI project. Has anyone found a working solution yet?

@Lakston

This comment has been minimized.

Show comment
Hide comment
@Lakston

Lakston Nov 6, 2017

Looking for clues for an Angular CLI project too

Lakston commented Nov 6, 2017

Looking for clues for an Angular CLI project too

@FlawaCLV

This comment has been minimized.

Show comment
Hide comment
@FlawaCLV

FlawaCLV Feb 7, 2018

Any clues for Angular CLI ?

FlawaCLV commented Feb 7, 2018

Any clues for Angular CLI ?

@Lakston

This comment has been minimized.

Show comment
Hide comment
@Lakston

Lakston Feb 8, 2018

As you can see I asked 4 months ago about the CLI and no answers, our solution was to simply replace moment with date-fns, and since we are also using chartjs in our project and it has a moment dependency we are in the process of replacing that too.

Lakston commented Feb 8, 2018

As you can see I asked 4 months ago about the CLI and no answers, our solution was to simply replace moment with date-fns, and since we are also using chartjs in our project and it has a moment dependency we are in the process of replacing that too.

@plandem

This comment has been minimized.

Show comment
Hide comment
@plandem

plandem commented Mar 29, 2018

quite nice solution
moment/momentjs.com#489

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment