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 ?

4

3 回答 3

12

给你.. 使用oclazyload使之成为可能。看看下面的代码。下面链接的一个plunker

我有一个名为myApp的模块,如下所示

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');
                        }]
                    }
            })

    });

我有另一个名为someApp的模块,如下所示

(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");
        });

})();

我有一个 Live Plunker 用于您的演示

于 2016-11-19T02:47:07.393 回答
2

严格来说 Webpack -

Webpack 只是一个模块捆绑器,而不是一个 javascript 加载器。因为它仅从本地存储打包文件并且不从 web 加载文件(除了它自己的块)。尽管其他模块可能包含在 webpack 中,这可能会相同的过程。

我将只演示一些您可以尝试的模块,因为在网络上有很多这样的定义。

因此,从另一个域延迟加载 cdn 的更好方法是使用javascript 加载器 - script.js

它可以通过以下方式加载 -

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
});

这是可能的,因为脚本加载器只是在全局上下文中评估 javascript。

参考这里

关于延迟加载cdn到angular app的问题

以下库Lab JS是专门为此目的而制作的。使用这个库加载和阻止 javascript 变得非常简单。

这是一个示例来演示

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

或者

您可以使用require.js

这是加载jquery的示例

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

您还应该考虑本文中的以下段落

异步加载第三方脚本是拥有高性能网页的关键,但这些脚本仍然会阻止 onload。花时间分析您的网络性能数据,并了解这些不那么重要的内容/小部件/广告/跟踪代码是否以及如何影响页面加载时间。

于 2016-11-21T09:26:35.050 回答
2

我有这个JStaticLoader repo,方便我在需要时加载静态文件。虽然,它没有角化,但您仍然可以在您的应用程序中使用它作为directive,直接从您的应用程序中调用它,controller甚至在$rootScope加载您想要的js.

JStaticLoader使用纯js,不需要依赖。它用于XMLHttpRequest加载静态文件。

例如在您的app.js(on $routeChangeStartor $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);
            });
        }
    });
}]);

在上面的示例中,我js使用 xhr 获取了一个文件,并在完成后将其作为 a 添加script到 mydocument中。然后将从浏览器的缓存中加载该脚本。

于 2016-11-19T02:14:28.500 回答