详解Angular5/Angular6项目如何添加热更新(HMR)功能

下面是详解Angular5/Angular6项目如何添加热更新(HMR)功能的完整攻略。

需要的前置条件

  • Angular CLI
  • Angular5或Angular6项目

步骤一:安装相关依赖

首先我们需要安装@angularclass/hmrwebpack-bundle-analyzer插件。运行下面的命令进行安装:

npm install --save-dev @angularclass/hmr webpack-bundle-analyzer

步骤二:修改app.module.ts

app.module.ts中,我们需要添加一些代码来实现HMR。具体代码如下:

import { NgModule, ApplicationRef, NgModuleRef } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { createNewHosts, removeNgStyles } from '@angularclass/hmr';

@NgModule({
  imports: [BrowserModule],
})
export class AppModule {
  constructor(private appRef: ApplicationRef, private moduleRef: NgModuleRef<any>) {}

  hmrOnInit(store: any) {
    if (!store || !store.state) {
      return;
    }
    console.log('HMR store', JSON.stringify(store, null, 2));
    if ('restoreInputValues' in store) {
      store.restoreInputValues();
    }
    const cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
    this.moduleRef.destroy();
    this.appRef.detachView(cmpLocation);
    // Create new host elements, rebuild styles
    const elements = createNewHosts(cmpLocation);
    // Reload state if it exists
    if ('disposeOldHosts' in this.moduleRef) {
      (<any>this.moduleRef).disposeOldHosts();
    }
    this.moduleRef = null;
    // Bootstrap the app
    setTimeout(() => {
      this.moduleRef = this.compiler.compileModuleSync(AppModule);
      const ngModule = this.moduleRef.create(this.injector, elements);
      this.appRef.attachView(ngModule.hostView);
    }, 0);
    // Restore input values
    if ('restoreInputValues' in store) {
      setTimeout(store.restoreInputValues, 0);
    }
    // Destroy old subscription if needed
    if (!this.subscription) {
      this.subscription = this.router.events.subscribe(event => {
        if (event instanceof NavigationEnd) {
          // Restore scroll position
          const restoredValues = store && store.state && store.state[this.router.url];
          if (restoredValues) {
            setTimeout(() => this.viewportScroller.scrollToPosition(restoredValues), 0);
          }
        }
      });
    }
  }

  hmrOnDestroy(store: any) {
    if (this.moduleRef) {
      this.appRef.detachView(this.appRef.components.map(cmp => cmp.location.nativeElement));
      this.moduleRef.destroy();
    }
    this.moduleRef = null;
    this.subscription.unsubscribe();
    this.subscription = null;
  }

  hmrAfterDestroy(store: any) {
    // Display new elements
    store.disposeOldHosts = createNewHosts(this.appRef.components.map(cmp => cmp.location.nativeElement));
    // Save scroll position
    store.state = {};
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        store.state[this.router.url] = this.viewportScroller.getScrollPosition();
      }
    });
  }
}

步骤三:修改webpack配置

webpack.dev.js文件中,找到module.exports对象中的entry选项,并添加以下代码:

entry: {
  polyfills: [...]
  vendor: [...],
  main: [
    './src/main.ts' // <-- Add this line
  ]
},

接下来,在同一个文件中找到module.exports对象中的output选项,并添加以下代码:

output: {
  path: helpers.root('dist'),
  filename: '[name].bundle.js',
  sourceMapFilename: '[name].map',
  chunkFilename: '[id].chunk.js',
  publicPath: '/',
  libraryTarget: 'var'
},

然后,在同一个文件中找到module.exports对象中的plugins选项,并添加以下代码:

new AngularCompilerPlugin({
  // ...
  "define": {
    "HMR": true
  },
  // ...
})

最后,在同一个文件中的末尾添加以下代码:

module.exports = function(env) {
  var hmrEnabled = env && env.HMR === true;
  // ...
  if (hmrEnabled) {
    config.plugins.push(new webpack.HotModuleReplacementPlugin());
    Object.keys(config.entry).forEach(function (entryName) {
      config.entry[entryName] = config.entry[entryName].concat('webpack-hot-middleware/client');
    });
  }
  // ...
  return config;
};

步骤四:启动HMR

运行以下命令启动HMR:

ng serve --hmr

运行成功后,修改代码并保存即可看到热更新的效果。

示例一:开启HMR并监测打包后的大小

运行以下命令启动HMR并监测打包后的大小:

ng serve --hmr --stats-json

启动成功后,可以在localhost:4200看到应用,并且在stats.json文件中得到打包后的大小。

示例二:在正在运行的应用程序中手动启用HMR

可以手动启用HMR来避免在重启应用程序之前等待HMR启用的时间。

添加以下代码:

import { ApplicationRef, NgModuleRef } from '@angular/core';
import { getNgZone } from '@angularclass/hmr';
declare const System: any;

export const hmrBootstrap = (
  module: any,
  bootstrap: () => Promise<NgModuleRef<any>>
) => {
  let ngZone: NgZone;
  module.hot.accept();
  bootstrap().then((ngModuleRef: NgModuleRef<any>) => {
    ngZone = getNgZone(ngModuleRef.injector);
    module.hot.dispose(() => {
      const appRef: ApplicationRef = ngModuleRef.injector.get(ApplicationRef);
      const elements = appRef.components.map(c => c.location.nativeElement);
      const makeVisible = createNewHosts(elements);
      ngModuleRef.destroy();
      ngZone.run(() => {
        const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
        hmrBootstrap(module, bootstrap);
      });
    });
  });
};

然后在main.ts中添加以下代码:

if (module['hot']) {
  hmrBootstrap(module, bootstrap);
} else {
  bootstrap();
}

运行应用后,在需要启用HMR的地方输入以下代码:

declare const require: any;
const hotFix = require('webpack/hot/overlay');
hotFix.handle(module);

手动启用HMR后,修改代码并保存即可看到热更新的效果。

综上所述,这就是“详解Angular5/Angular6项目如何添加热更新(HMR)功能”的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Angular5/Angular6项目如何添加热更新(HMR)功能 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • Node.js 多进程处理CPU密集任务的实现

    Node.js是单线程的,这意味着它只有一个进程,一次只能处理一个请求。随着CPU的性能不断提高,处理CPU密集型任务的需求也日益增加。因此,为了更好地利用CPU资源,Node.js提供了多进程模块,可以通过在不同的进程中执行代码来并行处理任务,从而提高处理速度。 1. Node.js的多进程模块cluster Node.js多进程处理的核心模块是clust…

    node js 2023年6月8日
    00
  • 如何删除node_modules重新安装的方法步骤

    下面是删除node_modules并重新安装的方法步骤: 步骤一:打开终端 在电脑中打开终端,进入需要删除node_modules的项目文件夹目录。 步骤二:删除node_modules 在终端中输入以下命令: rm -rf node_modules 该命令将会删除项目文件夹中的node_modules文件夹及其所有内容,包括所有的依赖包。 步骤三:清除np…

    node js 2023年6月8日
    00
  • 解决新建一个vue项目过程中遇到的问题

    当我们在新建一个vue项目的过程中,有可能会遇到一些问题,这里提供一些解决这些问题的攻略。 问题1:无法使用vue-cli 问题描述 在使用vue-cli新建项目时,可能会遇到以下错误提示: ‘vue’ 不是内部或外部命令,也不是可运行的程序或批处理文件。 解决方法 出现上述错误,通常是因为在命令行中找不到vue命令,需要安装vue-cli。我们可以通过以下…

    node js 2023年6月8日
    00
  • JS中如何优雅的使用async await详解

    下面是JS中如何优雅的使用async/await的详细攻略。 异步编程的不足 JavaScript是一门事件驱动(event-driven)和非阻塞(non-blocking)的编程语言。因为这个特性,它非常适合在浏览器和服务器端应用程序中进行异步编程。然而,异步编程往往会导致代码复杂、难以维护和调试,在回调地狱(callback hell)中陷入困境。 为…

    node js 2023年6月8日
    00
  • Nest.js系列学习之初识nest项目框架及服务

    当谈到现代Web应用程序开发时,Nest.js是一个值得注意的框架,它基于Node.js,使用了TypeScript和面向对象的编程模式。本文将向您介绍Nest.js框架及其服务的基础知识。 开始篇 Nest.js的介绍 Nest.js主要用于构建可伸缩、高度可维护的Web应用程序。它封装了很多常用的库和技术,在设计上基于AngularJS的思想,提供了一种…

    node js 2023年6月8日
    00
  • node中Express 动态设置端口的方法

    设置Express应用程序的端口是一个很常见的需求,可以通过以下两种方式实现动态设置端口: 1. 通过环境变量 可以通过设置环境变量来动态地设置Express应用程序的端口。这在使用Docker或类似的环境时非常有用,因为容器端口通常是动态分配的。 首先在应用程序中读取环境变量: const port = process.env.PORT || 3000; …

    node js 2023年6月8日
    00
  • 浅析node应用的timing-attack安全漏洞

    浅析node应用的timing-attack安全漏洞 什么是timing-attack安全漏洞 timing-attack安全漏洞是指黑客能够通过研究特定的计时规律来发现安全漏洞或者密码,从而实现非法访问或者窃取敏感信息的目的。该攻击方法主要利用计算机在运行指令时执行速度的差异来实现,通过对两个不同指令的响应时间进行比较,来推算出信息。 在node应用中,通…

    node js 2023年6月8日
    00
  • TypeScript实现类型安全的EventEmitter

    下面是 TypeScript 实现类型安全的 EventEmitter 的完整攻略。 什么是 TypeScript EventEmitter? EventEmitter 是 Node.js 中常用的一个模块,用于实现事件机制。可以通过绑定事件来监听对象或函数的状态变化,从而实现异步回调。 TypeScript 在 EventEmitter 的基础上实现了类型…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部