Angular 7 的生产构建,其中呈现 React 组件
Production build of Angular 7 with React component rendered within
我正在将现有的 Angular 应用程序逐个迁移到 React。查看了许多选项,包括 single-spa 和 nx,但它们不可行,因为现有的应用程序是一堆可怕的脚本注入疯狂。我选择了 Zacky Pickholz 所示的半手动选项:
https://medium.com/@zacky_14189/embedding-react-components-in-angular-the-easy-way-60f796b68aef
该项目成功地在 Angular 7 应用程序中渲染了一个 React 组件(耶!)。开发构建工作正常,但是生产构建在 tsx 包装器中抛出。
ERROR in ./src/app/components/my-wrapper-rct/my-wrapper-rct.tsx
Module parse failed: Unexpected character '@' (21:2)
You may need an appropriate loader to handle this file type.
| const containerElementName = 'myWrapperRct';
|
| @Component({
| selector: 'my-wrapper-rct',
| template: `<span #${containerElementName}></span>`,
包装器类似于 Zacky 存储库中的示例:
https://github.com/zackypick/react-in-angular
看起来生产转译器忽略了 tsx 包装器,所以当 JS 遇到 @Component
它不知道如何处理它。奇怪的是,这些包似乎是在此错误之前转换和生成的。希望有人对生产构建错误有所了解。
包装器代码:
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { MyReactComponent } from 'src/components/my-react-component/MyReactComponent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'myReactComponentContainer';
@Component({
selector: 'app-my-component',
template: `<span #${containerElementName}></span>`,
styleUrls: ['./MyReactComponent.scss'],
encapsulation: ViewEncapsulation.None,
})
export class MyComponentWrapperComponent implements OnChanges, OnDestroy, AfterViewInit {
@ViewChild(containerElementName, {static: false}) containerRef: ElementRef;
@Input() public counter = 10;
@Output() public componentClick = new EventEmitter<void>();
constructor() {
this.handleDivClicked = this.handleDivClicked.bind(this);
}
public handleDivClicked() {
if (this.componentClick) {
this.componentClick.emit();
this.render();
}
}
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
const {counter} = this;
ReactDOM.render(<div className={'i-am-classy'}>
<MyReactComponent counter={counter} onClick={this.handleDivClicked}/>
</div>, this.containerRef.nativeElement);
}
}
搜索了天涯海角,没有发现任何人面临完全相同的错误。这个报告的问题让我找到了一些路径:
https://github.com/angular/angular-cli/issues/9244
经过一些实验,我需要将 aot
和 buildOptimizer
设置为 false。他们无法处理这种情况。
构建大小差异很小:8.3MB 对 8.4MB。由于目标是尽快放弃 Angular,所以我可以接受这种小幅增加。
React 在编译 tsx 后不会自动导入,因此 React 不会在生产构建(aot 或 buildoptimizer)中导入。因此,建议将以下内容添加到使用 React 组件的模块的根目录中。在我的例子中,它是一个通过路由延迟加载的模块。
import React from 'react';
window.React = React;
这会将 React 添加到您的全局命名空间,并使其在您的组件中可访问。
我正在将现有的 Angular 应用程序逐个迁移到 React。查看了许多选项,包括 single-spa 和 nx,但它们不可行,因为现有的应用程序是一堆可怕的脚本注入疯狂。我选择了 Zacky Pickholz 所示的半手动选项:
https://medium.com/@zacky_14189/embedding-react-components-in-angular-the-easy-way-60f796b68aef
该项目成功地在 Angular 7 应用程序中渲染了一个 React 组件(耶!)。开发构建工作正常,但是生产构建在 tsx 包装器中抛出。
ERROR in ./src/app/components/my-wrapper-rct/my-wrapper-rct.tsx
Module parse failed: Unexpected character '@' (21:2)
You may need an appropriate loader to handle this file type.
| const containerElementName = 'myWrapperRct';
|
| @Component({
| selector: 'my-wrapper-rct',
| template: `<span #${containerElementName}></span>`,
包装器类似于 Zacky 存储库中的示例:
https://github.com/zackypick/react-in-angular
看起来生产转译器忽略了 tsx 包装器,所以当 JS 遇到 @Component
它不知道如何处理它。奇怪的是,这些包似乎是在此错误之前转换和生成的。希望有人对生产构建错误有所了解。
包装器代码:
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { MyReactComponent } from 'src/components/my-react-component/MyReactComponent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'myReactComponentContainer';
@Component({
selector: 'app-my-component',
template: `<span #${containerElementName}></span>`,
styleUrls: ['./MyReactComponent.scss'],
encapsulation: ViewEncapsulation.None,
})
export class MyComponentWrapperComponent implements OnChanges, OnDestroy, AfterViewInit {
@ViewChild(containerElementName, {static: false}) containerRef: ElementRef;
@Input() public counter = 10;
@Output() public componentClick = new EventEmitter<void>();
constructor() {
this.handleDivClicked = this.handleDivClicked.bind(this);
}
public handleDivClicked() {
if (this.componentClick) {
this.componentClick.emit();
this.render();
}
}
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
const {counter} = this;
ReactDOM.render(<div className={'i-am-classy'}>
<MyReactComponent counter={counter} onClick={this.handleDivClicked}/>
</div>, this.containerRef.nativeElement);
}
}
搜索了天涯海角,没有发现任何人面临完全相同的错误。这个报告的问题让我找到了一些路径:
https://github.com/angular/angular-cli/issues/9244
经过一些实验,我需要将 aot
和 buildOptimizer
设置为 false。他们无法处理这种情况。
构建大小差异很小:8.3MB 对 8.4MB。由于目标是尽快放弃 Angular,所以我可以接受这种小幅增加。
React 在编译 tsx 后不会自动导入,因此 React 不会在生产构建(aot 或 buildoptimizer)中导入。因此,建议将以下内容添加到使用 React 组件的模块的根目录中。在我的例子中,它是一个通过路由延迟加载的模块。
import React from 'react';
window.React = React;
这会将 React 添加到您的全局命名空间,并使其在您的组件中可访问。