Loading library when needed in Angular

511 views Asked by At

In an Angular 8 app, my component has a table that can be exported to an excel file. I'm using the library xlsx for that. The webpack-bundle-analyzer shows that the xlsx library uses 65% of my total chunk size.

As the export feature is used quite rarely, I'd like to exclude it from the initial bundle to increase performance for the majority of the users and load it when the user clicks on "export" and they need to wait for the download anyway.

This is what I currently have:

import * as xlsx from 'xlsx';
...
exportToExcel(filename, worksheet) {
   const ws: xlsx.WorkSheet = xlsx.utils.json_to_sheet(this.tableData);
   const wb: xlsx.WorkBook = xlsx.utils.book_new();
   xlsx.utils.book_append_sheet(wb, ws, worksheet);
   xlsx.writeFile(wb, filename+'.xlsx');
}

I would imagine something like this:

exportToExcel(filename, worksheet) {
   loadScript('/scripts/xlsx.js').then(xlsx => {
      const ws: xlsx.WorkSheet = xlsx.utils.json_to_sheet(this.tableData);
      const wb: xlsx.WorkBook = xlsx.utils.book_new();
      xlsx.utils.book_append_sheet(wb, ws, worksheet);
      xlsx.writeFile(wb, filename+'.xlsx');
   })       
}

Is there a way to do that? Or do you have any other suggestions?

2

There are 2 answers

0
StPaulis On

Something like this may help:

exportExcel() {
        import("xlsx").then(xlsx => {
            const worksheet = xlsx.utils.json_to_sheet(this.products);
            const workbook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
            const excelBuffer: any = xlsx.write(workbook, { bookType: 'xlsx', type: 'array' });
            this.saveAsExcelFile(excelBuffer, "products");
        });
}

From PrimeNg - Export

0
Janardhan Burle On

You can lazy load any script library in angular as below.

1. Specify that a specific script is to be lazy loaded and angular will just output a bundle and won’t add it to the index.html.

instead of a simple string in angular.json,

"scripts": [
        "src/some-script.js"
      ]

You do this by specifying the script in object format. as below.

"scripts": [
  {
    "input": "path/to/your/lazy-script.js",
    "lazy": true,
    "bundleName": "lazy-loaded-script"
  },
]

Note: You also must specify the output name (bundleName) to be able to reference to it later. If you don’t, Angular CLI will randomly generate a bundle name, which will change on each build.

2. To load our script, we begin by creating a new method loadExternalScript(scriptURL), which will return a promise as below.

loadExternalScript(scriptURL:string) {
  return new Promise(resolve => {
    const scriptElement = document.createElement('script');
    scriptElement.src = scriptUrl;
    scriptElement.onload = resolve;
    document.body.appendChild(scriptElement);
  });
}

call the methods to load the scripts as show below:

this.loadExternalScript('url/to/your/scripts').then(() => {}).catch(() => {});