I am trying to add server-side rendering capability to my existing Angular (v7.0.3) application. But I am having some issue with ng-flexmonster(v2.7.11). I am getting window is not defined ReferenceError (Stack Trace included in the end) after running node dist/server
.
After much investigation, I have zeroed down the issue to two components of a module which uses ng-flexmonster's FlexMonsterPivotModule and FlexMonster component. I have also wrapped all ts and html code where that pivot component is used with isPlatformBrowser(this.platformId)
checks. However, I am still getting the same error. So, I digged deeper and found that inside FlexMonster component's ts file there is import * as Flexmonster from 'flexmonster';
right at the top which actually imports the FlexMonster js package and references browser window object. Basically I want to add this patch on my app development which I am working with mobile application development company. And i have installed the flexmonster data server and admin panel as well, and able to create the index.
So, my question is "Is there a way to use this type of package with Angular Universal (SSR) so that the flexmonster is imported only in browser?".
D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:396797
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));a.Flexmonster=b()})(window,function(){return function(a){'use strict';
B6jj.a71="fm-filtered";j6jj.z9F="font-family";h6jj.o81="linear";m6jj.J2v="columnSortTuple";w6jj.j7F="currencySymbol";w6jj.v8p="truestyle";j6jj.V9F="padding-left";
I6jj.u3p="data-index";I6jj.K2p="week";m6jj.q2v="lastRowsTupleInteracted";T6jj.i8V=2;I6jj.F8p="rgb(255,255,255)";B6jj.u21="password";m6jj.M2v="extendedDataWidth";
h6jj.C81=".level";F6jj.W5y="useToken";h6jj.V91="fm-text-display";j6jj.O5F="defaultHierarchySortName";j6jj.B9F="class='";h6jj.P81="dx";h6jj.G51="fm-content";
j6jj.L9F=".{0}{{1}}\n";I6jj.g3p="label";w6jj.a2F="column";T6jj.w6p=4759;j6jj.Y1v="style";T6jj.j5V=400;w6jj.q3F="credentials";F6jj.N8y="fm-ui-col";B6jj.R9v="D4+";
I6jj.n4p=",";I6jj.V3p="originalCaption";I6jj.d0p="ntr";m6jj.i2v="columnCount";h6jj.i4y="fm-moreicon-
ReferenceError: window is not defined
at Object.<anonymous> (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:396797:122)
at Object.module.exports (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:397346:30)
at __webpack_require__ (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:20:30)
at Module.__WEBPACK_AMD_DEFINE_ARRAY__ (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:396587:69)
at __webpack_require__ (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:20:30)
at Object.ng-flexmonster (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:223596:18)
at __webpack_require__ (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:129039:30)
at Module../node_modules/ng-flexmonster/ng-flexmonster.ngfactory.js (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:151859:72)
at __webpack_require__ (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:129039:30)
at Module../src/app/dashboard/dashboard-report/flex-grid/flex-grid.component.ngfactory.js (D:\Projects\src\Portal-RnD\Portal-Features-1-SSR-Node-Angular-Guide\src\portal-ui\dist\server.js:172922:112)
I was able to fix this problem by using webpack's NormalModuleReplacementPlugin. At first, I created a directory called server-mocks under src directory. In there, I created a sub-directory called flexmonster and put the following JS file in there named mock-flexmonster.js. The js file contains Flexmonster namespace and properties that are needed in my app.
(function() {
var Flexmonster = {
Format: {},
Options: {},
Report: {},
Slice: {},
Toolbar: {},
CellData: {},
CellBuilder: {}
};
return Flexmonster;
})();
After that, I added the following plugin settings in plugins
array inside webpack.server.config.js.
new webpack.NormalModuleReplacementPlugin(
// fixes ReferenceError: window is not defined coming from flexmonster
/^flexmonster$/,
path.join(__dirname, 'src', 'server-mocks', 'flexmonster', 'mock-flexmonster.js')
)
Hello,
Thank you for reaching out to us.
Kindly note that Flexmonster is a client-side application. It does not support server-side rendering out of the box.
We recommend using the approach with the NormalModuleReplacementPlugin that you have already implemented. However, if it is critical for you, you can implement your own ng-flexmonster integration.
We hope it helps. You are welcome to write to us in case further questions arise.
Kind regards,
Nadia