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

yizhihongxing

下面是详解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开发中的express-session

    1. 什么是 express-session express-session 是 Node.js 开发中的一个 session 中间件,由于 HTTP 协议本身是无状态的,所以使用 session 机制来维护客户端与服务端之间的状态。 session 机制的实现方式通常有两种: 使用 cookie,将 session id 存放在客户端浏览器的 cookie…

    node js 2023年6月8日
    00
  • node.js中的fs.openSync方法使用说明

    node.js中的fs.openSync方法使用说明 fs.openSync() 方法用于使用文件路径字符串之前,获取对文件的访问。该方法通过一个文件路径字符串,与一组选项对象进行调用,返回一个整数(文件描述符),代表了一个通过该文件描述符可以进行操作的文件。 方法语法 fs.openSync(path[, flags[, mode]]) 方法参数 path…

    node js 2023年6月8日
    00
  • 利用NPM淘宝的node.js镜像加速nvm

    当我们在国内使用NVM(Node Version Manager)来管理Node.js的版本时,下载Node.js的速度很慢,甚至很难下载下来,因为官方的Node.js下载可能需要访问到国外的服务器。 为了解决这个问题,我们可以使用淘宝镜像提供的Node.js二进制包。下面是具体步骤: 步骤一:安装NVM 在命令行(terminal)运行以下命令安装NVM:…

    node js 2023年6月8日
    00
  • nodejs中内置模块fs,path常见的用法说明

    下面是对“nodejs中内置模块fs,path常见的用法说明”的攻略。 fs模块的常见用法 fs模块提供了许多文件系统相关的功能,比如读写文件、创建目录等。 读取文件的方法 const fs = require(‘fs’); // 异步读取文件 fs.readFile(‘path/to/file’, ‘utf-8’, function(err, data) …

    node js 2023年6月8日
    00
  • nodejs中实现修改用户路由功能

    下面是详细的攻略: 准备 在开始实现前,需要先安装Node.js和Express框架。步骤如下: 安装 Node.js:从 Node.js 官网 下载并安装包。 创建项目文件夹。 打开终端,进入到项目文件夹目录下。 输入以下命令安装 Express 框架: npm install express –save 其中,–save参数用于将安装的依赖项保存到项…

    node js 2023年6月8日
    00
  • node后端与Vue前端跨域处理方法详解

    一、 前言 在前后端分离的开发模式中,前端Vue与后端Node进行沟通交互涉及到跨域问题。下面我们来详细讲解node后端与Vue前端跨域处理方法。 二、 跨域原理 同源策略(Same Origin Policy)要求网页只能访问与本网页同一个域名、端口、协议的网页。也就是说,一个源的的脚本仅能读写属于该源的窗口和文档。如果读写的目标不是同源的,就会出现跨域问…

    node js 2023年6月8日
    00
  • JavaScript中使用Substring删除字符串最后一个字符

    在JavaScript中,可以使用Substring函数来截取字符串的一部分。如果要删除字符串的最后一个字符,可以使用Substring函数配合字符串的length属性进行操作。 以下是具体步骤: 获取字符串长度 let str = "Hello World"; let strLength = str.length; 以上代码中,我们定义…

    node js 2023年6月8日
    00
  • node.js Promise对象的使用方法实例分析

    关于“node.js Promise对象的使用方法实例分析”,我准备了以下攻略,希望对你有所帮助。 Promise是什么 Promise是ES6中用于处理异步编程的一种解决方案,它代表一种异步操作的最终完成(或失败)及其结果值的表示。 如何创建Promise对象 在node.js中,可以使用Promise构造函数来创建Promise对象。Promise构造函…

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