javascript - कोणीय सीएलआई और कोणीय 5 के साथ रन-टाइम में नए मॉड्यूल लोड करें




angular webpack (4)

वर्तमान में मैं एक प्रोजेक्ट पर काम कर रहा हूं, जो क्लाइंट सर्वर पर होस्ट किया जा रहा है। नए 'मॉड्यूल' के लिए पूरे एप्लिकेशन को फिर से जोड़ने का कोई इरादा नहीं है । उस ग्राहक ने कहा, ग्राहक राउटर / आलसी लोडेड मॉड्यूल्स को रनटाइम में अपडेट करना चाहता है । मैंने कई चीजों की कोशिश की है, लेकिन मैं इसे काम नहीं कर सकता। मैं सोच रहा था कि क्या आप में से कोई भी जानता है कि मैं अभी भी क्या कोशिश कर सकता हूं या क्या याद किया।

एक बात जिस पर मैंने गौर किया, अधिकांश संसाधन मैंने कोशिश की, कोणीय क्ली का उपयोग करते हुए, अनुप्रयोग बनाते समय वेबपैक द्वारा अलग-अलग भाग में बांधा जा रहा है। जो तर्कसंगत लगता है क्योंकि यह वेबपैक कोड विभाजन का उपयोग करता है। लेकिन क्या होगा यदि मॉड्यूल संकलन समय पर अभी तक ज्ञात नहीं है (लेकिन एक संकलित मॉड्यूल किसी सर्वर पर कहीं संग्रहीत है)? बंडलिंग काम नहीं करता है क्योंकि यह आयात करने के लिए मॉड्यूल नहीं ढूंढ सकता है। और जब भी सिस्टम पर पाया जाता है सिस्टमजेएस यूएमडी मॉड्यूल का उपयोग करेगा, लेकिन वेबपैक द्वारा एक अलग चंक में बंडल किया जाता है।

कुछ संसाधन जो मैंने पहले ही आज़मा लिए थे;

कुछ कोड जो मैंने पहले ही आजमाए और लागू किए, लेकिन इस समय काम नहीं कर रहे हैं;

सामान्य मॉड्यूल.ts फ़ाइल के साथ राउटर का विस्तार

     this.router.config.push({
    path: "external",
    loadChildren: () =>
      System.import("./module/external.module").then(
        module => module["ExternalModule"],
        () => {
          throw { loadChunkError: true };
        }
      )
  });

UMD बंडल के सामान्य SystemJS आयात

System.import("./external/bundles/external.umd.js").then(modules => {
  console.log(modules);
  this.compiler.compileModuleAndAllComponentsAsync(modules['External']).then(compiled => {
    const m = compiled.ngModuleFactory.create(this.injector);
    const factory = compiled.componentFactories[0];
    const cmp = factory.create(this.injector, [], null, m);

    });
});

बाहरी मॉड्यूल आयात करें, वेबपैक के साथ काम न करें (afaik)

const url = 'https://gist.githubusercontent.com/dianadujing/a7bbbf191349182e1d459286dba0282f/raw/c23281f8c5fabb10ab9d144489316919e4233d11/app.module.ts';
const importer = (url:any) => Observable.fromPromise(System.import(url));
console.log('importer:', importer);
importer(url)
  .subscribe((modules) => {
    console.log('modules:', modules, modules['AppModule']);
    this.cfr = this.compiler.compileModuleAndAllComponentsSync(modules['AppModule']);
    console.log(this.cfr,',', this.cfr.componentFactories[0]);
    this.external.createComponent(this.cfr.componentFactories[0], 0);
});

SystemJsNgModuleLoader का उपयोग करें

this.loader.load('app/lazy/lazy.module#LazyModule').then((moduleFactory: NgModuleFactory<any>) => {
  console.log(moduleFactory);
  const entryComponent = (<any>moduleFactory.moduleType).entry;
  const moduleRef = moduleFactory.create(this.injector);

  const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
});

रोलअप के साथ बनाए गए मॉड्यूल को लोड करने की कोशिश की

this.http.get(`./myplugin/${metadataFileName}`)
  .map(res => res.json())
  .map((metadata: PluginMetadata) => {

    // create the element to load in the module and factories
    const script = document.createElement('script');
    script.src = `./myplugin/${factoryFileName}`;

    script.onload = () => {
      //rollup builds the bundle so it's attached to the window object when loaded in
      const moduleFactory: NgModuleFactory<any> = window[metadata.name][metadata.moduleName + factorySuffix];
      const moduleRef = moduleFactory.create(this.injector);

      //use the entry point token to grab the component type that we should be rendering
      const compType = moduleRef.injector.get(pluginEntryPointToken);
      const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(compType); 
// Works perfectly in debug, but when building for production it returns an error 'cannot find name Component of undefined' 
// Not getting it to work with the router module.
    }

    document.head.appendChild(script);

  }).subscribe();

SystemJsNgModuleLoader के साथ उदाहरण केवल तब काम करता है जब एप्लिकेशन के राउटरमॉड्यूल में मॉड्यूल पहले से ही 'आलसी' मार्ग के रूप में प्रदान किया जाता है (जो वेबपैक के साथ निर्मित होने पर इसे एक चंक में बदल देता है)

मुझे इस विषय पर StackOverflow पर यहाँ और वहाँ बहुत चर्चा मिली और बशर्ते समाधान लोडिंग मॉड्यूल / घटकों के गतिशील रूप से अच्छे लगते हों यदि सामने वाले को पता हो। लेकिन कोई भी परियोजना के हमारे उपयोग के मामले के लिए उपयुक्त नहीं है। कृपया मुझे बताएं कि मैं अभी भी क्या प्रयास कर सकता हूं या गोता लगा सकता हूं।

धन्यवाद!

संपादित करें: मैंने पाया है; https://github.com/kirjs/angular-dynamic-module-loading और इसे आज़माएँगे।

अद्यतन करें: मैंने; SystemJS (और कोणीय 6 का उपयोग करके) गतिशील रूप से लोड करने वाले मॉड्यूल के उदाहरण के साथ एक भंडार बनाया; https://github.com/lmeijdam/angular-umd-dynamic-example


इसे कोणीय 6 लाइब्रेरी के साथ करें और रोलअप ट्रिक करें। मैंने अभी इसके साथ प्रयोग किया है और मैं पिछले पुनर्निर्माण के बिना मुख्य ऐप के साथ स्टैंडअलोन कोणीय एओटी मॉड्यूल साझा कर सकता हूं।

  1. कोणीय पुस्तकालय में angularCompilerOptions.skipTemplateCodegen को गलत पर सेट करें और लाइब्रेरी बनाने के बाद आपको मॉड्यूल कारखाना मिलेगा।
  2. उसके बाद इस तरह रोलअप के साथ एक umd मॉड्यूल बनाएँ: rollup dist/plugin/esm2015/lib/plugin.module.ngfactory.js --file src/assets/plugin.module.umd.js --format umd --name plugin
  3. मुख्य स्रोत ऐप में टेक्स्ट सोर्स umd बंडल लोड करें और इसे मॉड्यूल संदर्भ के साथ विकसित करें
  4. अब आप निर्यात वस्तु से ModuleFactory तक पहुंच सकते हैं

यहाँ https://github.com/iwnow/angular-plugin-example आप पा सकते हैं कि स्टैंडअलोन बिल्डिंग और एओटी के साथ प्लगइन कैसे विकसित करें


मेरा मानना ​​है कि यदि आप वेबपैक का उपयोग करके अपने मुख्य एप्लिकेशन को बनाते हैं और चलाते हैं तो UMD बंडल लोड करने के लिए SystemJS का उपयोग करना संभव है। मैंने एक समाधान का उपयोग किया जो डायनेमिक प्लगइन / एडऑन मॉड्यूल के यूएमडी बंडल बनाने के लिए एनजी-पैकाग्रा का उपयोग करता है। यह गीथब वर्णित प्रक्रिया को प्रदर्शित करता है: https://github.com/nmarra/dynamic-module-loading


मैंने Github पर साझा किए गए एप्लिकेशन को बनाने के लिए Angular 6 के लाइब्रेरी समर्थन के साथ https://github.com/kirjs/angular-dynamic-module-loading समाधान का उपयोग किया है। कंपनी की नीति के कारण इसे ऑफ़लाइन लेने की आवश्यकता थी। जैसे ही उदाहरण परियोजना स्रोत के बारे में चर्चा खत्म होगी मैं इसे गीथूब पर साझा करूंगा!

अद्यतन: रेपो पाया जा सकता है; https://github.com/lmeijdam/angular-umd-dynamic-example


मैंने एंगुलर 6 में परीक्षण किया है, बाहरी पैकेज या आंतरिक मॉड्यूल से मॉड्यूल को लोड करने के लिए समाधान काम करता है।

1. यदि आप किसी लाइब्रेरी प्रोजेक्ट या पैकेज से गतिशील रूप से लोड करना चाहते हैं:

मेरे पास एक लाइब्रेरी प्रोजेक्ट "एडमिन" है (या आप एक पैकेज का उपयोग कर सकते हैं) और एक एप्लीकेशन प्रोजेक्ट "ऐप"। मेरे "व्यवस्थापक" लाइब्रेरी प्रोजेक्ट में, मेरे पास AdminModule और AdminRoutModule है। मेरे "ऐप" प्रोजेक्ट में:

ए। Tsconfig.app.json में परिवर्तन करें:

  "compilerOptions": {
    "module": "esNext",
  },

ख। एप्लिकेशन- routing.module.ts में:

const routes: Routes = [
    {
        path: 'admin',
        loadChildren: async () => {
            const a = await import('admin')
            return a['AdminModule'];
        }
    },
    {
        path: '',
        redirectTo: '',
        pathMatch: 'full'
    }
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule {
}

2. यदि आप एक ही परियोजना से एक मॉड्यूल लोड करना चाहते हैं।

4 अलग-अलग विकल्प हैं:

ए। एप्लिकेशन- routing.module.ts में:

const routes: Routes = [
    {
        path: 'example',
        /* Options 1: Use component */
        // component: ExampleComponent,  // Load router from component
        /* Options 2: Use Angular default lazy load syntax */
        loadChildren: './example/example.module#ExampleModule',  // lazy load router from module
        /* Options 3: Use Module */
        // loadChildren: () => ExampleModule, // load router from module
        /* Options 4: Use esNext, you need to change tsconfig.app.json */
        /*
        loadChildren: async () => {
            const a = await import('./example/example.module')
            return a['ExampleModule'];
        }
        */
    },
    {
        path: '',
        redirectTo: '',
        pathMatch: 'full'
    }
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule {
}
``






angular5