Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load momentjs timezones data asynchronously in Angular

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);
          });
      }
    }
    
like image 844
Liero Avatar asked Oct 28 '22 15:10

Liero


1 Answers

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.

like image 147
Dimanoid Avatar answered Dec 21 '22 15:12

Dimanoid