angular: bug(elements): importing `createCustomElement` breaks SSR
I’m submitting a…
[x] Bug report
Current behavior
Importing createCustomElement
throws an error during angular universal server side rendering.
Note: it appears that simply importing the function throws the error. Currently, even the following code throws an error during SSR:
import {createCustomElement} from '@angular/elements';
. . .
export class AppModule {
constructor() {
if (false as any) {
createCustomElement
}
}
}
Error:
var elProto = Element.prototype;
^
ReferenceError: Element is not defined
at Object.<anonymous> (/user/apps/tests/universal-starter/dist/server.js:126911:15)
at __webpack_require__ (/user/apps/tests/universal-starter/dist/server.js:20:30)
at Object.@angular/elements (/user/apps/tests/universal-starter/dist/server.js:126796:18)
at __webpack_require__ (/user/apps/tests/universal-starter/dist/server.js:126326:30)
at Object../src/app/app.module.ts (/user/apps/tests/universal-starter/dist/server.js:126453:18)
at __webpack_require__ (/user/apps/tests/universal-starter/dist/server.js:126326:30)
at Object../src/app/app.server.module.ngfactory.js (/user/apps/tests/universal-starter/dist/server.js:126504:11)
at __webpack_require__ (/user/apps/tests/universal-starter/dist/server.js:126326:30)
at Object../src/main.server.ts (/user/apps/tests/universal-starter/dist/server.js:126712:37)
at __webpack_require__ (/user/apps/tests/universal-starter/dist/server.js:126326:30)
Expected behavior
Ideally, custom elements could be rendered via SSR normally, but, at minimum, it’d expect the ability to import createCustomElement
and then conditionally call it using isPlatformBrowser()
so that the custom element was only defined + registered on the client side.
Minimal reproduction of the problem with instructions
A reproduction of the issue can be found here: https://github.com/thefliik/universal-starter/tree/elements-ssr-bug. Simply clone the repo and run yarn build:ssr && yarn serve:ssr
.
The repo was made by cloning the @angular/universal-starter
repo, adding @angular/elements
to project.json
, and updating app.module.ts
with:
import {createCustomElement} from '@angular/elements';
...
export class AppModule {
constructor() {
/**
* # Note
*
* Remove this statement and no errors are thrown. I *think* this is because
* tree shaking will remove the `createCustomElement` import statement without
* this line.
*/
if (false as any) {
createCustomElement
}
}
}
What is the motivation / use case for changing the behavior?
To allow custom elements built with @angular/elements
to be used in a SSR app.
My specific use case for angular elements is as a work around for issue #14324 (& #17168).
Environment
Angular CLI: 6.0.0
Node: 8.9.1
OS: darwin x64
Angular: 6.0.5
... animations, common, compiler, core, elements, forms, http
... platform-browser, platform-browser-dynamic, platform-server
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.6.0
@angular-devkit/build-angular 0.6.0
@angular-devkit/build-optimizer 0.6.0
@angular-devkit/core 0.6.0
@angular-devkit/schematics 0.6.0
@angular/cli 6.0.0
@angular/compiler-cli 6.0.0
@angular/language-service 6.0.0
@ngtools/webpack 6.0.0
@schematics/angular 0.6.0
@schematics/update 0.6.0
rxjs 6.0.0
typescript 2.7.2
webpack 4.6.0
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 19 (16 by maintainers)
Commits related to this issue
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): add SSR guard for missing global prototype Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches function ... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): lazily check matches fixes #24551 — committed to PatrickJS/angular by PatrickJS 4 years ago
- fix(elements): lazily check matches fixes #24551 style(elements): correct types style: lint — committed to PatrickJS/angular by PatrickJS 4 years ago
- fix(elements): lazily check matches fixes #24551 style(elements): correct types style: lint style(element): lint style(elements): lint — committed to PatrickJS/angular by PatrickJS 4 years ago
- fix(elements): detect matchesSelector prototype without IIFE Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches functi... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): detect matchesSelector prototype without IIFE Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the matches functi... — committed to CaerusKaru/angular by CaerusKaru 4 years ago
- fix(elements): detect matchesSelector prototype without IIFE (#37799) Although in SSR we patch the global prototypes with DOM globals like Element and Node, this patch does not occur before the match... — committed to angular/angular by CaerusKaru 4 years ago
As a work around, you can conditionally import
createCustomElement
withconst { createCustomElement } = require('@angular/elements')
.For example:
@ericmartinezr thanks for the suggestion. I had tried the solution suggested in that issue before reporting this and, while it does eliminate the
var elProto = Element.prototype;
error, it results in a new error.Update (the new error is…)
Adding:
to
server.ts
(which I think is similar to #24116, @gkalpak ?) eliminates thevar elProto = Element.prototype;
error but instead results in the following error:This error is raised under the same conditions as before (i.e. simply importing
createCustomElement()
throws the error).It’s actually a problem of Angular CLI, for server-side rendering for custom elements, it should always use
"target": "es2015"
rather than requiring the polyfills (which is not compatible with node).But currently Angular CLI will always skip bundle of
@angular
packages and forwarding to UMD bundles, which are es5 code which doesn’t fulfill Custom Elements requirement (realclass
type).