Skip to content

Commit

Permalink
feat(loader): Add promise rejection upon loader error (#94)
Browse files Browse the repository at this point in the history
BREAKING CHANGES: Webpack >= 2.4 is required for the error callback to be supported with require.ensure

BEFORE:

Webpack < 2.4 is supported

AFTER:

Webpack >= 2.4 is supported

Closes #75
  • Loading branch information
brandonroberts committed Nov 17, 2017
1 parent df345fc commit 68d89ff
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 42 deletions.
22 changes: 15 additions & 7 deletions docs/options.md
Expand Up @@ -29,9 +29,11 @@ replacement
```ts
{
path: 'lazy',
loadChildren: () => new Promise(function (resolve) {
loadChildren: () => new Promise(function (resolve, reject) {
(require as any).ensure([], function (require: any) {
resolve(require('./lazy/lazy.module')['LazyModule']);
}, function () {
reject({ loadChunkError: true });
});
})
}
Expand All @@ -45,19 +47,19 @@ replacement
```ts
{
path: 'lazy',
loadChildren: () => System.import('./lazy/lazy.module').then(module => module['LazyModule'])
loadChildren: () => System.import('./lazy/lazy.module')
.then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); })
}
```

To use `dynamic import`, set the `loader` to `import`

**NOTE:** Using `import` only works with Webpack >= 2.1.0.

replacement
```ts
{
path: 'lazy',
loadChildren: () => import('./lazy/lazy.module').then(module => module['LazyModule'])
loadChildren: () => import('./lazy/lazy.module')
.then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); })
}
```

Expand Down Expand Up @@ -144,6 +146,8 @@ replacement
loadChildren: () => new Promise(function (resolve) {
(require as any).ensure([], function (require: any) {
resolve(require('./lazy/lazy.module.ngfactory')['LazyModuleNgFactory']);
}, function () {
reject({ loadChunkError: true });
});
})
}
Expand All @@ -170,6 +174,8 @@ replacement (require loader)
loadChildren: () => new Promise(function (resolve) {
(require as any).ensure([], function (require: any) {
resolve(require('./lazy/lazy.module')['LazyModule']);
}, function () {
reject({ loadChunkError: true });
}, 'MyChunk');
})
}
Expand All @@ -179,14 +185,16 @@ replacement (system loader)
```ts
{
path: 'lazy',
loadChildren: () => System.import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module').then(module => module['LazyModule'])
loadChildren: () => System.import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module')
.then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); })
}
```

replacement (import loader)
```ts
{
path: 'lazy',
loadChildren: () => import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module').then(module => module['LazyModule'])
loadChildren: () => import(/* webpackChunkName: "MyChunk" */ './lazy/lazy.module')
.then(module => module['LazyModule'], () => { throw({ loadChunkError: true }); })
}
```
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -32,5 +32,8 @@
"mocha": "^3.0.2",
"pmock": "^0.2.3",
"should": "^11.1.0"
},
"peerDependencies": {
"webpack": ">=2.4.0"
}
}
76 changes: 52 additions & 24 deletions spec/index.spec.js
Expand Up @@ -45,9 +45,11 @@ describe('Loader', function() {
it(loadString, function() {

var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -73,9 +75,11 @@ describe('Loader', function() {
loadStrings.forEach(function(loadString) {
it(loadString, function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -95,9 +99,11 @@ describe('Loader', function() {

it('should return a loadChildren async require statement', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -112,9 +118,11 @@ describe('Loader', function() {

it('should return a plain javascript loadChildren async require statement', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' require.ensure([], function (require) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand Down Expand Up @@ -144,9 +152,11 @@ describe('Loader', function() {

it('should return a loadChildren chunkName require statement', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' }, \'name\');',
'})'
];
Expand All @@ -162,7 +172,7 @@ describe('Loader', function() {
it ('should return a loadChildren System.import statement', function() {
var result = [
'loadChildren: () => System.import(\'./path/to/file.module\')',
' .then(module => module[\'FileModule\'])'
' .then(module => module[\'FileModule\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -176,7 +186,7 @@ describe('Loader', function() {
it ('should return a loadChildren chunkName System.import statement', function() {
var result = [
'loadChildren: () => System.import(/* webpackChunkName: "name" */ \'./path/to/file.module\')',
' .then(module => module[\'FileModule\'])'
' .then(module => module[\'FileModule\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -190,7 +200,7 @@ describe('Loader', function() {
it ('should return a loadChildren dynamic import statement', function() {
var result = [
'loadChildren: () => import(\'./path/to/file.module\')',
' .then(module => module[\'FileModule\'])'
' .then(module => module[\'FileModule\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -204,7 +214,7 @@ describe('Loader', function() {
it ('should return a loadChildren chunkName dynamic import statement', function() {
var result = [
'loadChildren: () => import(/* webpackChunkName: "name" */ \'./path/to/file.module\')',
' .then(module => module[\'FileModule\'])'
' .then(module => module[\'FileModule\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -219,9 +229,11 @@ describe('Loader', function() {
var modulePath = './path/to/file.module';

var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'default\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -236,9 +248,11 @@ describe('Loader', function() {

it('should support a custom delimiter', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -256,9 +270,11 @@ describe('Loader', function() {
var env = pmock.platform('win32');

var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'.\\\\path\\\\to\\\\file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -275,9 +291,11 @@ describe('Loader', function() {

it('should support non-relative paths', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'path/to/file.module\')[\'FileModule\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -297,10 +315,12 @@ describe('Loader', function() {

it('should return a loadChildren async require statement', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module.ngfactory\')[\'FileModuleNgFactory\']);',
' });',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];

Expand Down Expand Up @@ -330,7 +350,7 @@ describe('Loader', function() {
it ('should return a loadChildren System.import statement', function() {
var result = [
'loadChildren: () => System.import(\'./path/to/file.module.ngfactory\')',
' .then(module => module[\'FileModuleNgFactory\'])'
' .then(module => module[\'FileModuleNgFactory\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -344,7 +364,7 @@ describe('Loader', function() {
it ('should return a loadChildren dynamic import statement', function() {
var result = [
'loadChildren: () => import(\'./path/to/file.module.ngfactory\')',
' .then(module => module[\'FileModuleNgFactory\'])'
' .then(module => module[\'FileModuleNgFactory\'], () => { throw({ loadChunkError: true }); })'
];

var loadedString = loader.call({
Expand All @@ -359,10 +379,12 @@ describe('Loader', function() {
var moduleSuffix = '.ngfile';

var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module' + moduleSuffix + '\')[\'FileModuleNgFactory\']);',
' });',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];

Expand All @@ -378,9 +400,11 @@ describe('Loader', function() {
var factorySuffix = 'NgFact';

var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'./path/to/file.module.ngfactory\')[\'FileModule' + factorySuffix + '\']);',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
Expand All @@ -395,10 +419,12 @@ describe('Loader', function() {

it('should support non-relative paths', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'path/to/file.module.ngfactory\')[\'FileModuleNgFactory\']);',
' });',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];

Expand All @@ -421,10 +447,12 @@ describe('Loader', function() {

it('should return a loadChildren async require statement', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(require(\'../../../compiled/src/app/groups/inventory/index.ngfactory\')[\'InventoryModuleNgFactory\']);',
' });',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];

Expand Down
22 changes: 14 additions & 8 deletions spec/utils.spec.js
Expand Up @@ -32,32 +32,38 @@ describe('Utils', function() {

it('should return an asynchronous require loadChildren statement with chunkName parameter', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(' + getRequireString(path, name) + ');',
' }, \'name\');',
' }, function () {',
' reject({ loadChunkError: true });',
' }, \'name\');',
'})'
];
getRequireLoader('path', 'name', 'name', true).should.eql(result.join(''));
});

it('should return an asynchronous require loadChildren statement without chunkName parameter', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' (require as any).ensure([], function (require: any) {',
' resolve(' + getRequireString(path, name) + ');',
' });',
' }, function () {',
' reject({ loadChunkError: true });',
' });',
'})'
];
getRequireLoader('path', undefined, 'name', true).should.eql(result.join(''));
});

it('should return an asynchronous require loadChildren statement with vanilla javascript', function() {
var result = [
'loadChildren: () => new Promise(function (resolve) {',
'loadChildren: () => new Promise(function (resolve, reject) {',
' require.ensure([], function (require) {',
' resolve(' + getRequireString(path, name) + ');',
' }, \'name\');',
' }, function () {',
' reject({ loadChunkError: true });',
' }, \'name\');',
'})'
];
getRequireLoader('path', 'name', 'name', true, true).should.eql(result.join(''));
Expand All @@ -71,7 +77,7 @@ describe('Utils', function() {
it('should return an asynchronous System.import loadChildren statement', function() {
var result = [
'loadChildren: () => System.import(\'' + path + '\')',
' .then(module => module[\'' + name + '\'])'
' .then(module => module[\'' + name + '\'], () => { throw({ loadChunkError: true }); })'
];

getSystemLoader('path', 'name', true).should.eql(result.join(''));
Expand All @@ -84,7 +90,7 @@ describe('Utils', function() {
it('should return an asynchronous dynamic import loadChildren statement', function() {
var result = [
'loadChildren: () => import(\'' + path + '\')',
' .then(module => module[\'' + name + '\'])'
' .then(module => module[\'' + name + '\'], () => { throw({ loadChunkError: true }); })'
];

getImportLoader('path', 'name', true).should.eql(result.join(''));
Expand Down

0 comments on commit 68d89ff

Please sign in to comment.