Coder Social home page Coder Social logo

mohammedzamakhan / ngx-loadable Goto Github PK

View Code? Open in Web Editor NEW
166.0 3.0 22.0 6.97 MB

⏳ Simple Lazy Loading for Non Routable Angular Modules

Home Page: https://mohammedzamakhan.github.io/ngx-loadable/

License: MIT License

JavaScript 1.30% TypeScript 73.72% HTML 18.00% CSS 6.98%

ngx-loadable's Introduction

ngx-loadable

All Contributors

npm license size

ngx-loadable logo The library logo represents faster application like speed of wind

Table of Contents

Problem

Angular provides an easy way for adding route based lazy loading modules. But in most of the projects, each route tends to have a lot of different components. It could be because of lots of modals, tabs, and components that appear based on user interaction in a single route.

Solution

The ngx-loadable wraps the complex implementation for lazy loading non routable modules in a simple API. It provides a component ngx-loadable and a service LoadableService to lazy load modules. A component can be used to control the loading of one module and to display different states, i.e. loading, error, timedOut and loaded.

Install

Install and manage the ngx-loadable using NPM. You may use yarn or npm.

npm install ngx-loadable --save

or

yarn add ngx-loadable

Usage

NgModule

Import the LoadableModule in the NgModule and declare them in the "imports", you can also use the forRoot() for forChild() function.

  • Step 1:
import { LoadableModule } from 'ngx-loadable';

@NgModule({
  imports: [
    LoadableModule
  ]
})
  • Step 2: Create a Module with a Component bootstrapped to the Module

  • Step 3: Include the module path in the lazyModules array in angular.json file, for it to be created as a lazy module by Angular CLI

  • Step 4: Use the ngx-loadable component

<button (click)="show = true" (mouseenter)="loginModalModule.preload()">
    Preload on mouseenter and show on click
</button>
<ngx-loadable
    #loginModalModule
    [module]="'login-modal'"
    [show]="show"
    [timeout]="1000"
>
    <div loading>Loading...</div>
    <div error>Error</div>
    <div timedOut>
        TimedOut!
        <button (click)="loginModalModule.reload()">
            Reload
        </button>
    </div>
</ngx-loadable>

or use the LoadableService

import { LoadableService } from 'ngx-loadable';
...
class YourComponent {
    contructor(private loadableService: LoadableService) { }
    load() {
        this.loadableService.preload('lazy')
            .then(() => console.log('loaded'))
            .catch((error) => console.error(error));
        }
    }
}

Contribute

Contribution guidelines for this project

License

© 2019 ngx-loadable. All Rights Reserved.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Zama Khan Mohammed
Zama Khan Mohammed

💻 🎨 💡 📖 🤔 🚇
rumanhassan
rumanhassan

🤔 💻 🔧
aijazkhan81
aijazkhan81

🖋
Aditya Menon
Aditya Menon

📖
David Würfel
David Würfel

🐛
Michael Reeves
Michael Reeves

📖
siddharthpal
siddharthpal

🐛

This project follows the all-contributors specification. Contributions of any kind welcome!

ngx-loadable's People

Contributors

m-aditya avatar mohammedzamakhan avatar reevmich avatar rumanhassan avatar siddharthpal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ngx-loadable's Issues

Passing data to lazily loaded component

Hi @mohammedzamakhan, thanks for the awesome work!

I want to pass data to the lazily loaded component from the parent component.
Currently, I am using a service to share the data to the lazily loaded component as a workaround.

Is it possible to accomplish this with a simple mechanism like @Input decorator?

Thanks

Loadable config missing "fileMappings" in version 2.x.x

Hi there!
I'm trying to update ngx-loadable from version 1.1.1 to version 2.1.1 but I'm getting some errors regarding forRoot configuration.
With version 1.1.1 I used "fileMappings" and everything worked fine for me...

LoadableModule.forRoot({
fileMappings: {
footer: 'src/app/features/layout-root/footer/footer.module#FooterModule',
(...)
}
})

...but with version 2.x.x it is not possible to use "fileMappings" anymore.
Unfortunately, I cannot find any documentation to understand how to replace it.
Can you help me, please?

Here is the angular version I'm using at the moment:

Angular CLI: 8.3.23
Node: 10.16.0
OS: win32 x64
Angular: 8.2.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router, service-worker

Package Version

@angular-devkit/architect 0.803.23
@angular-devkit/build-angular 0.803.23
@angular-devkit/build-optimizer 0.803.23
@angular-devkit/build-webpack 0.803.23
@angular-devkit/core 8.3.23
@angular-devkit/schematics 8.3.23
@angular/cdk 8.2.3
@angular/cli 8.3.23
@angular/material 8.2.3
@angular/pwa 0.8.9
@ngtools/webpack 8.3.23
@schematics/angular 0.8.9
@schematics/update 0.803.23
rxjs 6.5.4
typescript 3.5.3
webpack 4.39.2

Thanks,
Carlos Escribano

Lazy load third party modules

Hi,
Is there a way to use this library to lazy load a third party module coming from npm?
An example can be ngx-quill that is a wrapper of the famous quill editor.
How can I lazy load the quill editor component declared in Quill module? (that coming from a library?)

ngx-loadable and NG10

Does ngx-loadable support NG10?
I tried to use it in my project (I used your simple exmaple) and it failed
(the modules array in LoadableService is empty, which caused preload & getModule to fail).

Add example for pre ivy

Hi @mohammedzamakhan

Thanks for such a cool library. angular/core used in the demo app is for the Ivy engine. Can we add an example for pre-Ivy compiler which would work with Angular 7? If there isn't any repo I can create it and try ngx-loadable with Angular 7.

Please let me know if there is any change in using ngx-loadble for view engine?

ModuleConfig was previously added, it will not be added multiple times

Hi

I updated ngx-loadable to version 2.1.1 because Iupdated our app to angular 8.

What we did in our code in previous version (angular 7.2.5 and ngx-loadable version 1.0.10) was:


"lazyModules": [
              "src/app/features/layout-root/footer/footer.module",
...
...
...
            ]

Then in our core.module:


import { lazyloadFilemappings } from 'app/config/lazyload-filemappings';

LoadableModule.forRoot({
      fileMappings: lazyloadFilemappings
    })

where
lazyload-filemappings.ts is:


export const lazyloadFilemappings = {
  'footer': 'src/app/features/layout-root/footer/footer.module#FooterModule',
...
...
...

After updating to v.2.1.1 fileMappings property is no more available. I read that configuration is different.

I think this is the right configuration now:


LoadableModule.forRoot({
      moduleConfigs: [{
        name: 'footer',
        loadChildren: () => import("../features/layout-root/footer/footer.module").then(mod=> mod.FooterModule),
        matcher
      }]
    })

so I used that in core.module

When I run app I get this warning:
ngx-loadable - ModuleConfig with name 'footer' was previously added, it will not be added multiple times, continue...
Cattura1

I get this warning multiple times and it continues to infinite and the app is blocked.

Why this happens?
What's wrong?
I also tried to remove "lazyModules" from angular,json without luck.

If I use only LoadableModule in core.module then I get error:
TypeError: "this.options is null" on this line:
<ngx-loadable [show]="true" [module]="'footer'">

and naturally footer is not loaded

Thanks for your help

Angular 13 support

After updating my app to Angular 13 I got the following issues.

Error: node_modules/ngx-loadable/lib/loadable.service.d.ts:1:43 - error TS2305: Module '"@angular/core"' has no exported member 'NgModuleFactoryLoader'.

Warning when starting Angular build

Recently I get the following warning when ever I build my Angular app that includes ngx-loadable:

Warning: Entry point 'ngx-loadable' contains deep imports into '/app/node_modules/@angular/compiler/src/core'. This is probably not a problem, but may cause the compilation of entry points to be out of order.

I've made this pull request: #37 which should address the issues

Lazily loading module doesn't load up module specific configuration

Here's my lazy module:

export function createTranslateLoader(http: HttpClient) {
  console.log('loading translate module');
  return new TranslateHttpLoader(http, './assets/i18n/product/', '.json?cb=' + new Date().getTime());
}

@NgModule({
  declarations: [
    LandingComponent
  ],
  bootstrap: [LandingComponent],
  entryComponents: [
    RoomModalComponent
  ],
  imports: [
    SharedModule,
    TranslateModule.forChild({
      loader: {
        provide: TranslateLoader,
        useFactory: (createTranslateLoader),
        deps: [HttpClient]
      },
      isolate: true,
      missingTranslationHandler: {provide: MissingTranslationHandler, useClass: MyMissingTranslationHandler}
    })
  ],
  exports: []
})
export class ProductModule { }

When the module is loaded, it correctly shows the bootstrapped component. However, it fails to load ngx-translate (https://medium.com/@TuiZ/how-to-split-your-i18n-file-per-lazy-loaded-module-with-ngx-translate-3caef57a738f) and it doesn't register the entryComponent so when I try to open the modal using Angular Material Dialog it gives me the error:

VM1195 polyfills.js:2557 Uncaught Error: No component factory found for RoomModalComponent. Did you add it to @NgModule.entryComponents?

Thoughts?

Exemple for version 2.1.1

Trying to use your package and I'm facing some issue to use it.

I've tried multiple ways to make it work without success...

LoadableModule.forFeature({
      moduleConfigs: [{
        name: 'suggested-company-sidebar',
        matcher: () => import("src/app/shared/suggested-company-sidebar.module").then(mod=> mod.SuggestedCompanySidebarModule)
      }]),

matcher is required and on the demo, we should use load while in this newer version it is not present.

Then I tried in the component.ts (without the config above)

this.loadableService.preload('suggested-company-sidebar')
        .then(() => console.log('loaded'))
        .catch((error) => console.error(error));

I get the following error :

loadChildren is not a function
at LoadableService.preload (ngx-loadable.js:83)

When I don't set a config in the module or called preload from the component, I'm getting the following error

Cannot read property 'loadingComponent' of null
    at LoadableComponent.loadFn (ngx-loadable.js:266)

the html code look like this

<ngx-loadable #suggestedCompanySidebar
                    [module]="'suggested-company-sidebar'"
                    [show]="suggestedCompanyDisplay"
                    [timeout]="1000">
        <div loading>Loading...</div>
        <div error>Error</div>
        <div timedOut>
          TimedOut!
          <button (click)="suggestedCompanySidebar.reload()">
            Reload
          </button>
        </div>
      </ngx-loadable>

I'm kind of lost with your package.

PS : I'm using ngx-loadable from a lazy module defined with loadChildren in app-routing.module.ts

Also, I will like to know if the content will be displayed at the server level (SSR) as I want to lazy load components of my page to speed up the loading time of the app nevertheless I still need that the full page content to be crawled by Google Bot when it call the server (SSR)

Thanks in advance for your replu

How to transitition from HeroLoader/Lazy-af to ngx-loadable ?

My currentProject has already 10+ entries in angular.json -> lazyModules

they all have the form:
"src/app/lazyModules/<HASH-VALUE>/m1.module"
(they are all called m1.module)

I will not regenerate them all with scematics so this approach
<ngx-loadable module="m1" [show]="show"></ngx-loadable>
will not work (I believe).

Because of backend validation I cannot change my naming convention.

It looks like I have to go for "magic strings". How can I port my old modules and continue with scematics for the new ones?

Is there a way I can keep my naming conventions?

Lazy load a whole library with nrwl/NX.

Hi, I have created a project using nrwl/nx extention of angular CLI (https://github.com/nrwl/nx).
I want to add a whole library as a lazy loading module following are my angular and tsconfig json files

`{
"version": 1,
"projects": {
"lazy-load-demo": {
"projectType": "application",
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
},
"root": "apps/lazy-load-demo",
"sourceRoot": "apps/lazy-load-demo/src",
"prefix": "lazy-load-demo",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/apps/lazy-load-demo",
"index": "apps/lazy-load-demo/src/index.html",
"main": "apps/lazy-load-demo/src/main.ts",
"polyfills": "apps/lazy-load-demo/src/polyfills.ts",
"tsConfig": "apps/lazy-load-demo/tsconfig.app.json",
"aot": false,
"assets": [
"apps/lazy-load-demo/src/favicon.ico",
"apps/lazy-load-demo/src/assets"
],
"styles": ["apps/lazy-load-demo/src/styles.scss"],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/lazy-load-demo/src/environments/environment.ts",
"with": "apps/lazy-load-demo/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "lazy-load-demo:build"
},
"configurations": {
"production": {
"browserTarget": "lazy-load-demo:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "lazy-load-demo:build"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"apps/lazy-load-demo/tsconfig.app.json",
"apps/lazy-load-demo/tsconfig.spec.json"
],
"exclude": ["/node_modules/", "!apps/lazy-load-demo/"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/lazy-load-demo/jest.config.js",
"tsConfig": "apps/lazy-load-demo/tsconfig.spec.json",
"setupFile": "apps/lazy-load-demo/src/test-setup.ts"
}
}
}
},
"lazy-load-demo-e2e": {
"root": "apps/lazy-load-demo-e2e",
"sourceRoot": "apps/lazy-load-demo-e2e/src",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/lazy-load-demo-e2e/cypress.json",
"tsConfig": "apps/lazy-load-demo-e2e/tsconfig.e2e.json",
"devServerTarget": "lazy-load-demo:serve"
},
"configurations": {
"production": {
"devServerTarget": "lazy-load-demo:serve:production"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["apps/lazy-load-demo-e2e/tsconfig.e2e.json"],
"exclude": ["
/node_modules/", "!apps/lazy-load-demo-e2e/"]
}
}
}
}

},
"lazy-load-coponent": {
"projectType": "library",
"root": "libs/lazy-load-coponent",
"sourceRoot": "libs/lazy-load-coponent/src",
"prefix": "lazy-load-demo",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/lazy-load-coponent/tsconfig.lib.json",
"libs/lazy-load-coponent/tsconfig.spec.json"
],
"exclude": ["/node_modules/", "!libs/lazy-load-coponent/**"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/lazy-load-coponent/jest.config.js",
"tsConfig": "libs/lazy-load-coponent/tsconfig.spec.json",
"setupFile": "libs/lazy-load-coponent/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"styleext": "scss"
}
}
}
},
"cli": {
"defaultCollection": "@nrwl/angular"
},
"schematics": {
"@nrwl/angular:application": {
"unitTestRunner": "jest",
"e2eTestRunner": "cypress"
},
"@nrwl/angular:library": {
"unitTestRunner": "jest"
}
},
"defaultProject": "lazy-load-demo"
}
`
and tsconfig file

{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "esnext",
"typeRoots": ["node_modules/@types"],
"lib": ["es2017", "dom"],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@lazy-load-demo/lazy-load-coponent": [
"libs/lazy-load-coponent/src/index.ts"
]
}
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "tmp"]
}

While building the project the individual chunk gets created successfully but afterwards, I am
getting an error

ERROR in D:/Projects/Internal/lazy-load-demo1/libs/lazy-load-coponent/src/lib/lazy-load-coponent.module.ts Module build failed (from lazy-load-demo1/node_modules/@ngtools/webpack/src/index.js): Error: lazy-load-demo1\libs\lazy-load-coponent\src\lib\lazy-load-coponent.module.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' propError: lazy-load-demo1\libs\lazy-load-coponent\src\lib\lazy-load-coponent.module.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property. at AngularCompilerPlugin.getCompiledFile (lazy-load-demo1\node_modules\@ngtools\webpack\src\angular_compiler_plugin.js:838:23) at plugin.done.then (lazy-load-demo1\node_modules\@ngtools\webpack\src\loader.js:41:31) at process._tickCallback (internal/process/next_tick.js:68:7)

Is there any way to solve this error?

Load lazy modules on remote server

Hi

I am developing consumable web components that are meant to live on external sites. They will include a single javascript file from our site to be able to use our components.

If I make some of the code modular and it gets time to load one of these modules on their site and the modules don't live locally on their server, how will ngx-loadable know to go to my CDN to load the module from?

Thank you
Bjorn

Error on pre-loading modules

When i try to preload a module after following all the steps.
this.loadableService.preload('item-details') .then(() => console.log('loaded')) .catch((error) => console.error(error));

Getting the below error.please help

Uncaught Error: Uncaught (in promise): TypeError: Cannot read property 'load' of undefined TypeError: Cannot read property 'load' of undefined at LoadableService.preload (:4200/vendor.js:215402) at new SingleOrderComponent (single-order-single-order-module.js:395) at createClass (:4200/vendor.js:96210) at createDirectiveInstance (:4200/vendor.js:96019) at createViewNodes (:4200/vendor.js:107299) at createRootView (:4200/vendor.js:107171) at Object.createProdRootView [as createRootView] (:4200/vendor.js:107919) at ComponentFactory_.create (:4200/vendor.js:95153) at ComponentFactoryBoundToModule.create (:4200/vendor.js:91588) at ViewContainerRef_.createComponent (:4200/vendor.js:95311) at resolvePromise (:4200/polyfills.js:7219) at resolvePromise (:4200/polyfills.js:7178) at :4200/polyfills.js:7280 at ZoneDelegate.invokeTask (:4200/polyfills.js:6826) at Object.onInvokeTask (:4200/vendor.js:103085) at ZoneDelegate.invokeTask (:4200/polyfills.js:6825) at Zone.runTask (:4200/polyfills.js:6594) at drainMicroTaskQueue (:4200/polyfills.js:6996)

Cannot find module 'src/app/product/product.module'

Hi @mohammedzamakhan!

Thank you for writing this. Very handy indeed :-)

Angular CLI: 7.3.6
Node: 11.12.0
OS: darwin x64
Angular: 7.2.10
... animations, common, compiler, compiler-cli, core, elements
... forms, http, language-service, platform-browser
... platform-browser-dynamic, router, service-worker

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.13.6
@angular-devkit/build-angular      0.13.6
@angular-devkit/build-ng-packagr   0.13.6
@angular-devkit/build-optimizer    0.13.6
@angular-devkit/build-webpack      0.13.6
@angular-devkit/core               7.3.6
@angular-devkit/schematics         7.3.6
@angular/cdk                       7.3.5
@angular/cli                       7.3.6
@angular/flex-layout               7.0.0-beta.24
@angular/material                  7.3.5
@angular/pwa                       0.13.6
@ngtools/json-schema               1.1.0
@ngtools/webpack                   7.3.6
@schematics/angular                7.3.6
@schematics/update                 0.13.6
ng-packagr                         4.7.1
rxjs                               6.4.0
typescript                         3.2.4
webpack                            4.29.0

Here's my module:

import {NgModule} from '@angular/core';
import {LandingComponent} from './landing/landing.component';
import {SharedModule} from '../shared/shared.module';

@NgModule({
  declarations: [LandingComponent],
  bootstrap: [LandingComponent],
  imports: [
    SharedModule
  ]
})
export class ProductModule { }

I followed your instructions. I registered a lazyModule in my project under options:

"lazyModules": [
  "projects/booking-engine/src/app/product/product.module"
]

I loaded the module like so:

LoadableModule.forRoot({
      appDir: 'src/app/',
      fileMappings: {
        product: 'src/app/product/product.module#ProductModule'
      }
    })

I tried to load the module using your directive and your service but both return an error.
Cannot find module 'src/app/product/product.module'

FYI My project is a web component using Angular Elements.

Please let me know your thoughts.

ILoadableRootConfig not exported through public api

Current behavior

The ILoadableRootConfig is not exported through public api.

When you import it you end with a nested path:

import { ILoadableRootConfig } from 'ngx-loadable/lib/loadable.config';

##Expected behavior

You should be able to get ILoadableRootConfig like:

import { ILoadableRootConfig } from 'ngx-loadable/lib/loadable.config';

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.