Skip to content

add support for angular2-universal #140

Description

@AnderssonPeter

It seems this does not work with angular2-universal as it gives a error about the window object not exist.

Are there any plans to add support for it?

Activity

  1. MarkPieszak commented on Oct 17, 2016

    @MarkPieszak

    From looking at it at a glance, it looks like this library requires jQuery/hammerJS and has a few small references to window (all which don't exist on the server-side).

    Unless these requirements were removed, I'd imagine this would be more in our ballpark on the Angular Universal side to at least (attempt) to support some of these features, which would slow down server rendering, or at least ignore them somehow (which means they just won't get rendered on the server-side). You can see the issue here (angular/universal#534), but it's nothing something I imagine we'll be able to implement soon as it's a huge overhaul. :(

  2. AnderssonPeter commented on Oct 18, 2016

    @AnderssonPeter
    Author

    @MarkPieszak Ok thanks i guess ill have to look for a different CSS framework, do you know if there is a list with compatible css frameworks? (the only one i know is bootstrap).

  3. MarkPieszak commented on Oct 18, 2016

    @MarkPieszak

    ng2-bootstrap
    https://github.com/valor-software/ng2-bootstrap

    ng-bootstrap (think they have one issue with Carousel remaining to work perfectly with Universal)
    https://github.com/ng-bootstrap/ng-bootstrap

    Both work very well with Universal, they have no jQuery dependencies and have fixed any window/document references/etc.

    Not sure why both teams didn't just combine their efforts :(
    @AnderssonPeter

  4. rubyboy commented on Apr 30, 2017

    @rubyboy
    Contributor

    After moving to the Angular CLI this is now part of the library.

  5. bisubus commented on May 3, 2017

    @bisubus

    @rubyboy How so? The library still relies on browser globals in entry point and custom-event-polyfill.

  6. rubyboy commented on May 4, 2017

    @rubyboy
    Contributor

    @bisubus is there anything we can do in the library to support angular universal? I thought we'd need support in MaterializeCSS itself.

  7. bisubus commented on May 4, 2017

    @bisubus

    @rubyboy Definitely yes. I tried to go Universal before, and the ng2-materialize was one of the few show-stoppers.

    The app will fail to bootstrap if MaterializeModule is included on server side, and it will fail if it's not (at least because materialize directive is used in templates).

    Should we assume that materialize directive doesn't do any DOM changes that would be crucial to pre-render and it's safe to make the whole module a noop on server side by default?

  8. rubyboy commented on May 5, 2017

    @rubyboy
    Contributor

    @bisubus I'd actually assume that Materialize does do DOM changes. Worth checking in the original repo.
    Do you have a suggestion how to add support for universal in the angular2-materialize library? Happy for a PR or work with you together on getting that implemented.
    Thanks!

  9. bisubus commented on May 5, 2017

    @bisubus

    @rubyboy Sure, we'll see how things go.

    I've checked how it's going in Angular Material, and it looks like it still isn't ready for Universal, see angular/components#308, but there's supposed to be a separate entry point for server side, like angular2-materialize/server import. Makes sense.

    The good thing is that in Materialize most visuals are implemented with CSS, while JS does interaction with user. Until JS part will be rewritten to native Angular DOM manipulation like @MarkPieszak suggested, I guess that stubbing materialize directive and ignoring window stuff for server side is the only reasonable way.

    Another direction I see is that browser part (angular2-materialize import) has to be refactored a bit to make it more suitable for server side if a user wants to render it with jsdom or something (not even sure if jsdom can handle jQuery and Waves and other complex DOM stuff). Currently mocking global.window will result in incorrect framework behaviour, angular/angular#16545 . Since there's no built-in window service, I guess it makes sense to introduce something like MATERIALIZE_WINDOW provider that defaults to window global and can be easily substituted with jsdom. I guess in this case window.document from MATERIALIZE_WINDOW should be preferred over built-in DOCUMENT provider, too, since implementations will be different on server side.

    What do you think?

  10. reopened this on May 6, 2017
  11. rubyboy commented on May 6, 2017

    @rubyboy
    Contributor

    I've reopened this issue, to keep it in the correct state. @bisubus as you said, we do need to put some effort in supporting universal.
    Your suggestions make sense. I've never tried using universal, so it's hard for me to advocate on the correct approach. If we can keep the changes minimal, another option would be to have 2 entry points, to allow different imports (import 'angular2-materialize' vs. import 'angular2-materialize-universal', or something like that?). That would make the maintenance much easier, if the shared code inside the directly and accompanying classes is the same.

  12. susheelbanyal commented on Aug 9, 2017

    @susheelbanyal

    Hi there, It would be great help if anyone can tell me, how to remove the window is not defined issue in angular2-materialize with universal

  13. bisubus commented on Aug 9, 2017

    @bisubus

    @susheelbanyal To my knowledge, it's currently better to not include angular2-materialize module on server side at all and stub its directives instead.

  14. susheelbanyal commented on Aug 9, 2017

    @susheelbanyal

    How can we do that? any code sample?

  15. 1 remaining item

  16. bisak commented on Sep 17, 2017

    @bisak

    I'm also banging my head against the wall trying to implement Angular Universal with materialize. The error I get is the following...

    C:\Development\Tests\node_modules\angular2-materialize\dist\materialize-module.js:1
    (function (exports, require, module, __filename, __dirname) { import { NgModule } from '@angular/core';
                                                                  ^^^^^^
    
    SyntaxError: Unexpected token import
        at createScript (vm.js:74:10)
        at Object.runInThisContext (vm.js:116:10)
        at Module._compile (module.js:588:28)
        at Object.Module._extensions..js (module.js:635:10)
        at Module.load (module.js:545:32)
        at tryModuleLoad (module.js:508:12)
        at Function.Module._load (module.js:500:3)
        at Module.require (module.js:568:17)
        at require (internal/module.js:11:18)
        at Object.JbiC (C:\Development\Tests\dist\dist-server\main.bundle.js:1:7632)
    
    

    That's a major bummer. Had I known I'd run into such issues I wouldn't have started a project with materialize. Had no idea at the time that I'd need to use Angular Universal :/

  17. bisubus commented on Sep 17, 2017

    @bisubus

    @biskazz The issue doesn't have to do anything with Universal or this package but is specific to your build process. You may also try allowJS option.

  18. ssatz commented on Dec 22, 2017

    @ssatz

    I have successfully used angular2 materialize in angular universal project.
    All you need to do is install domino.
    and add below code to server files

    const domino = require('domino');
    const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html'), 'utf8').toString();
    const win = domino.createWindow(template);
    global['window'] = win;
    global['document'] = win.document;
    global['$'] = require('jQuery');
    global['jQuery '] = require('jQuery');
    global['Materialize'] = win.Materialize;
    
  19. mpunit2530 commented on Feb 28, 2018

    @mpunit2530

    @ssatz can you share the code here. I am facing the same issue. I have added the above code but failing at Cannot set property 'default' of undefined @ exports.default = Materialize.

  20. ssatz commented on Mar 1, 2018

    @ssatz

    @karunya2530 : find the below gist link for server.ts file
    https://gist.github.com/ssatz/9e894070af27a7b9233ff25eb6f8cc2d
    I think this is something to do with webpack bundle import. if the above implementation is not working then share your tsconfig file

    EDIT: Ignore the above gist file, it is for latest alpha version materialize css without jquery.
    Here is the version with jquery

    import 'zone.js/dist/zone-node';
    import 'reflect-metadata';
    const domino = require('domino');
    import { enableProdMode } from '@angular/core';
    import { ngExpressEngine } from '@nguniversal/express-engine';
    import * as express from 'express';
    import { join } from 'path';
    import { readFileSync } from 'fs';
    
    // Faster server renders w/ Prod mode (dev mode never needed)
    enableProdMode();
    
    // Express server
    const app = express();
    const compression = require('compression');
    const PORT = process.env.PORT || 3000;
    const DIST_FOLDER = join(process.cwd(), 'dist');
    
    // Our index.html we'll use as our template
    const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html'), 'utf8').toString();
    const win = domino.createWindow(template);
    global['window'] = win;
    global['document'] = win.document;
    global['$'] = require('jQuery');
    global['jQuery '] = global['$'];
    global['Materialize'] = win.Materialize;
    // * NOTE :: leave this as require() since this file is built Dynamically from webpack
    const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
    
    const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
    app.use(compression());
    
    app.engine('html', ngExpressEngine({
        bootstrap: AppServerModuleNgFactory,
        providers: [
            provideModuleMap(LAZY_MODULE_MAP)
        ]
    }));
    
    
    app.set('view engine', 'html');
    app.set('views', join(DIST_FOLDER, 'browser'));
    
    // Server static files from /browser
    app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), { maxAge: '1y' }));
    
    // All regular routes use the Universal engine
    app.get('*', (req, res) => {
        res.render('index', {
            req: req,
            res: res
        });
    });
    
    // Start up the Node server
    app.listen(PORT, () => {
        console.log(`Node server listening on http://localhost:${PORT}`);
    });
    
  21. mpunit2530 commented on Mar 9, 2018

    @mpunit2530
  22. ssatz commented on Mar 9, 2018

    @ssatz

    @karunya2530: here is the sample repo
    https://github.com/ssatz/Angular-SSR-Service-Worker

  23. mpunit2530 commented on Mar 13, 2018

    @mpunit2530

    Hi Satish,

    I did followed the sample repo but yet i am facing this error
    factory(jQuery, Hammer);
    ^

    ReferenceError: Hammer is not defined

    Do you have any idea to resolve this ??

  24. ssatz commented on Mar 13, 2018

    @ssatz
  25. mpunit2530 commented on Mar 13, 2018

    @mpunit2530

    Hi,
    I have achieved though, but i am getting now this error..

    app\node_modules\domino\lib\utils.js:41
    throw new Error("NotYetImplemented");
    Error: NotYetImplemented
    at HTMLCanvasElement.exports.nyi (app\node_modules\domino\lib\utils.js:41:9)

  26. mpunit2530 commented on Mar 13, 2018

    @mpunit2530

    I think i am using chart.js and this is causing the server.js to fail to execute. Do you have any idea on this ??

  27. ssatz commented on Mar 13, 2018

    @ssatz

    checkout the link here
    https://github.com/angular/universal

    import { PLATFORM_ID } from '@angular/core';
     import { isPlatformBrowser, isPlatformServer } from '@angular/common';
     
     constructor(@Inject(PLATFORM_ID) private platformId: Object) { ... }
     
     ngOnInit() {
       if (isPlatformBrowser(this.platformId)) {
          // Client only code.
          ...
       }
       if (isPlatformServer(this.platformId)) {
         // Server only code.
         ...
       }
     }
    

    note : mail me sathish.thi[@]gmail.com . I won't reply here

  28. joscmw95 commented on May 6, 2018

    @joscmw95
    Collaborator

    Initially I followed @ssatz's way to circumvent the problem of not having the window object during SSR.
    However, after some time I realize, because domino wasn't able to provide proper DOM API, the directive has been suspiciously causing issues with Node's memory usage -- memory leak due to GC not able to clean up the problematic directives.

    Since these Directives aren't very much useful in SSR, it is better to gracefully disable them via platform checking.

  29. ssatz commented on May 6, 2018

    @ssatz

    @joscmw95 👍 Seems to be awesome.
    Memory leakage would be by jQeury & jQuery dependencies.

  30. tuffant21 commented on Aug 24, 2018

    @tuffant21

    As far as I am aware, materialize-css version 1.0.0-rc.2 no longer requires jquery. So technically, this could be closed if angular2-materialize were to support that version.

    Maybe? @rubyboy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions