Importing a lazy-loaded module with routes in a module with a route breaks routing
Actually, when creating a shared module, there is no need to care about modules which uses a little part of the shared module, because Angular's tree-shaking will keep only the used code from an imported module, and remove the rest.
I've prepared a minimal project to demonstrate it: https://github.com/youkouleley/Angular-treeshaking-demo
This project has two lazy modules: AModule
and BModule
. Both of these modules import SharedModule
. SharedModule
exports three components:
AComponent
which is used inAModule
onlyBComponent
which is used inBModule
onlyBothComponent
which is used inAModule
andBModule
Here is what you'll get when ng build
ing this project in production mode and opening the 4-es2015.<hash>.js
file:
(window.webpackJsonp = window.webpackJsonp || []).push([[4], {
KImX: function (n, l, u) {
"use strict";
u.r(l);
var t = u("8Y7J");
class a {
constructor() {}
ngOnInit() {}
}
var r = u("phyl");
class o {}
var c = u("pMnS"),
s = t.gb({
encapsulation: 0,
styles: [[""]],
data: {}
});
function b(n) {
return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "p", [], null, null, null, null, null)), (n()(), t.rb(-1, null, ["a works!"]))], null, null)
}
function i(n) {
return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "app-a", [], null, null, null, b, s)), t.hb(1, 114688, null, 0, a, [], null, null)], function (n, l) {
n(l, 1, 0)
}, null)
}
var p = t.eb("app-a", a, i, {}, {}, []),
e = u("gJxL"),
f = u("SVse"),
h = u("iInd"),
d = u("PCNd");
u.d(l, "AModuleNgFactory", function () {
return v
});
var v = t.fb(o, [], function (n) {
return t.ob([t.pb(512, t.j, t.T, [[8, [c.a, p, e.a]], [3, t.j], t.u]), t.pb(4608, f.i, f.h, [t.r, [2, f.o]]), t.pb(1073742336, f.b, f.b, []), t.pb(1073742336, h.l, h.l, [[2, h.q], [2, h.k]]), t.pb(1073742336, d.a, d.a, []), t.pb(1073742336, o, o, []), t.pb(1024, h.i, function () {
return [[{
path: "a",
component: a
}, {
path: "both",
component: r.a
}
]]
}, [])])
})
},
PCNd: function (n, l, u) {
"use strict";
u.d(l, "a", function () {
return t
});
class t {}
},
gJxL: function (n, l, u) {
"use strict";
var t = u("8Y7J"),
a = u("phyl");
u.d(l, "a", function () {
return s
});
var r = t.gb({
encapsulation: 0,
styles: [[""]],
data: {}
});
function o(n) {
return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "p", [], null, null, null, null, null)), (n()(), t.rb(-1, null, ["both works!"]))], null, null)
}
function c(n) {
return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "app-both", [], null, null, null, o, r)), t.hb(1, 114688, null, 0, a.a, [], null, null)], function (n, l) {
n(l, 1, 0)
}, null)
}
var s = t.eb("app-both", a.a, c, {}, {}, [])
},
phyl: function (n, l, u) {
"use strict";
u.d(l, "a", function () {
return t
});
class t {
constructor() {}
ngOnInit() {}
}
}
}
]);
Note that the BComponent
from the SharedModule
is missing from the AModule
chunk. Sames goes for BModule
chunk that excludes AComponent
.
Also, note that this behavior is obtained when setting commonChunk
to false
in the build options. This option allows you to choose between:
false
: Bundle the needed parts of theSharedModule
directly into the lazy modules that imported it. Pro: Even loading time between lazy modules. Con: Some code fromSharedModule
is duplicated between lazy modules chunks, higher app size overalltrue
(default): Have a common chunk that contains the parts of theSharedModule
which are used at least by two lazy modules (the rest is bundled into the lazy modules themselves). Pro: No duplicated code, lower app size overall. Con: The first lazy module is slower to load (it loads the common chunk even if the current route doesn't need it)
As a conclusion, Angular build provides optimizations for the SharedModule
with commonChunk
set either to true
or false
(depending on your context) you don't really have to worry about your SharedModule
size. Thus, you don't have to try strange patterns like you did, with hybrid modules fulfilling the feature module role, and the shared module role at the same time.