Angular 4,热模块替换附加而不是替换

Posted

技术标签:

【中文标题】Angular 4,热模块替换附加而不是替换【英文标题】:Angular 4, Hot module replacement appending instead of replacing 【发布时间】:2018-07-17 23:07:01 【问题描述】:

我遇到了一个奇怪的问题,热模块替换在我的应用程序中一直运行良好一段时间,但在最近的某个时候,它发生了变化。它不是替换页面上的特定组件,而是将组件附加到页面顶部,并且仍然在下面留下旧组件的副本。

我在谷歌上搜索了所有内容,并试图找出发生了什么变化,但运气不佳。我的 WebPack 文件根本没有太大变化。

这是我的Webpack.js 文件。

角度 4

Visual Studio 2017

.Net Core 2.0

【问题讨论】:

奇数。我从来没有听说过这样的事情。我在您的 webpack 配置中没有发现任何问题。我建议进行二进制搜索以查找导致它的更改-返回到您知道它有效的提交,然后在当时和现在之间选择一个提交并查看它是否在那里有效....重复直到找到该提交打破它。不幸的是,有时这是唯一的方法。 如果你使用 Angular / SPA 模板,你有 boot.client.ts 吗? 【参考方案1】:

接受的答案不适用于角度 5。

几个小时后,我终于找到了适合我的解决方案。

首先安装@angularclass/hmr:

npm install --save-dev @angularclass/hmr

然后使用这个boot.browser.ts(有些调用boot.client.ts):

import 'reflect-metadata';
import 'zone.js';
import 'bootstrap';
import  enableProdMode, NgModuleRef, ApplicationRef  from '@angular/core';
import  platformBrowserDynamic  from '@angular/platform-browser-dynamic';
import  AppModule  from './app/app.module.browser';
import  createNewHosts  from '@angularclass/hmr';

const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);

if (module.hot) 
    let ngModule: NgModuleRef<any>;
    module.hot.accept();

    bootstrap().then(mod => ngModule = mod);
    module.hot.dispose(() => 
        const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
        const elements = appRef.components.map(c => c.location.nativeElement);
        const makeVisible = createNewHosts(elements);
        ngModule.destroy();
        makeVisible();
    );
 else 
    enableProdMode();

到目前为止,一切正常。

【讨论】:

【参考方案2】:

我在使用 .NET Core / Angular 模板时遇到过这种情况。这个 sn-p 应该确保旧组件被删除,并在热模块更换处置钩子期间创建一个新的新组件。

如果你有一个boot.client.ts,看看它是否包含这个:

if (module.hot) 
    module.hot.accept();
    module.hot.dispose(() => 

        // Before restarting the app, we create a new root element and dispose the old one
        const oldRootElem = document.querySelector('app');
        const newRootElem = document.createElement('app');

        oldRootElem!.parentNode!.insertBefore(newRootElem, oldRootElem);
        modulePromise.then(appModule => appModule.destroy());
    );

【讨论】:

这非常接近。我在我的应用程序的根级别添加了一个新组件来处理往返登录屏幕的路由。它的名称与“应用程序”不同。当我将上面的代码更改为新名称时,一切又开始工作了。

以上是关于Angular 4,热模块替换附加而不是替换的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Angular 2 Webpack 热模块替换

webpack性能优化

webpack性能优化

06HMR热加载

Angular 2 - 替换历史而不是推送

webpack学习之—— 模块热替换(Hot Module Replacement)