Javascript Angular:如何延迟加载google分析脚本?

Javascript Angular:如何延迟加载google分析脚本?,javascript,angular,typescript,google-analytics,angular8,Javascript,Angular,Typescript,Google Analytics,Angular8,我目前正在使用Angular 8。 我想知道如何懒洋洋地加载我的谷歌分析脚本。 我发现一些关于全局脚本的文档是使用angular.json中的脚本数组延迟加载的: "scripts": [ "src/global-script.js", { "input": "src/lazy-script.js", "lazy": true }, { "input": "src/pre-rename-script.js", "bundleName": "renamed-script" }, ],

我目前正在使用Angular 8。 我想知道如何懒洋洋地加载我的谷歌分析脚本。 我发现一些关于全局脚本的文档是使用angular.json中的脚本数组延迟加载的:

"scripts": [
  "src/global-script.js",
  { "input": "src/lazy-script.js", "lazy": true },
  { "input": "src/pre-rename-script.js", "bundleName": "renamed-script" },
],
通过

但它说现在已经贬值了,他们查阅了他们的文档,但我找不到任何关于它的信息


GTM google tag manager会减慢绘制时间。所以我只希望在我的angular应用程序最初加载完成后才激活GTM

你们有什么例子给我看吗


谢谢。

最好将这些脚本保存在src\assets文件夹中,并将它们直接添加到index.html文件中

角度应用程序 ...
您可以使用承诺和服务的组合来实现这一点。基本上,您需要做的是创建一个服务,该服务在主体中动态注入脚本标记并设置脚本的路径,一旦设置了路径,请解析承诺,以便可以使用脚本的功能。 以下是一项服务,它可以做到这一点:

export class DelayedScriptLoader {

private delayInMilliseconds: number;
private scriptPromise: Promise<void> | null;
private urls: string[];

// I initialize the delayed script loader service.
constructor( urls: string[], delayInMilliseconds: number );
constructor( urls: string, delayInMilliseconds: number );
constructor( urls: any, delayInMilliseconds: number ) {

    this.delayInMilliseconds = delayInMilliseconds;
    this.scriptPromise = null;
    this.urls = Array.isArray( urls )
        ? urls
        : [ urls ]
    ;

}

// ---
// PUBLIC METHODS.
// ---

// I load the the underlying Script tags. Returns a Promise.
public load() : Promise<void> {

    // If we've already configured the script request, just return it. This will
    // naturally queue-up the requests until the script is resolved.
    if ( this.scriptPromise ) {

        return( this.scriptPromise );

    }

    // By using a Promise-based workflow to manage the deferred script loading,
    // requests will naturally QUEUE-UP IN-MEMORY (not a concern) until the delay has
    // passed and the remote-scripts have been loaded. In this case, we're not even
    // going to load the remote-scripts until they are requested FOR THE FIRST TIME.
    // Then, we will use they given delay, after which the in-memory queue will get
    // flushed automatically - Promises rock!!
    this.scriptPromise = this.delay( this.delayInMilliseconds )
        .then(
            () => {

                var scriptPromises = this.urls.map(
                    ( url ) => {

                        return( this.loadScript( url ) );

                    }
                );

                return( Promise.all( scriptPromises ) );

            }
        )
        .then(
            () => {

                // No-op to generate a Promise<void> from the Promise<Any[]>.

            }
        )
    ;

    return( this.scriptPromise );

}

// ---
// PRIVATE METHODS.
// ---

// I return a Promise that resolves after the given delay.
private delay( delayInMilliseconds: number ) : Promise<any> {

    var promise = new Promise(
        ( resolve ) => {

            setTimeout( resolve, delayInMilliseconds );

        }
    );

    return( promise );

}


// I inject a Script tag with the given URL into the head. Returns a Promise.
private loadScript( url: string ) : Promise<any> {

    var promise = new Promise(
        ( resolve, reject ) => {

            var commentNode = document.createComment( " Script injected via DelayedScriptLoader. " );

            var scriptNode = document.createElement( "script" );
            scriptNode.type = "text/javascript";
            scriptNode.onload = resolve;
            scriptNode.onerror = reject;
            scriptNode.src = url;

            document.head.appendChild( commentNode );
            document.head.appendChild( scriptNode );

        }
    );

    return( promise );

}
}

下面是使用此服务的组件:

// Import the core angular services.
import { Component } from "@angular/core";

// Import the application components and services.
import { AnalyticsService } from "./analytics.service";

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

@Component({
    selector: "my-app",
    styleUrls: [ "./app.component.less" ],
    template:
    `
        <p>
            <a (click)="doThis()">Do This</a>
            &mdash;
            <a (click)="doThat()">Do That</a>
        </p>
    `
})
export class AppComponent {

    private analyticsService: AnalyticsService;

    // I initialize the app component.
    constructor( analyticsService: AnalyticsService ) {

        this.analyticsService = analyticsService;

    }

    // ---
    // PUBLIC METHODS.
    // ---

    // I execute an action (that we're going to track).
    public doThat() : void {

        this.analyticsService.track(
            "do.that",
            {
                now: Date.now()
            }
        );

    }


    // I execute an action (that we're going to track).
    public doThis() : void {

        this.analyticsService.track(
            "do.this",
            {
                now: Date.now()
            }
        );

    }


    // I get called once after the inputs have been bound for the first time.
    public ngOnInit() : void {

        this.analyticsService.identify(
            "bennadel",
            {
                group: "admin"
            }
        );

    }

}

当你说懒负载时,你会怎么想?延迟加载通常是一个用于图像的术语,因此它仅在您滚动到该内容时加载图像。但是,应该在页面加载后立即加载脚本,可以采用阻塞方式,也可以采用延迟或异步方式。您希望何时加载脚本?GTM google tag manager会减慢绘制时间。因此,我只想在我的angular应用程序初始加载后激活GTM。这样做有什么区别?Assert文件夹包含图像和其他资产文件,以便在构建应用程序时复制。通过这种方式,您可以像在普通html中一样添加这些脚本,并且在编译过程中不会出现问题谢谢您的回答,但它如何帮助我减少第一次这样做的痛苦呢?因为我希望我的应用程序视图在激活GTM之前已初始化。请尝试在index.html正文的最后一行添加脚本。这将首先加载您的视图,然后GTMBE在询问我在这里看到他们的博客之前,它可能会起作用。我会小心的。也许是正确的答案让我们看看。非常感谢。
// Import the core angular services.
import { Component } from "@angular/core";

// Import the application components and services.
import { AnalyticsService } from "./analytics.service";

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

@Component({
    selector: "my-app",
    styleUrls: [ "./app.component.less" ],
    template:
    `
        <p>
            <a (click)="doThis()">Do This</a>
            &mdash;
            <a (click)="doThat()">Do That</a>
        </p>
    `
})
export class AppComponent {

    private analyticsService: AnalyticsService;

    // I initialize the app component.
    constructor( analyticsService: AnalyticsService ) {

        this.analyticsService = analyticsService;

    }

    // ---
    // PUBLIC METHODS.
    // ---

    // I execute an action (that we're going to track).
    public doThat() : void {

        this.analyticsService.track(
            "do.that",
            {
                now: Date.now()
            }
        );

    }


    // I execute an action (that we're going to track).
    public doThis() : void {

        this.analyticsService.track(
            "do.this",
            {
                now: Date.now()
            }
        );

    }


    // I get called once after the inputs have been bound for the first time.
    public ngOnInit() : void {

        this.analyticsService.identify(
            "bennadel",
            {
                group: "admin"
            }
        );

    }

}