5

I have just installed the package:

npm install moment-timezone --save

And in angular component I use it like this:

import * as moment from 'moment-timezone';
moment().tz('America/New York');

I guess this adds all timezone data (900+kB) to the vendors bundle and slows down application startup.

How to load it asynchronously, on demand only?

I would really like to use NPM solution, so that the database get's updated automatically when updating npm packages. Nobody would ever remember to update the timezones database manually.

Edit:

@Dimanoid's answer shows how to import moment-timezone from npm without data:

import * as moment from 'moment-timezone/moment-timezone';

And here's how you can include the data as lazy loaded asset:

  1. Modify angular.json -> projects -> yourprojects -> architect -> build -> options:

    "assets": [
        "src/favicon.ico",
        "src/assets/i18n",
        {   //add this
            "glob": "latest.json",
            "input": "node_modules/moment-timezone/data/packed",
            "output": "assets/moment-timezone"
        }
    ]
    
  2. request it on demand from assets folder:

    import * as moment from 'moment-timezone/moment-timezone';
    import { PlatformLocation } from '@angular/common';
    
    export class MyComponent implements OnInit {
    
      constructor(private platformLocation: PlatformLocation) {
      }
      ngOnInit(){
         //you can use @angular/http instead of fetch
         fetch(this.platformLocation.getBaseHrefFromDOM() +  'assets/moment-timezone/latest.json')
          .then(time => time.json())
          .then(timeZoneData => {
            moment.tz.load(timeZoneData);
          });
      }
    }
    
Liero
  • 25,216
  • 29
  • 151
  • 297
  • 2
    Load the timezones bundle when you need it and call `moment.tz.load()`. https://momentjs.com/timezone/docs/#/data-loading/loading-a-data-bundle/ PS.But I think moving you component with moment-tz to separate module and use lazy loading will be easier and more effective... – Dimanoid May 10 '19 at 09:58
  • but first, how do I reference moment-timezone without data in angular project? – Liero May 10 '19 at 18:34
  • As any other js library. Download, import, use. https://stackoverflow.com/questions/44945766/use-external-javascript-library-in-angular-application – Dimanoid May 11 '19 at 09:09
  • 1
    so npm package doesn't support lazy loading of the data bundle? – Liero May 11 '19 at 11:46

1 Answers1

2

Well ok, to not convert comments to forum let's summarize this all.

You can download the lib from official site, place it somewhere in your code tree, import it then load tz-bundle from backend and call moment.tz.load() to initialize moment-timezon then use it.

import 'moment';
import * as moment from '../../assets/moment-timezone-nodata';

ngOnInit() {
    this.loadTzBundle().subscribe(data => {
        moment.tz.load(data);
    });
}

To illustrtate this I made a minimal working example: https://stackblitz.com/edit/moment-tz-data-loading

Edit

I got a look at the sources and actually npm package has the lib and data separated. It just load the data when you import the defaults.

var moment = module.exports = require("./moment-timezone");
moment.tz.load(require('./data/packed/latest.json'));

So you can install the package and load the lib without data I think.

import * as moment from 'moment-timezone/moment-timezone';

I updated the example.

Dimanoid
  • 6,999
  • 4
  • 40
  • 55
  • I will upvote this, but the problem with this solution is, that this way the database won't ever get updated in real world. People update npm packages, but nobody will ever remember to update asset downloaded manually. – Liero May 13 '19 at 07:22
  • I got a look at the sources and actually npm package has the lib and data separated. I updated the answer. – Dimanoid May 13 '19 at 07:41