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
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.
Thanks for the reply.
Not yet, but I'll keep you posted.
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 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')
.
hmm ok... it works if you use the node.js instructions.
@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
The npm instructions worked for me, but not bower install --save moment=momentjs
@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.
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! :)
Now you can use bower install --save moment
@ichernev That sounds good. In this case, I believe that updating the Where to use it documentation would resolve this issue.
Bit late on this, but now one can use the provide plugin
plugins: [
new webpack.ProvidePlugin({
"window.moment": "moment"
}),
new BowerWebpackPlugin()
]
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)$/)
]
Added doc item as moment/momentjs.com#269. Will track there.
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";
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.
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
});
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 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?
was this fixed? if not, should it be re-opened?
Why was this closed? This is still an occurring issue.
@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.
@butterflyhug
This fix worked for me:
import 'moment'
For reference:
Using Angular2 v2.0.0, Webpack ^1.13.0
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.
https://github.com/moment/moment/issues/2373
https://github.com/moment/moment/issues/2416
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_.
@ajohnsonRH
I installed npm packs, but when I do
import moment from 'moment-timezone';
moment is always undefined. How that?
I am having this same problem using Angular 2 CLI project. Has anyone found a working solution yet?
Looking for clues for an Angular CLI project too
Any clues for Angular CLI ?
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.
quite nice solution
https://github.com/moment/momentjs.com/pull/489
Most helpful comment
As @sokra suggested, I have added the following plugin in order to require only the necessary locale. Also notice that
lang
directory inmoment
has been changed tolocale
.