angular-cli如何启用HMR

webpack有一个非常好玩的插件叫:模块换替换(HMR),即添加或删除模块时应用持续运行,不需要页面刷新。虽然angular cli至问世以来就以webpack为核心,可直到【1.0.0-beta.22】以上版本才开始支持。

那么,接下来我们来玩一玩Angular的热替换。

先决条件

  • angular cli 至少 1.0.0-beta.22 以上版本

创建项目

使用Angular CLI创建一个空项目。

ng new ng-hmr
cd ng-hmr

添加HMR环境配置文件

HMR需要一定代码嵌入,而这些模块我们希望只在开发过程中使用,所以这里创建一个环境配置文件,用于区分我们什么时候需要引入 hmr 模块,而不会影响我们生产环境。

首先,创建 src/environments/environment.hmr.ts 文件,内容为:

export const environment = {
  production: false,
  hmr: true
};

这里相比较默认两个环境,增加了 hmr: true 变量。那么,另外两个,也一并设置相应 hmr 变量,来确保什么情况下才允许开启 HMR。

environment.prod.ts 生产环境肯定不会开启它:

export const environment = {
  production: true,
  hmr: false
};

environment.ts 默认环境,如果有必要也可以设置为 true,为了后面更好的演示,这里我设置 false

export const environment = {
  production: false,
  hmr: false
};

新环境配置还需要更新 angular-cli.jsonenvironments 节点,以确保angular cli 能认识:

      "environments": {
        "source": "environments/environment.ts",
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts",
        // 新增的节点
        "hmr": "environments/environment.hmr.ts"
      }

到此,与配置相关已经完成,你可以尝试使用 ng serve --hmr -e=hmr 来启用HMR。而且和之前相比会有这样一段提醒:

NOTICE Hot Module Replacement (HMR) is enabled for the dev server.
The project will still live reload when HMR is enabled,
but to take advantage of HMR additional application code is required
(not included in an Angular CLI project by default).
See https://webpack.github.io/docs/hot-module-replacement.html
for information on working with HMR for Webpack.

添加angular-hmr模块依赖与配置

正如提醒信息中说的,Angular CLI默认并不提供HMR所需要的额外应用代码。但Angular已经有了一个现成HMR模块即【Angular 2 Hot Module Replacement】,安装它:

npm install --save-dev @angularclass/hmr

接下来,创建 src/hmr.ts 文件,配置模块内容:

import { NgModuleRef, ApplicationRef } from '@angular/core';
import { createNewHosts } from '@angularclass/hmr';

export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => {
    let ngModule: NgModuleRef<any>;
    module.hot.accept();
    bootstrap().then(mod => {
        ngModule = mod;
    });
    module.hot.dispose(() => {
        let appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
        let elements = appRef.components.map(c => c.location.nativeElement);
        let makeVisible = createNewHosts(elements);
        ngModule.destroy();
        makeVisible();
    });
};

最后,修改 src/main.ts 内容:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode, ApplicationRef } from '@angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';

import { hmrBootstrap } from './hmr';

if (environment.production) {
  enableProdMode();
}

const bootstrap = () => {
  return platformBrowserDynamic().bootstrapModule(AppModule);
}

if (environment.hmr) {
  if (module['hot']) {
    hmrBootstrap(module, bootstrap);
  } else {
    // 未加上 --hmr 时,控制台会有错误提醒
    console.error('HMR没有启用,确保 ng server 命令加上 --hmr 标记');
  }
} else {
  bootstrap();
}

运行

现在,我们可以使用以下命令来启动HMR:

ng serve --hmr -e=hmr

尝试修改一个 app.component.tstitle 属性值,保存后,无须刷新页面,立即生效:

效果图

快点,享受更快乐的编码方式吧!

1 Comment

  1. 不错~

    哥们的域名太随性了吧……

发表评论

Your email address will not be published.

*

© 2017 卡片机色彩 沪ICP备13032872号-3

Theme by cipchk

to top