下面是详解Angular5/Angular6项目如何添加热更新(HMR)功能的完整攻略。
需要的前置条件
- Angular CLI
- Angular5或Angular6项目
步骤一:安装相关依赖
首先我们需要安装@angularclass/hmr
和webpack-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技术站