├── .gitignore ├── CHANGELOG.md ├── README.md ├── docs └── options.md ├── package.json ├── spec ├── index.spec.js └── utils.spec.js └── src ├── index.js └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [0.8.3](https://github.com/brandonroberts/angular-router-loader/compare/v0.8.2...v0.8.3) (2018-04-05) 3 | 4 | 5 | 6 | 7 | ## [0.8.2](https://github.com/brandonroberts/angular-router-loader/compare/v0.8.1...v0.8.2) (2018-01-03) 8 | 9 | 10 | 11 | 12 | ## [0.8.1](https://github.com/brandonroberts/angular-router-loader/compare/v0.8.0...v0.8.1) (2017-12-19) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * **utils:** Update vanilla JS require loader to be fully ES5 ([#98](https://github.com/brandonroberts/angular-router-loader/issues/98)) ([e6d9d88](https://github.com/brandonroberts/angular-router-loader/commit/e6d9d88)) 18 | 19 | 20 | 21 | 22 | # [0.8.0](https://github.com/brandonroberts/angular-router-loader/compare/v0.7.0...v0.8.0) (2017-11-17) 23 | 24 | 25 | ### Features 26 | 27 | * **loader:** Add promise rejection upon loader error ([#94](https://github.com/brandonroberts/angular-router-loader/issues/94)) ([68d89ff](https://github.com/brandonroberts/angular-router-loader/commit/68d89ff)), closes [#75](https://github.com/brandonroberts/angular-router-loader/issues/75) 28 | * **loader:** Add support for chunk name to system && import loaders ([#93](https://github.com/brandonroberts/angular-router-loader/issues/93)) ([df345fc](https://github.com/brandonroberts/angular-router-loader/commit/df345fc)) 29 | 30 | 31 | ### BREAKING CHANGES 32 | 33 | * **loader:** Webpack >= 2.4 is required for the error callback to be supported with require.ensure 34 | 35 | BEFORE: 36 | 37 | Webpack < 2.4 is supported 38 | 39 | AFTER: 40 | 41 | Webpack >= 2.4 is supported 42 | 43 | 44 | 45 | 46 | # [0.7.0](https://github.com/brandonroberts/angular-router-loader/compare/v0.6.0...v0.7.0) (2017-11-14) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **docs:** Added updated changelog ([7d1f7f3](https://github.com/brandonroberts/angular-router-loader/commit/7d1f7f3)) 52 | 53 | 54 | ### Features 55 | 56 | * **loader:** Add support for dynamic import ([#90](https://github.com/brandonroberts/angular-router-loader/issues/90)) ([a9835ab](https://github.com/brandonroberts/angular-router-loader/commit/a9835ab)) 57 | * **loader:** Update regex to be able to use double-quotes and single-quotes ([#80](https://github.com/brandonroberts/angular-router-loader/issues/80)) ([0444b6e](https://github.com/brandonroberts/angular-router-loader/commit/0444b6e)) 58 | 59 | 60 | 61 | 62 | # [0.6.0](https://github.com/brandonroberts/angular-router-loader/compare/v0.3.4...v0.6.0) (2017-03-29) 63 | 64 | 65 | ### Bug Fixes 66 | 67 | * **deps:** Updated webpack/loader-utils version to fix deprecation warning ([#61](https://github.com/brandonroberts/angular-router-loader/issues/61)) ([979ae85](https://github.com/brandonroberts/angular-router-loader/commit/979ae85)) 68 | * **docs:** Clarify `genDir` option usage ([#51](https://github.com/brandonroberts/angular-router-loader/issues/51)) ([b6f46b3](https://github.com/brandonroberts/angular-router-loader/commit/b6f46b3)) 69 | * **docs:** Fix colons in readme.md ([#36](https://github.com/brandonroberts/angular-router-loader/issues/36)) ([58db6de](https://github.com/brandonroberts/angular-router-loader/commit/58db6de)) 70 | * **loader:** Fixed bug when using query string with loadChildren ([#62](https://github.com/brandonroberts/angular-router-loader/issues/62)) ([8616eae](https://github.com/brandonroberts/angular-router-loader/commit/8616eae)) 71 | * **loader:** Prefer the query 'debug' parameter to the global value ([#37](https://github.com/brandonroberts/angular-router-loader/issues/37)) ([b96316c](https://github.com/brandonroberts/angular-router-loader/commit/b96316c)) 72 | 73 | 74 | ### Features 75 | 76 | * **loader:** Added support for plain JavaScript async require statement ([#69](https://github.com/brandonroberts/angular-router-loader/issues/69)) ([7714e1f](https://github.com/brandonroberts/angular-router-loader/commit/7714e1f)) 77 | 78 | 79 | 80 | 81 | ## [0.3.4](https://github.com/brandonroberts/angular-router-loader/compare/v0.3.2...v0.3.4) (2016-11-13) 82 | 83 | 84 | ### Bug Fixes 85 | 86 | * **loader:** Updated string matching to account for spaces in between loadChildren ([578c68b](https://github.com/brandonroberts/angular-router-loader/commit/578c68b)) 87 | 88 | 89 | ### Features 90 | 91 | * **docs:** Added example of named chunks ([#29](https://github.com/brandonroberts/angular-router-loader/issues/29)) ([4643068](https://github.com/brandonroberts/angular-router-loader/commit/4643068)) 92 | * **loader:** Added support for named chunks ([#27](https://github.com/brandonroberts/angular-router-loader/issues/27)) ([43e83a3](https://github.com/brandonroberts/angular-router-loader/commit/43e83a3)) 93 | * **loader:** Added support for non-relative paths ([28befa8](https://github.com/brandonroberts/angular-router-loader/commit/28befa8)) 94 | 95 | 96 | 97 | 98 | ## [0.3.2](https://github.com/brandonroberts/angular-router-loader/compare/v0.3.1...v0.3.2) (2016-10-09) 99 | 100 | 101 | 102 | 103 | ## [0.3.1](https://github.com/brandonroberts/angular-router-loader/compare/v0.2.2...v0.3.1) (2016-10-07) 104 | 105 | 106 | ### Bug Fixes 107 | 108 | * **loader:** Fixed files without a relative path. ([01fb92e](https://github.com/brandonroberts/angular-router-loader/commit/01fb92e)) 109 | 110 | 111 | ### Features 112 | 113 | * **loader:** Updated regex to be less greedy on finding occurrences. Added debug mode ([b821d38](https://github.com/brandonroberts/angular-router-loader/commit/b821d38)) 114 | 115 | 116 | 117 | 118 | ## [0.2.2](https://github.com/brandonroberts/angular-router-loader/compare/v0.2.1...v0.2.2) (2016-09-22) 119 | 120 | 121 | ### Features 122 | 123 | * **tests:** Added unit tests for loader ([03f828f](https://github.com/brandonroberts/angular-router-loader/commit/03f828f)) 124 | 125 | 126 | 127 | 128 | ## [0.2.1](https://github.com/brandonroberts/angular-router-loader/compare/v0.2.0...v0.2.1) (2016-09-18) 129 | 130 | 131 | ### Bug Fixes 132 | 133 | * **loader:** Fixed bug with sync loading filename ([84c8562](https://github.com/brandonroberts/angular-router-loader/commit/84c8562)) 134 | 135 | 136 | ### Features 137 | 138 | * **tests:** Added initial unit tests for loader ([824cc57](https://github.com/brandonroberts/angular-router-loader/commit/824cc57)) 139 | * **tests:** Added unit tests for util functions ([982897b](https://github.com/brandonroberts/angular-router-loader/commit/982897b)) 140 | 141 | 142 | 143 | 144 | # [0.2.0](https://github.com/brandonroberts/angular-router-loader/compare/v0.1.3...v0.2.0) (2016-09-18) 145 | 146 | 147 | ### Features 148 | 149 | * **loader:** Added option for sync module loading ([dd26e77](https://github.com/brandonroberts/angular-router-loader/commit/dd26e77)) 150 | 151 | 152 | 153 | 154 | ## [0.1.3](https://github.com/brandonroberts/angular-router-loader/compare/v0.1.2...v0.1.3) (2016-09-14) 155 | 156 | 157 | ### Bug Fixes 158 | 159 | * **windows:** Fixed file path replacement on windows ([d17ab66](https://github.com/brandonroberts/angular-router-loader/commit/d17ab66)) 160 | 161 | 162 | 163 | 164 | ## [0.1.2](https://github.com/brandonroberts/angular-router-loader/compare/v0.1.1...v0.1.2) (2016-09-14) 165 | 166 | 167 | ### Bug Fixes 168 | 169 | * **windows:** Fixed variable for replacement ([2d321ef](https://github.com/brandonroberts/angular-router-loader/commit/2d321ef)) 170 | 171 | 172 | 173 | 174 | ## [0.1.1](https://github.com/brandonroberts/angular-router-loader/compare/e630236...v0.1.1) (2016-09-14) 175 | 176 | 177 | ### Bug Fixes 178 | 179 | * **loader:** Added check for Windows OS and use appropriate path API ([e630236](https://github.com/brandonroberts/angular-router-loader/commit/e630236)) 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-router-loader 2 | 3 | [![CircleCI](https://circleci.com/gh/brandonroberts/angular-router-loader.svg?style=shield&circle-token=a8a709588d22664ab74922050eda672898d2d417)](https://circleci.com/gh/brandonroberts/angular-router-loader) 4 | [![npm version](https://badge.fury.io/js/angular-router-loader.svg)](https://badge.fury.io/js/angular-router-loader) 5 | 6 | A Webpack loader for Angular that enables string-based module loading with the `Angular Router` 7 | 8 | *Package was previously named `angular2-router-loader`* 9 | 10 | ## Installation 11 | 12 | `npm install angular-router-loader --save-dev` 13 | 14 | ## Usage 15 | 16 | Add the `angular-router-loader` to your typescript loaders 17 | 18 | **Angular Version >= 5** 19 | 20 | ```ts 21 | loaders: [ 22 | { 23 | test: /\.ts$/, 24 | loaders: [ 25 | 'awesome-typescript-loader' 26 | ] 27 | }, 28 | { 29 | test: /\.(ts|js)$/, 30 | loaders: [ 31 | 'angular-router-loader' 32 | ] 33 | } 34 | ] 35 | ``` 36 | 37 | **Angular Version < 5** 38 | 39 | ```ts 40 | loaders: [ 41 | { 42 | test: /\.ts$/, 43 | loaders: [ 44 | 'awesome-typescript-loader', 45 | 'angular-router-loader' 46 | ] 47 | } 48 | ] 49 | ``` 50 | 51 | ## Lazy Loading 52 | 53 | In your route configuration, use `loadChildren` with a relative path to your lazy loaded angular module. The string is delimited with a `#` where the right side of split is the angular module class name. 54 | 55 | ```ts 56 | import { Routes } from '@angular/router'; 57 | 58 | export const routes: Routes = [ 59 | { path: 'lazy', loadChildren: './lazy.module#LazyModule' } 60 | ]; 61 | ``` 62 | 63 | **NOTE**: When specifying a relative path to lazy loaded module, one of the following two conditions *must* hold: 64 | 65 | * The routes are defined in the same module file where it is imported with `RouterModule.forRoot` or `RouterModule.forChild` 66 | * The routes are defined in a separate routing file, and that routing file is a sibling of module file. 67 | 68 | ## Synchronous Loading 69 | 70 | For synchronous module loading, add the `sync=true` as a query string value to your `loadChildren` string. The module will be included in your bundle and not lazy-loaded. 71 | 72 | ```ts 73 | import { Routes } from '@angular/router'; 74 | 75 | export const routes: Routes = [ 76 | { path: 'lazy', loadChildren: './lazy.module#LazyModule?sync=true' } 77 | ]; 78 | ``` 79 | 80 | ## Additional Documentation 81 | 82 | * [Loader Options](./docs/options.md#general-loader-options) 83 | * [AoT Compilation Options](./docs/options.md#loader-options-aot-compilation) 84 | * [Lazy Loading Options](./docs/options.md#lazy-loading-options) 85 | 86 | 87 | ## Credits 88 | 89 | This loader was inspired by the following projects. 90 | 91 | [es6-promise-loader](https://github.com/gdi2290/es6-promise-loader) by [PatrickJS](https://twitter.com/@gdi2290) 92 | 93 | [angular2-template-loader](https://github.com/TheLarkInn/angular2-template-loader) by [Sean Larkin](https://twitter.com/@TheLarkInn) 94 | 95 | ### License 96 | 97 | MIT (http://www.opensource.org/licenses/mit-license.php) 98 | -------------------------------------------------------------------------------- /docs/options.md: -------------------------------------------------------------------------------- 1 | ## General Loader Options 2 | 3 | Options are provided as a query string with the `angular-router-loader` 4 | 5 | ```ts 6 | loaders: [ 7 | 'angular-router-loader?option=value' 8 | ] 9 | 10 | ``` 11 | 12 | ### debug: `(default: false)` 13 | 14 | Logs the file, loadChildren string found and replacement string used to the console. 15 | 16 | ### loader: `(default: 'require')` 17 | 18 | Sets the loader string returned for code splitting. 19 | 20 | original 21 | ```ts 22 | { 23 | path: 'lazy', 24 | loadChildren './lazy.module#LazyModule' 25 | } 26 | ``` 27 | 28 | replacement 29 | ```ts 30 | { 31 | path: 'lazy', 32 | loadChildren: () => new Promise(function (resolve, reject) { 33 | (require as any).ensure([], function (require: any) { 34 | resolve(require('./lazy/lazy.module')['LazyModule']); 35 | }, function () { 36 | reject({ loadChunkError: true }); 37 | }); 38 | }) 39 | } 40 | ``` 41 | 42 | To use `System.import`, set the `loader` to `system` 43 | 44 | **NOTE:** Using `system` only works with Webpack 2. Webpack 1 users should use the default. 45 | 46 | replacement 47 | ```ts 48 | { 49 | path: 'lazy', 50 | loadChildren: () => System.import('./lazy/lazy.module') 51 | .then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); }) 52 | } 53 | ``` 54 | 55 | To use `dynamic import`, set the `loader` to `import` 56 | 57 | replacement 58 | ```ts 59 | { 60 | path: 'lazy', 61 | loadChildren: () => import('./lazy/lazy.module') 62 | .then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); }) 63 | } 64 | ``` 65 | 66 | ## Loader options (AoT compilation) 67 | 68 | ### aot: `(default: false)` 69 | 70 | Enables replacement of the `loadChildren` string to 71 | load the Angular compiled factory file and factory class based on the provided file and class. 72 | 73 | ### genDir `(default: '')` 74 | 75 | **NOTE:** Angular version < 5 only 76 | 77 | In your `tsconfig.json`, if you set the `genDir` in the `angularCompilerOptions` to compile to a separate directory, this option needs to be set to the same value here. 78 | 79 | ## AoT example 80 | 81 | Example file structure (after an AOT build) 82 | ``` 83 | |-- compiled 84 | |-- src 85 | |-- app 86 | |-- src 87 | |-- app 88 | |-- tsconfig.json 89 | ``` 90 | tsconfig.json (Angular Compiler Options) 91 | 92 | ```json 93 | "angularCompilerOptions": { 94 | "genDir": "compiled", 95 | "skipMetadataEmit" : true 96 | } 97 | ``` 98 | 99 | Webpack Configuration (TypeScript loaders) 100 | 101 | **Angular Version >= 5** 102 | 103 | ```ts 104 | loaders: [ 105 | { 106 | test: /\.ts$/, 107 | loaders: [ 108 | 'awesome-typescript-loader' 109 | ] 110 | }, 111 | { 112 | test: /\.(ts|js)$/, 113 | loaders: [ 114 | 'angular-router-loader?aot=true' 115 | ] 116 | } 117 | ] 118 | ``` 119 | 120 | **Angular Version < 5** 121 | 122 | ```ts 123 | loaders: [ 124 | { 125 | test: /\.ts$/, 126 | loaders: [ 127 | 'awesome-typescript-loader', 128 | 'angular-router-loader?aot=true&genDir=compiled' 129 | ] 130 | } 131 | ] 132 | ``` 133 | 134 | original 135 | ```ts 136 | { 137 | path: 'lazy', 138 | loadChildren './lazy.module#LazyModule' 139 | } 140 | ``` 141 | 142 | replacement 143 | ```ts 144 | { 145 | path: 'lazy', 146 | loadChildren: () => new Promise(function (resolve) { 147 | (require as any).ensure([], function (require: any) { 148 | resolve(require('./lazy/lazy.module.ngfactory')['LazyModuleNgFactory']); 149 | }, function () { 150 | reject({ loadChunkError: true }); 151 | }); 152 | }) 153 | } 154 | ``` 155 | 156 | ## Lazy Loading Options 157 | 158 | ### chunkName 159 | 160 | Allows you to provide [named chunks](http://webpack.github.io/docs/code-splitting.html#named-chunks) for code splitting. 161 | 162 | original 163 | ```ts 164 | { 165 | path: 'lazy', 166 | loadChildren './lazy.module#LazyModule?chunkName=MyChunk' 167 | } 168 | ``` 169 | 170 | replacement (require loader) 171 | ```ts 172 | { 173 | path: 'lazy', 174 | loadChildren: () => new Promise(function (resolve) { 175 | (require as any).ensure([], function (require: any) { 176 | resolve(require('./lazy/lazy.module')['LazyModule']); 177 | }, function () { 178 | reject({ loadChunkError: true }); 179 | }, 'MyChunk'); 180 | }) 181 | } 182 | ``` 183 | 184 | replacement (system loader) 185 | ```ts 186 | { 187 | path: 'lazy', 188 | loadChildren: () => System.import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module') 189 | .then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); }) 190 | } 191 | ``` 192 | 193 | replacement (import loader) 194 | ```ts 195 | { 196 | path: 'lazy', 197 | loadChildren: () => import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module') 198 | .then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); }) 199 | } 200 | ``` 201 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-router-loader", 3 | "version": "0.8.5", 4 | "description": "A webpack loader for Angular that enables string-based module loading with the Angular Router", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", 8 | "test": "mocha -R spec spec", 9 | "test:watch": "npm run test -- -w" 10 | }, 11 | "keywords": [ 12 | "angular", 13 | "webpack", 14 | "loader", 15 | "router", 16 | "lazy-loading" 17 | ], 18 | "author": "Brandon Roberts", 19 | "license": "MIT", 20 | "dependencies": { 21 | "loader-utils": "^1.0.2" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/brandonroberts/angular-router-loader/issues" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/brandonroberts/angular-router-loader.git" 29 | }, 30 | "devDependencies": { 31 | "conventional-changelog-cli": "^1.2.0", 32 | "mocha": "^3.0.2", 33 | "pmock": "^0.2.3", 34 | "should": "^11.1.0" 35 | }, 36 | "peerDependencies": { 37 | "webpack": ">=2.4.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /spec/index.spec.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | var loader = require('../src/index'); 3 | 4 | function checkResult(loaded, result) { 5 | return loaded.should.eql(result.join('')); 6 | } 7 | 8 | describe('Loader', function() { 9 | 10 | var resourcePath = 'path/to/routes.ts'; 11 | var modulePath = './path/to/file.module#FileModule'; 12 | var query = ''; 13 | 14 | describe('should match', function() { 15 | 16 | var loadStrings = [ 17 | `loadChildren: '${modulePath}'`, 18 | `loadChildren:'${modulePath}'`, 19 | `loadChildren :'${modulePath}'`, 20 | `loadChildren : '${modulePath}'`, 21 | `loadChildren : '${modulePath}'`, 22 | `loadChildren :'${modulePath}'`, 23 | 24 | `loadChildren: "${modulePath}"`, 25 | `loadChildren:"${modulePath}"`, 26 | `loadChildren :"${modulePath}"`, 27 | `loadChildren : "${modulePath}"`, 28 | 29 | `"loadChildren":"${modulePath}"`, 30 | `"loadChildren": "${modulePath}"`, 31 | `"loadChildren" : "${modulePath}"`, 32 | `"loadChildren" : "${modulePath}"`, 33 | `"loadChildren" :"${modulePath}"`, 34 | `"loadChildren" : "${modulePath}"`, 35 | 36 | `'loadChildren':"${modulePath}"`, 37 | `'loadChildren': "${modulePath}"`, 38 | `'loadChildren' : "${modulePath}"`, 39 | `'loadChildren' : "${modulePath}"`, 40 | `'loadChildren' :"${modulePath}"`, 41 | `'loadChildren' : "${modulePath}"` 42 | ]; 43 | 44 | loadStrings.forEach(function(loadString) { 45 | it(loadString, function() { 46 | 47 | var result = [ 48 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 49 | ' (require as any).ensure([], function (require: any) {', 50 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 51 | ' }, function(e: any) {', 52 | ' reject({ loadChunkError: true, details: e });', 53 | ' });', 54 | '}) }' 55 | ]; 56 | 57 | var loadedString = loader.call({ 58 | resourcePath: resourcePath, 59 | query: query 60 | }, loadString); 61 | 62 | checkResult(loadedString, result); 63 | 64 | }); 65 | }); 66 | 67 | describe('should not match', function() { 68 | 69 | var loadStrings = [ 70 | `loadChildren: \`${modulePath}\``, 71 | `loadChildren : () => {}`, 72 | `loadChildren: someFunction('./')` 73 | ]; 74 | 75 | loadStrings.forEach(function(loadString) { 76 | it(loadString, function() { 77 | var result = [ 78 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 79 | ' (require as any).ensure([], function (require: any) {', 80 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 81 | ' }, function(e: any) {', 82 | ' reject({ loadChunkError: true, details: e });', 83 | ' });', 84 | '}) }' 85 | ]; 86 | 87 | var loadedString = loader.call({ 88 | resourcePath: resourcePath, 89 | query: query 90 | }, loadString); 91 | 92 | checkResult(loadedString, [loadString]); 93 | 94 | }); 95 | }); 96 | }); 97 | 98 | }); 99 | 100 | it('should return a loadChildren async require statement', function() { 101 | var result = [ 102 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 103 | ' (require as any).ensure([], function (require: any) {', 104 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 105 | ' }, function(e: any) {', 106 | ' reject({ loadChunkError: true, details: e });', 107 | ' });', 108 | '}) }' 109 | ]; 110 | 111 | var loadedString = loader.call({ 112 | resourcePath: resourcePath, 113 | query: query 114 | }, `loadChildren: '${modulePath}'`); 115 | 116 | checkResult(loadedString, result); 117 | }); 118 | 119 | it('should return a plain javascript loadChildren async require statement', function() { 120 | var result = [ 121 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 122 | ' require.ensure([], function (require) {', 123 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 124 | ' }, function(e) {', 125 | ' reject({ loadChunkError: true, details: e });', 126 | ' });', 127 | '}) }' 128 | ]; 129 | 130 | var loadedString = loader.call({ 131 | resourcePath: resourcePath.replace('.ts', '.js'), 132 | query: query 133 | }, `loadChildren: '${modulePath}'`); 134 | 135 | checkResult(loadedString, result); 136 | }); 137 | 138 | it('should return a loadChildren sync require statement', function() { 139 | var result = [ 140 | 'loadChildren: function() {', 141 | ' return require(\'./path/to/file.module\')[\'FileModule\'];', 142 | '}' 143 | ]; 144 | 145 | var loadedString = loader.call({ 146 | resourcePath: resourcePath, 147 | query: query 148 | }, `loadChildren: '${modulePath}?sync=true'`); 149 | 150 | checkResult(loadedString, result); 151 | }); 152 | 153 | it('should return a loadChildren chunkName require statement', function() { 154 | var result = [ 155 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 156 | ' (require as any).ensure([], function (require: any) {', 157 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 158 | ' }, function(e: any) {', 159 | ' reject({ loadChunkError: true, details: e });', 160 | ' }, \'name\');', 161 | '}) }' 162 | ]; 163 | 164 | var loadedString = loader.call({ 165 | resourcePath: resourcePath, 166 | query: query 167 | }, `loadChildren: '${modulePath}?chunkName=name'`); 168 | 169 | checkResult(loadedString, result); 170 | }); 171 | 172 | it ('should return a loadChildren System.import statement', function() { 173 | var result = [ 174 | 'loadChildren: function() { return System.import(\'./path/to/file.module\')', 175 | ' .then(module => module[\'FileModule\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 176 | ]; 177 | 178 | var loadedString = loader.call({ 179 | resourcePath: resourcePath, 180 | query: '?loader=system' 181 | }, `loadChildren: '${modulePath}'`); 182 | 183 | checkResult(loadedString, result); 184 | }); 185 | 186 | it ('should return a loadChildren chunkName System.import statement', function() { 187 | var result = [ 188 | 'loadChildren: function() { return System.import(/* webpackChunkName: "name" */ \'./path/to/file.module\')', 189 | ' .then(module => module[\'FileModule\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 190 | ]; 191 | 192 | var loadedString = loader.call({ 193 | resourcePath: resourcePath, 194 | query: '?loader=system' 195 | }, `loadChildren: '${modulePath}?chunkName=name'`); 196 | 197 | checkResult(loadedString, result); 198 | }); 199 | 200 | it ('should return a loadChildren dynamic import statement', function() { 201 | var result = [ 202 | 'loadChildren: function() { return import(\'./path/to/file.module\')', 203 | ' .then(module => module[\'FileModule\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 204 | ]; 205 | 206 | var loadedString = loader.call({ 207 | resourcePath: resourcePath, 208 | query: '?loader=import' 209 | }, `loadChildren: '${modulePath}'`); 210 | 211 | checkResult(loadedString, result); 212 | }); 213 | 214 | it ('should return a loadChildren chunkName dynamic import statement', function() { 215 | var result = [ 216 | 'loadChildren: function() { return import(/* webpackChunkName: "name" */ \'./path/to/file.module\')', 217 | ' .then(module => module[\'FileModule\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 218 | ]; 219 | 220 | var loadedString = loader.call({ 221 | resourcePath: resourcePath, 222 | query: '?loader=import' 223 | }, `loadChildren: '${modulePath}?chunkName=name'`); 224 | 225 | checkResult(loadedString, result); 226 | }); 227 | 228 | it('should return a loadChildren async require statement with default', function() { 229 | var modulePath = './path/to/file.module'; 230 | 231 | var result = [ 232 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 233 | ' (require as any).ensure([], function (require: any) {', 234 | ' resolve(require(\'./path/to/file.module\')[\'default\']);', 235 | ' }, function(e: any) {', 236 | ' reject({ loadChunkError: true, details: e });', 237 | ' });', 238 | '}) }' 239 | ]; 240 | 241 | var loadedString = loader.call({ 242 | resourcePath: resourcePath, 243 | query: query 244 | }, `loadChildren: '${modulePath}'`); 245 | 246 | checkResult(loadedString, result); 247 | }); 248 | 249 | it('should support a custom delimiter', function() { 250 | var result = [ 251 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 252 | ' (require as any).ensure([], function (require: any) {', 253 | ' resolve(require(\'./path/to/file.module\')[\'FileModule\']);', 254 | ' }, function(e: any) {', 255 | ' reject({ loadChunkError: true, details: e });', 256 | ' });', 257 | '}) }' 258 | ]; 259 | 260 | var loadedString = loader.call({ 261 | resourcePath: resourcePath, 262 | query: '?delimiter=*' 263 | }, `loadChildren: '${modulePath.replace('#', '*')}'`); 264 | 265 | checkResult(loadedString, result); 266 | }); 267 | 268 | it('should support windows file paths', function() { 269 | var pmock = require('pmock'); 270 | var env = pmock.platform('win32'); 271 | 272 | var result = [ 273 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 274 | ' (require as any).ensure([], function (require: any) {', 275 | ' resolve(require(\'.\\\\path\\\\to\\\\file.module\')[\'FileModule\']);', 276 | ' }, function(e: any) {', 277 | ' reject({ loadChunkError: true, details: e });', 278 | ' });', 279 | '}) }' 280 | ]; 281 | 282 | var loadedString = loader.call({ 283 | resourcePath: resourcePath, 284 | query: query 285 | }, `loadChildren: '${modulePath}'`); 286 | 287 | checkResult(loadedString, result); 288 | 289 | env.reset(); 290 | }); 291 | 292 | it('should support non-relative paths', function() { 293 | var result = [ 294 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 295 | ' (require as any).ensure([], function (require: any) {', 296 | ' resolve(require(\'path/to/file.module\')[\'FileModule\']);', 297 | ' }, function(e: any) {', 298 | ' reject({ loadChunkError: true, details: e });', 299 | ' });', 300 | '}) }' 301 | ]; 302 | 303 | var loadedString = loader.call({ 304 | resourcePath: resourcePath, 305 | query: '' 306 | }, `loadChildren: '${modulePath.replace('./', '')}'`); 307 | 308 | checkResult(loadedString, result); 309 | }); 310 | 311 | describe('AoT', function() { 312 | beforeEach(function() { 313 | query = '?aot=true&genDir=.' 314 | }); 315 | 316 | it('should return a loadChildren async require statement', function() { 317 | var result = [ 318 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 319 | ' (require as any).ensure([], function (require: any) {', 320 | ' resolve(require(\'./path/to/file.module.ngfactory\')[\'FileModuleNgFactory\']);', 321 | ' }, function(e: any) {', 322 | ' reject({ loadChunkError: true, details: e });', 323 | ' });', 324 | '}) }' 325 | ]; 326 | 327 | var loadedString = loader.call({ 328 | resourcePath: resourcePath, 329 | query: query 330 | }, `loadChildren: '${modulePath}'`); 331 | 332 | checkResult(loadedString, result); 333 | }); 334 | 335 | it('should return a loadChildren sync require statement', function() { 336 | var result = [ 337 | 'loadChildren: function() {', 338 | ' return require(\'./path/to/file.module.ngfactory\')[\'FileModuleNgFactory\'];', 339 | '}' 340 | ]; 341 | 342 | var loadedString = loader.call({ 343 | resourcePath: resourcePath, 344 | query: query 345 | }, `loadChildren: '${modulePath}?sync=true'`); 346 | 347 | checkResult(loadedString, result); 348 | }); 349 | 350 | it ('should return a loadChildren System.import statement', function() { 351 | var result = [ 352 | 'loadChildren: function() { return System.import(\'./path/to/file.module.ngfactory\')', 353 | ' .then(module => module[\'FileModuleNgFactory\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 354 | ]; 355 | 356 | var loadedString = loader.call({ 357 | resourcePath: resourcePath, 358 | query: query + '&loader=system' 359 | }, `loadChildren: '${modulePath}'`); 360 | 361 | checkResult(loadedString, result); 362 | }); 363 | 364 | it ('should return a loadChildren dynamic import statement', function() { 365 | var result = [ 366 | 'loadChildren: function() { return import(\'./path/to/file.module.ngfactory\')', 367 | ' .then(module => module[\'FileModuleNgFactory\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 368 | ]; 369 | 370 | var loadedString = loader.call({ 371 | resourcePath: resourcePath, 372 | query: query + '&loader=import' 373 | }, `loadChildren: '${modulePath}'`); 374 | 375 | checkResult(loadedString, result); 376 | }); 377 | 378 | it('should support a custom moduleSuffix', function() { 379 | var moduleSuffix = '.ngfile'; 380 | 381 | var result = [ 382 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 383 | ' (require as any).ensure([], function (require: any) {', 384 | ' resolve(require(\'./path/to/file.module' + moduleSuffix + '\')[\'FileModuleNgFactory\']);', 385 | ' }, function(e: any) {', 386 | ' reject({ loadChunkError: true, details: e });', 387 | ' });', 388 | '}) }' 389 | ]; 390 | 391 | var loadedString = loader.call({ 392 | resourcePath: resourcePath, 393 | query: query + '&moduleSuffix=' + moduleSuffix 394 | }, `loadChildren: '${modulePath}'`); 395 | 396 | checkResult(loadedString, result); 397 | }); 398 | 399 | it('should support a custom factorySuffix', function() { 400 | var factorySuffix = 'NgFact'; 401 | 402 | var result = [ 403 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 404 | ' (require as any).ensure([], function (require: any) {', 405 | ' resolve(require(\'./path/to/file.module.ngfactory\')[\'FileModule' + factorySuffix + '\']);', 406 | ' }, function(e: any) {', 407 | ' reject({ loadChunkError: true, details: e });', 408 | ' });', 409 | '}) }' 410 | ]; 411 | 412 | var loadedString = loader.call({ 413 | resourcePath: resourcePath, 414 | query: query + '&factorySuffix=' + factorySuffix 415 | }, `loadChildren: '${modulePath}'`); 416 | 417 | checkResult(loadedString, result); 418 | }); 419 | 420 | it('should support non-relative paths', function() { 421 | var result = [ 422 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 423 | ' (require as any).ensure([], function (require: any) {', 424 | ' resolve(require(\'path/to/file.module.ngfactory\')[\'FileModuleNgFactory\']);', 425 | ' }, function(e: any) {', 426 | ' reject({ loadChunkError: true, details: e });', 427 | ' });', 428 | '}) }' 429 | ]; 430 | 431 | var loadedString = loader.call({ 432 | resourcePath: resourcePath, 433 | query: query 434 | }, `loadChildren: '${modulePath.replace('./', '')}'`); 435 | 436 | checkResult(loadedString, result); 437 | }); 438 | }); 439 | 440 | describe('AoT + genDir', function() { 441 | var resourcePath = 'src/app/my-module/my-module.routes.ts'; 442 | var modulePath = '../groups/inventory/index#InventoryModule'; 443 | 444 | beforeEach(function() { 445 | query = '?aot=true&genDir=compiled' 446 | }); 447 | 448 | it('should return a loadChildren async require statement', function() { 449 | var result = [ 450 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 451 | ' (require as any).ensure([], function (require: any) {', 452 | ' resolve(require(\'../../../compiled/src/app/groups/inventory/index.ngfactory\')[\'InventoryModuleNgFactory\']);', 453 | ' }, function(e: any) {', 454 | ' reject({ loadChunkError: true, details: e });', 455 | ' });', 456 | '}) }' 457 | ]; 458 | 459 | var loadedString = loader.call({ 460 | resourcePath: resourcePath, 461 | query: query 462 | }, `loadChildren: '${modulePath}'`); 463 | 464 | checkResult(loadedString, result); 465 | }); 466 | }); 467 | }); 468 | -------------------------------------------------------------------------------- /spec/utils.spec.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | var utils = require('../src/utils'); 3 | 4 | describe('Utils', function() { 5 | var getRequireString = utils.getRequireString; 6 | 7 | var path = 'path'; 8 | var name = 'name'; 9 | 10 | describe('getRequireString', function() { 11 | it('should return a require statement', function() { 12 | getRequireString(path, name).should.eql('require(\'path\')[\'name\']'); 13 | }); 14 | }); 15 | 16 | describe('getSyncLoader', function() { 17 | var getSyncLoader = utils.getSyncLoader; 18 | 19 | it('should return a synchronous require loadChildren statement', function() { 20 | var result = [ 21 | 'loadChildren: function() {', 22 | ' return ' + getRequireString(path, name) + ';', 23 | '}' 24 | ]; 25 | 26 | getSyncLoader('path', 'name', true).should.eql(result.join('')); 27 | }); 28 | }); 29 | 30 | describe('getRequireLoader', function() { 31 | var getRequireLoader = utils.getRequireLoader; 32 | 33 | it('should return an asynchronous require loadChildren statement with chunkName parameter', function() { 34 | var result = [ 35 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 36 | ' (require as any).ensure([], function (require: any) {', 37 | ' resolve(' + getRequireString(path, name) + ');', 38 | ' }, function(e: any) {', 39 | ' reject({ loadChunkError: true, details: e });', 40 | ' }, \'name\');', 41 | '}) }' 42 | ]; 43 | getRequireLoader('path', 'name', 'name', true).should.eql(result.join('')); 44 | }); 45 | 46 | it('should return an asynchronous require loadChildren statement without chunkName parameter', function() { 47 | var result = [ 48 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 49 | ' (require as any).ensure([], function (require: any) {', 50 | ' resolve(' + getRequireString(path, name) + ');', 51 | ' }, function(e: any) {', 52 | ' reject({ loadChunkError: true, details: e });', 53 | ' });', 54 | '}) }' 55 | ]; 56 | getRequireLoader('path', undefined, 'name', true).should.eql(result.join('')); 57 | }); 58 | 59 | it('should return an asynchronous require loadChildren statement with vanilla javascript', function() { 60 | var result = [ 61 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 62 | ' require.ensure([], function (require) {', 63 | ' resolve(' + getRequireString(path, name) + ');', 64 | ' }, function(e) {', 65 | ' reject({ loadChunkError: true, details: e });', 66 | ' }, \'name\');', 67 | '}) }' 68 | ]; 69 | getRequireLoader('path', 'name', 'name', true, true).should.eql(result.join('')); 70 | }); 71 | 72 | }); 73 | 74 | describe('getSystemLoader', function() { 75 | var getSystemLoader = utils.getSystemLoader; 76 | 77 | it('should return an asynchronous System.import loadChildren statement', function() { 78 | var result = [ 79 | 'loadChildren: function() { return System.import(\'' + path + '\')', 80 | ' .then(module => module[\'' + name + '\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 81 | ]; 82 | 83 | getSystemLoader('path', 'name', true).should.eql(result.join('')); 84 | }); 85 | }); 86 | 87 | describe('getImportLoader', function() { 88 | var getImportLoader = utils.getImportLoader; 89 | 90 | it('should return an asynchronous dynamic import loadChildren statement', function() { 91 | var result = [ 92 | 'loadChildren: function() { return import(\'' + path + '\')', 93 | ' .then(module => module[\'' + name + '\'], (e: any) => { throw({ loadChunkError: true, details: e }); }) }' 94 | ]; 95 | 96 | getImportLoader('path', 'name', true).should.eql(result.join('')); 97 | }); 98 | }); 99 | 100 | describe('normalizeFilePath', function() { 101 | var pmock = require('pmock'); 102 | var normalizeFilePath = utils.normalizeFilePath; 103 | var env; 104 | 105 | describe('for windows os', function() { 106 | beforeEach(function() { 107 | env = pmock.platform('win32'); 108 | }); 109 | 110 | it('should replace backslashes with forward slashes', function() { 111 | normalizeFilePath('./path', true).should.eql('.\\\\path'); 112 | }); 113 | 114 | it('should make a relative path if the path is not relative and the original path was relative', function() { 115 | normalizeFilePath('path', true).should.eql('.\\\\path'); 116 | }); 117 | 118 | it('should not make a relative path if the original path was not relative', function() { 119 | normalizeFilePath('path', false).should.eql('path'); 120 | }); 121 | 122 | afterEach(function() { 123 | env.reset(); 124 | }); 125 | }); 126 | 127 | describe('for non-windows os', function() { 128 | beforeEach(function() { 129 | env = pmock.platform('posix'); 130 | }); 131 | 132 | it('should not replace backslashes', function() { 133 | normalizeFilePath('./path', true).should.eql('./path'); 134 | }); 135 | 136 | it('should make a relative path if the path is not relative and the original path was relative', function() { 137 | normalizeFilePath('path', true).should.eql('./path'); 138 | }); 139 | 140 | it('should not make a relative path if the original path was not relative', function() { 141 | normalizeFilePath('path', false).should.eql('path'); 142 | }); 143 | 144 | afterEach(function() { 145 | env.reset(); 146 | }); 147 | }); 148 | }); 149 | 150 | describe('getFilename', function() { 151 | var getFilename = utils.getFilename; 152 | 153 | it('should return the filename for a given path without an extension', function() { 154 | getFilename('path/to/module.ngfactory.ts').should.eql('module.ngfactory'); 155 | }); 156 | }); 157 | 158 | describe('getChunkName', function() { 159 | var getChunkName = utils.getChunkName; 160 | 161 | it('should return the chunkName string for a system loader and provided chunkName', function() { 162 | getChunkName('system', 'name').should.eql('/* webpackChunkName: "name" */ '); 163 | }); 164 | 165 | it('should return the chunkName string for a import loader and provided chunkName', function() { 166 | getChunkName('import', 'name').should.eql('/* webpackChunkName: "name" */ '); 167 | }); 168 | 169 | it('should return the chunkName string for a require loader and provided chunkName', function() { 170 | getChunkName('require', 'name').should.eql(', \'name\''); 171 | }); 172 | 173 | it('should return an empty chunkName string for a loader and an empty chunkName', function() { 174 | getChunkName('require', '').should.eql(''); 175 | }); 176 | }); 177 | }); 178 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | var loaderUtils = require('loader-utils'); 2 | var path = require('path'); 3 | var utils = require('./utils'); 4 | 5 | module.exports = function(source, sourcemap) { 6 | this.cacheable && this.cacheable(); 7 | 8 | // regex for loadChildren string 9 | var loadChildrenRegex = /["']?loadChildren["']?[\s]*:[\s]*['|"](.*?)['|"]/gm; 10 | 11 | // parse query params 12 | var query = loaderUtils.getOptions(this) || {}; 13 | 14 | // get query options 15 | var delimiter = query.delimiter || '#'; 16 | var aot = query.aot || false; 17 | var moduleSuffix = query.moduleSuffix || '.ngfactory'; 18 | var factorySuffix = query.factorySuffix || 'NgFactory'; 19 | var loader = query.loader || 'require'; 20 | var genDir = query.genDir || ''; 21 | var inline = query.inline || true; 22 | var debug = (typeof query.debug !== 'boolean' ? this.debug : query.debug); 23 | var baseDir = query.baseDir || process.cwd(); 24 | 25 | // get the filename path 26 | var resourcePath = this.resourcePath; 27 | var filename = utils.getFilename(resourcePath); 28 | var isJs = path.extname(resourcePath).toLowerCase() === '.js'; 29 | 30 | var replacedSource = source.replace(loadChildrenRegex, function(match, loadString) { 31 | // check for query string in loadString 32 | var queryIndex = loadString.lastIndexOf('?'); 33 | var hasQuery = queryIndex !== -1; 34 | var loadStringQuery = hasQuery ? loaderUtils.getOptions({ query: loadString.substr(queryIndex) }) : {}; 35 | var sync = !!loadStringQuery.sync; 36 | var chunkName = loadStringQuery.chunkName || undefined; 37 | var isRelativePath = loadString.startsWith('.'); 38 | 39 | // get the module path string 40 | var pathString = hasQuery ? loadString.substr(0, queryIndex) : loadString; 41 | 42 | // split the string on the delimiter 43 | var parts = pathString.split(delimiter); 44 | 45 | // get the file path and module name 46 | var filePath = parts[0] + (aot ? moduleSuffix : ''); 47 | var moduleName = (parts[1] || 'default'); 48 | 49 | moduleName += (aot ? factorySuffix : ''); 50 | 51 | // update the file path for non-ngfactory files 52 | if (aot && filename.substr(-9) !== moduleSuffix.substr(-9) && isRelativePath) { 53 | // the full path of the directory of the current resource 54 | var currentDir = path.dirname(resourcePath); 55 | 56 | // the absolute path of our destenation NgModule module. 57 | var absoluteNgModulePath = path.resolve(currentDir, filePath); 58 | 59 | /* 60 | * If "genDir" is empty the compiler emits to the source tree, next to the original component source code. 61 | * absoluteNgModulePath points to there so we're good. 62 | * 63 | * If "genDir" exist need to map the path based on "genDir" 64 | */ 65 | if (genDir && genDir !== '.') { 66 | 67 | /* 68 | "genDir" is tricky. 69 | The path used for "genDir" is resolved relative to the "tsconfig.json" file used to execute ngc. 70 | This out of the context of webpack so we can't figure this out automatically. 71 | The user needs to set a "genDir" relative to the root of the project which should resolve to the same absolute path ngc resolves for "genDir". 72 | 73 | If "tsconfig.json" is in the root of the project it's identical. 74 | */ 75 | 76 | var relativeNgModulePath = path.relative(baseDir, absoluteNgModulePath); 77 | absoluteNgModulePath = path.join(path.resolve(baseDir, genDir), relativeNgModulePath); 78 | } 79 | 80 | 81 | // filePath is an absolute path, we need the relative filePath: 82 | filePath = path.relative(currentDir, absoluteNgModulePath); 83 | } 84 | 85 | filePath = utils.normalizeFilePath(filePath, isRelativePath); 86 | 87 | var replacement = match; 88 | 89 | if (sync) { 90 | replacement = utils.getSyncLoader(filePath, moduleName, inline); 91 | } else if (loader === 'system') { 92 | replacement = utils.getSystemLoader(filePath, moduleName, inline, chunkName, isJs); 93 | } else if (loader === 'import') { 94 | replacement = utils.getImportLoader(filePath, moduleName, inline, chunkName, isJs); 95 | } else { 96 | replacement = utils.getRequireLoader(filePath, chunkName, moduleName, inline, isJs); 97 | } 98 | 99 | if (debug) { 100 | console.log('[angular-router-loader]: --DEBUG--'); 101 | console.log('[angular-router-loader]: File: ' + resourcePath); 102 | console.log('[angular-router-loader]: Original: ' + match); 103 | console.log('[angular-router-loader]: Replacement: ' + replacement); 104 | } 105 | 106 | return replacement; 107 | }); 108 | 109 | if (this.callback) { 110 | this.callback(null, replacedSource, sourcemap); 111 | } else { 112 | return replacedSource; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var path = require('path'); 3 | 4 | module.exports.getRequireString = function(filePath, moduleName, inline) { 5 | return 'require(\'' + filePath + '\')[\'' + moduleName + '\']'; 6 | }; 7 | 8 | module.exports.getSyncLoader = function(filePath, moduleName, inline) { 9 | var requireString = module.exports.getRequireString(filePath, moduleName); 10 | 11 | var result = [ 12 | 'loadChildren: function() {', 13 | ' return ' + requireString + ';', 14 | '}' 15 | ]; 16 | 17 | return inline ? result.join('') : result.join('\n'); 18 | }; 19 | 20 | module.exports.getRequireLoader = function(filePath, chunkName, moduleName, inline, isJs) { 21 | var requireString = module.exports.getRequireString(filePath, moduleName); 22 | 23 | var result = [ 24 | 'loadChildren: function() { return new Promise(function (resolve, reject) {', 25 | ' ' + (isJs ? 'require' : '(require as any)') + '.ensure([], function (' + (isJs ? 'require' : 'require: any') + ') {', 26 | ' resolve(' + requireString + ');', 27 | ' }, function(' + (isJs ? 'e' : 'e: any') + ') {', 28 | ' reject({ loadChunkError: true, details: e });', 29 | ' }' + module.exports.getChunkName('require', chunkName) + ');', 30 | '}) }' 31 | ]; 32 | 33 | return inline ? result.join('') : result.join('\n'); 34 | }; 35 | 36 | module.exports.getSystemLoader = function(filePath, moduleName, inline, chunkName, isJs) { 37 | var result = [ 38 | 'loadChildren: function() { return System.import(' + module.exports.getChunkName('system', chunkName) + '\'' + filePath + '\')', 39 | ' .then(module => module[\'' + moduleName + '\'], (' + (isJs ? 'e' : 'e: any') + ') => { throw({ loadChunkError: true, details: e }); }) }' 40 | ]; 41 | 42 | return inline ? result.join('') : result.join('\n'); 43 | }; 44 | 45 | module.exports.getImportLoader = function(filePath, moduleName, inline, chunkName, isJs) { 46 | var result = [ 47 | 'loadChildren: function() { return import(' + module.exports.getChunkName('import', chunkName) + '\'' + filePath + '\')', 48 | ' .then(module => module[\'' + moduleName + '\'], (' + (isJs ? 'e' : 'e: any') + ') => { throw({ loadChunkError: true, details: e }); }) }' 49 | ]; 50 | 51 | return inline ? result.join('') : result.join('\n'); 52 | }; 53 | 54 | module.exports.getFilename = function(resourcePath) { 55 | var filename = path.basename(resourcePath); 56 | 57 | return path.basename(resourcePath, path.extname(filename)); 58 | }; 59 | 60 | module.exports.normalizeFilePath = function(filePath, relativePathMatch) { 61 | var newPath = filePath; 62 | 63 | if (relativePathMatch && !newPath.startsWith('./') && !newPath.startsWith('../')) { 64 | newPath = './' + newPath; 65 | } 66 | 67 | if (os.platform() === 'win32') { 68 | var path = newPath.replace(/\//g, '\\'); 69 | newPath = path.replace(/\\/g, '\\\\'); 70 | } 71 | 72 | return newPath; 73 | } 74 | 75 | module.exports.getChunkName = function (loader, chunkName) { 76 | if (chunkName && (loader === 'import' || loader === 'system')) { 77 | return '/* webpackChunkName: "' + chunkName + '" */ '; 78 | } else if (chunkName && loader == 'require') { 79 | return ', \'' + chunkName + '\''; 80 | } 81 | 82 | return ''; 83 | } 84 | --------------------------------------------------------------------------------