AngularJS- Dynamic Loading of script files using LazyLoad- Webpack
Asked Answered
M

3

17

Right now in my index.html page I have links to two CDN files one being a JS and the other a CSS file.

i.e. in the the bottom of my body

https://somedomain.com/files/js/js.min.js

and in the head

https://somedomain.com/files/css/css.min.css

But right now they aren't needed on my homepage but just in one particular route. So I was looking into how I can lazy load these CDN resources when that routes gets hit i.e. /profile and only then ?

These aren't installed via bower or npm but just loaded via CDN url for example jquery. How in Angular 1 and Webpack can I lazy load that based on a route ?

Mackey answered 16/11, 2016 at 22:38 Comment(4)
By one particular route what does it refer to?Harp
Angular has route i.e /profile. Profile has a seperate Module, Controller, view etc I only want to load the above libraries when a user navigates to that particular route.Mackey
$ocLazyLoad works greatMirepoix
$ocLazyLoad Example app freakyjolly.com/how-to-lazy-load-modules-controllers-angularjsUlcerate
H
12

Here you go.. It is made possible using oclazyload. Have a look at below code. A plunker linked below

I have a module Called myApp as below

angular.module('myApp', ['ui.router','oc.lazyLoad'])
    .config(function ($stateProvider, $locationProvider, $ocLazyLoadProvider) {
            $stateProvider
                .state("home", {
                    url: "/home",
                    templateUrl: "Home.html",
                    controller: 'homeCtrl',
                    resolve: { 
                        loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                            return $ocLazyLoad.load('homeCtrl.js');
                        }]
                    }
                })
            .state("profile", {
                url:"/profile",
                templateUrl: "profile.html",
                 resolve: {
                      loadMyCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
                      return $ocLazyLoad.load('someModule.js');
                        }]
                    }
            })

    });

I have another module called someApp as below

(function () {
var mynewapp=angular.module('someApp',['myApp']);

mynewapp.config(function(){

  //your code to route from here! 

});
      mynewapp.controller("profileCtrl", function ($scope) {

            console.log("reached profile controller");
        });

})();

I have a Live Plunker for your demo here

Harp answered 19/11, 2016 at 2:47 Comment(0)
F
2

I have this JStaticLoader repo, to ease me loading static files whenever I need them. Though, it's not angularized, but you can still use it in your app as a directive, direct call it from your controller or even in the $rootScope to load your desired js.

JStaticLoader uses pure js and require no dependencies. It uses XMLHttpRequest to load the static files.

As an example use in your app.js (on $routeChangeStart or $stateChangeStart)

myApp
.run(['$rootScope', '$http', function ($rootScope, $http) {
    var scriptExists = function (scriptId) {
        if (document.getElementById(scriptId)) {
            return true;
        }

        return false;
    };

    var addLazyScript = function (scriptId, url) {
        if (scriptExists(scriptId)) return;

        var js = document.createElement('script'),
            els = document.getElementsByTagName('script')[0];

        js.id = scriptId;
        js.src = url;
        js.type = "text/javascript";

        els.parentNode.insertBefore(js, els);
    };

    $rootScope.$on('$routeChangeStart', function (e, current) {
        if (current.controller === 'MainCtrl') {
            var pathUrls = ["https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.js"],
                scriptId = 'lazyScript1';

            if (scriptExists(scriptId)) return;

            JStaticLoader(pathUrls, { files: ['js'] }, function (vals, totalTime) {
                /* Success */
                for (var i = 0; i < vals.length; i++) {
                    var path = vals[i];
                    addLazyScript(scriptId, path);
                }
            }, function (error, totalTime) {
                /* Error */
                console.warn(error, totalTime);
            });
        }
    });
}]);

On the sample above, I get a js file by using xhr, and append it as a script in my document once it's finished. The script will then be loaded from your browser's cache.

Fairspoken answered 19/11, 2016 at 2:14 Comment(4)
XMLHttpRequest is not an external library.. it's actually as built in as can get developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest. By implement it on your own, do you mean like... implementing ajax without using XMLHttpRequest? sorry to be blunt but.. what a terrible idea!Precise
@FélixGagnon-Grenier I am not saying XHR is external library.. But, JStaticLoader is..Fairspoken
... I must have been mislead by this sentence: "It's using XMLHttpRequest to load them. So, if you do not wish to use external library for this, you can implement it your own." At first (and actually, many read afterwards too) and without surrounding context, it totally means that XMLHttpRequest is an external library, and that if you don't want to use those, you should implement your own. Maybe just remove that part about XHR and just say that JStaticLoader is, and that if you want to avoid external libraries, you should implement it yourself.Precise
which, thinking about it, means you could also just remove that altogether, as the point is to provide answer, not to tell op they can implement it on their own... :)Precise
E
2

Strictly talking about the Webpack -

Webpack is just a module bundler and not a javascript loader.Since it packages files only from the local storage and doesn't load the files from the web(except its own chunks).ALthough other modules may be included into the webpack which may do the same process.

I will demonstrate only some of the modules which you can try,as there are many such defined on the web.

Therefore a better way to lazy load the cdn from the another domain would be using the javascript loader - script.js

It can be loaded in the following way -

var $script = require("script.js");
 $script = ("https://somedomain.com/files/js/js.min.js or https://somedomain.com/files/css/css.min.css",function(){
 //.... is ready now
});

This is possible because the script-loader just evaluates the javascript in the global context.

References here

Concerning about the issue of lazy loading the cdn into the angular app

The following library Lab JS is made specifically for this purpose. It becomes very simple to load and bloack the javascript using this library.

Here is an example to demonstrate

<script src="LAB.js"></script>
  <script>
    $LAB
     .script("/local/init.js").wait(function(){
       waitfunction();
     });
  <script>

OR

You can use the require.js

Here is an example to load the jquery

require.config({
    paths: {
        "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min"
    },
    waitSeconds: 40
  });

You should also consider the following paragraph from this article.

Loading third party scripts async is key for having high performance web pages, but those scripts still block onload. Take the time to analyze your web performance data and understand if and how those not-so-important content/widgets/ads/tracking codes impact page load times.

Ecdysiast answered 21/11, 2016 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.