Repository navigation
add support for angular2-universal #140
Description
Activity
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. :(
@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).
ng2-bootstrap
https://github.com/valor-software/ng2-bootstrapng-bootstrap (think they have one issue with Carousel remaining to work perfectly with Universal)
https://github.com/ng-bootstrap/ng-bootstrapBoth 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 :(
@AnderssonPeterAfter moving to the Angular CLI this is now part of the library.
@rubyboy How so? The library still relies on browser globals in entry point and custom-event-polyfill.
@bisubus is there anything we can do in the library to support angular universal? I thought we'd need support in MaterializeCSS itself.
@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
materializedirective is used in templates).Should we assume that
materializedirective 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?@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!@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/serverimport. 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
materializedirective and ignoringwindowstuff for server side is the only reasonable way.Another direction I see is that browser part (
angular2-materializeimport) has to be refactored a bit to make it more suitable for server side if a user wants to render it withjsdomor something (not even sure if jsdom can handle jQuery and Waves and other complex DOM stuff). Currently mockingglobal.windowwill 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 towindowglobal and can be easily substituted withjsdom. I guess in this casewindow.documentfrom MATERIALIZE_WINDOW should be preferred over built-in DOCUMENT provider, too, since implementations will be different on server side.What do you think?
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.Reacted by RogueAIHi there, It would be great help if anyone can tell me, how to remove the
window is not definedissue inangular2-materializewithuniversal@susheelbanyal To my knowledge, it's currently better to not include
angular2-materializemodule on server side at all and stub its directives instead.How can we do that? any code sample?
1 remaining item
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 :/
@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
allowJSoption.I have successfully used angular2 materialize in angular universal project.
All you need to do is install domino.
and add below code to server filesconst 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;Reacted by RogueAI, Paweł Hertman and sathish@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.
@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 fileEDIT: Ignore the above gist file, it is for latest alpha version materialize css without jquery.
Here is the version with jqueryimport '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}`); });- Hi Sathish, How are you doing, hope doing well. This is punit here, i comment on one of the github issue for the mentioned subject and u shared me the server.ts as you can see in mail trial i have used same server.ts contents and code as you wrote, but i am facing some issue with materializecss still, is it possible for you to share me webpack.config.js and package.json contents urgently because i am stucked to this issue from so many days and i have tried all posible solutions but i am not getting it done . It would be great help from you if you could help to solve this issue. You can reply me on the same email. Will wait for response. Thanks in advance for your help and support Regards, Punit…On Thu, 1 Mar 2018, 13:39 sathish, ***@***.***> wrote: @karunya2530 <https://github.com/karunya2530> : find the below gist link for server.ts file https://gist.github.com/ssatz/9e894070af27a7b9233ff25eb6f8cc2d <http://url> — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#140 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AjNzlC5ycfqO-TsC2sNBEeV4RDCd3NJEks5tZ6zOgaJpZM4KZCh0> .
@karunya2530: here is the sample repo
https://github.com/ssatz/Angular-SSR-Service-WorkerHi 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 ??
- Hi, i think you need to install the hammerjs . Materialize css depends on hammerjs for touch interface. Note: This seems to be a long trail. You can PM me via mail. Best Regards, sathish kumar…On Tue, Mar 13, 2018 at 12:04 PM, karunya2530 ***@***.***> wrote: 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 ?? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#140 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AGkq0kYlY2M0F_PoqO3dTqYdK7xvtJVKks5td2hfgaJpZM4KZCh0> .
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)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 ??
checkout the link here
https://github.com/angular/universalimport { 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
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.
@joscmw95 👍 Seems to be awesome.
Memory leakage would be by jQeury & jQuery dependencies.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
It seems this does not work with
angular2-universalas it gives a error about thewindowobject not exist.Are there any plans to add support for it?