How to use ng-flexmonster with Angular Universal?

Answered
Nobel asked on August 4, 2019

The issue is basically what the title says, I am using ng-flexmonster v2.7.11 with Angular 7.0.3. Now I am trying to add server-side rendering(SSR) to my application. But I am getting the following error in node server while running server.js. From the error stack trace and from looking around in ng-flexmonster's node_modules ts files, I understand that this is happening due to import of flexmonster.js file which references the browser window object that is unavailable on server.

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)

So, in this case, how can I use ng-flexmonster with SSR. Is there a workaround maybe in webpack or in some other way?

3 answers

Public
Dmytro Zvazhii Dmytro Zvazhii Flexmonster August 5, 2019

Hello,
Thank you for writing to us.
 
Flexmonster is a client-side application and it strongly relies on browser capabilities. 
We cannot guarantee that it will work as expected in the server environment.
 
Still, you can try the following workarounds to run such 3-rd party libraries: https://stackoverflow.com/questions/46849835/window-is-not-defined-angular-universal-third-library, https://medium.com/@maciejtreder/angular-server-side-rendering-with-ng-toolkit-universal-c08479ca688.
 
Please let us know if you managed to resolve the case.
Regards,
Dmytro

Public
Nobel August 5, 2019

Hi Dmytro,
Thanks for the reply. I was actually able to fix the issue by mocking flexmonster.js on the server 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')
    )

 
This solution was found in Angular's universal-starter repository issues section. Here is comment link.
 
Regards,
Nobel

Public
Dmytro Zvazhii Dmytro Zvazhii Flexmonster August 6, 2019

Hello Nobel,
We are glad that you have managed to resolve the case.
Thank you for publishing your solution here.
We hope that your positive experience will help our users to overcome similar issues.
Please let us know in case of any other question.
Regards,
Dmytro

Please login or Register to Submit Answer