Building with AOT breaks
Hi there. I was wondering if you had any input or suggestions when trying to run ng serve --prod. At present, this breaks with the current implementation. I was attempting to use your solution (something similar) for my project, but am running up against this [probably] AOT issue.
Any help would be greatly appreciated.
The simple repro is to try to run ng serve --prod in this project.
Thank you
@zackypick Even I am facing same issue when trying to run the app in prod mode. Getting Error as follows:
ERROR ReferenceError: React is not defined render http://localhost:4300/main.a3a651f148906b293118.js:1 ngOnChanges http://localhost:4300/main.a3a651f148906b293118.js:1 checkAndUpdateNode http://localhost:4300/main.a3a651f148906b293118.js:1 checkAndUpdateNode http://localhost:4300/main.a3a651f148906b293118.js:1 checkAndUpdateNode http://localhost:4300/main.a3a651f148906b293118.js:1 prodCheckAndUpdateNode http://localhost:4300/main.a3a651f148906b293118.js:1 View_AppComponent_0 http://localhost:4300/main.a3a651f148906b293118.js:1 updateDirectives http://localhost:4300/main.a3a651f148906b293118.js:1 checkAndUpdateView http://localhost:4300/main.a3a651f148906b293118.js:1 callViewAction http://localhost:4300/main.a3a651f148906b293118.js:1 execComponentViewsAction http://localhost:4300/main.a3a651f148906b293118.js:1 checkAndUpdateView http://localhost:4300/main.a3a651f148906b293118.js:1 detectChanges http://localhost:4300/main.a3a651f148906b293118.js:1 main.a3a651f148906b293118.js:1:353090
@mkeith121 @zackypick Any help on this? Please let me know how to fix this.
@nethravikram @zackypick I found a solution in our project and I'd be happy to create a PR with those updates.
The solution I found was to dynamically import React at the point at which it's used. So instead of importing React at the top like:
import { React } from 'react';
You would use the module import in the render function like so:
import(react).then(({React}) => {
// Do something with the React object
})
I will try to make a PR today with my proposed changes. @nethravikram, let me know if you have any questions about this.
Here is a quick and dirty rewrite of the original render function with changes:
private render() {
const {counter} = this;
const reactImport = import('react').then((React) => React);
const reactDomImport = import('react-dom').then((ReactDOM) => ReactDOM);
Promise.all([reactImport, reactDomImport]).then(
([React, ReactDOM]) => {
ReactDOM.render(<div className={'i-am-classy'}>
<MyReactComponent counter={counter} onClick={this.handleDivClicked}/>
</div>, this.containerRef.nativeElement);
})
}
I didn't test the above yet, just trying to be helpful until I have time to push a PR. This approach does work for me on Angular 9 prod builds (AOT, Ivy, etc).
@mkeith121 I am getting the compiler issue with above code.
src/components/my-react-component/MyReactComponentWrapper.tsx:69:20 - error TS2339: Property 'render' does not exist on type 'typeof React'.
69 ReactDOM.render(<div className={'i-am-classy'}>
~~~~~~
Thanks!
@nethravikram I updated my original comment to fix the issue. The order of the Promises in the invocation were wrong, so ReactDOM was a variable representing React. If you update your code with what I've corrected it to, it should work.
It wasn't intended to be used as a directy copy/paste, but I'm glad it looks like it should work.
@mkeith121 This solution works. Thank you so much for the help!!
@nethravikram @zackypick I found a solution in our project and I'd be happy to create a PR with those updates.
The solution I found was to dynamically import React at the point at which it's used. So instead of importing React at the top like:
import { React } from 'react';You would use the module import in the render function like so:
import(react).then(({React}) => { // Do something with the React object })I will try to make a PR today with my proposed changes. @nethravikram, let me know if you have any questions about this.
Here is a quick and dirty rewrite of the original render function with changes:
private render() { const {counter} = this; const reactImport = import('react').then((React) => React); const reactDomImport = import('react-dom').then((ReactDOM) => ReactDOM); Promise.all([reactImport, reactDomImport]).then( ([React, ReactDOM]) => { ReactDOM.render(<div className={'i-am-classy'}> <MyReactComponent counter={counter} onClick={this.handleDivClicked}/> </div>, this.containerRef.nativeElement); }) }I didn't test the above yet, just trying to be helpful until I have time to push a PR. This approach does work for me on Angular 9 prod builds (AOT, Ivy, etc).
It worked with ng build --prod but still not working with server-side rendering, even though I checked isPlatformBrowser before rendering.
@nethravikram @zackypick I found a solution in our project and I'd be happy to create a PR with those updates.
The solution I found was to dynamically import React at the point at which it's used. So instead of importing React at the top like:
import { React } from 'react';You would use the module import in the render function like so:
import(react).then(({React}) => { // Do something with the React object })I will try to make a PR today with my proposed changes. @nethravikram, let me know if you have any questions about this.
Here is a quick and dirty rewrite of the original render function with changes:
private render() { const {counter} = this; const reactImport = import('react').then((React) => React); const reactDomImport = import('react-dom').then((ReactDOM) => ReactDOM); Promise.all([reactImport, reactDomImport]).then( ([React, ReactDOM]) => { ReactDOM.render(<div className={'i-am-classy'}> <MyReactComponent counter={counter} onClick={this.handleDivClicked}/> </div>, this.containerRef.nativeElement); }) }I didn't test the above yet, just trying to be helpful until I have time to push a PR. This approach does work for me on Angular 9 prod builds (AOT, Ivy, etc).
It works, thanks for sharing it!