How to download only Zone.js when necessary

I am creating an Angular 2 application that can be dynamically injected into a live website. The purpose of this application is to visually modify the contents of the website.

Everything works as expected when this website doesn’t work well with Angular 2. In particular, when the original website uses Angular 2 and Zone.js, my application also tries to download Zone.js, but it crashes on error: Zone already loaded. I use Webpack as a build system, and I have tried to solve the problem by dividing the assembly into 3 parts: manifest, polyfilland app. The manifest contains only the Webpack manifest, the polyfill contains core-jsand zone.js, and the rest is in app. There is also a fourth fragment called index. This is the one that is posted on the website and it first checks to see if it is defined window.Zone. If so, only manifestand are added app. Otherwise also polyfill.

The problem is that when the block is polyfillnot loaded, all modules in this fragment are absent in Webpack. Therefore, when the code reaches some importof the block appthat requires either core-js, or zone.js(which, I think, happens), I get this error:

TypeError: Cannot read property 'call' of undefined
    at __webpack_require__ (manifest.js:55)
    at Object.<anonymous> (app.js:15016)
    at __webpack_require__ (manifest.js:55)
    at Object.<anonymous> (app.js:65567)
    at __webpack_require__ (manifest.js:55)
    at Object.<anonymous> (app.js:65163)
    at __webpack_require__ (manifest.js:55)
    at Object.defineProperty.value (app.js:65137)
    at __webpack_require__ (manifest.js:55)
    at webpackJsonpCallback (manifest.js:26)

Somewhere in the manifest file:

/******/   // Execute the module function
/******/   modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

Question

How to configure Webpack or Angular so as not to import zone.jsas dependencies, but use the one that is already registered in the window? I want to be able to conditionally download core-jsand zone.jsonly if it is not already uploaded to the website.

UPDATE

I changed my assembly (Webpack) to use only one package. In this package, I tried using Webpack dynamic import as follows:

// import reflect metadata shim
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';


// Angular and application imports
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
import { ViewEncapsulation } from '@angular/core';


// load the editor in the next frame
requestAnimationFrame(() => {

    if (window.Zone) {
        bootstrap();
    }
    else {
        import('zone.js/dist/zone') // <-- PROBLEM HERE
            .then(bootstrap);
    }

});


// bootstraps the editor
function bootstrap() {

    // add the root component to the DOM
    const root = document.createElement('efe-root');
    document.body.appendChild(root);

    // bootstrap the Angular app
    platformBrowserDynamic()
        .bootstrapModule(AppModule, {
            defaultEncapsulation: ViewEncapsulation.Native
        })
        .then(() => console.debug('Exponea Free Editor has bootstrapped'));

}

Typescript, . , zone.js , , . ?

+4
2

zone.js , polyfills.ts:

import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';  <---- remove this line

zone.js , :

declare var System;
if (!window['Zone']) {
    System.import('zone.js/dist/zone');  // Included with Angular CLI.
}
+3

commonjs/webpack systemjs build run system

systemjs , .

, , , , , systemjs .

0

Source: https://habr.com/ru/post/1683949/


All Articles