Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): include HMR accept code in main.ts
Browse files Browse the repository at this point in the history
This fixes as issue where in some cases the changed module is not accepted which cases the dev-server to fallback to live-reload.

This is because the hmr.js and main.ts have different module ids.
  • Loading branch information
alan-agius4 authored and mgechev committed Oct 14, 2020
1 parent 871dd6a commit 49841f8
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 212 deletions.
43 changes: 43 additions & 0 deletions packages/angular_devkit/build_angular/src/dev-server/hmr_spec.ts
@@ -0,0 +1,43 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Architect, BuilderRun } from '@angular-devkit/architect';
import { DevServerBuilderOutput } from '@angular-devkit/build-angular';
import fetch from 'node-fetch'; // tslint:disable-line:no-implicit-dependencies
import { createArchitect, host } from '../test-utils';


describe('Dev Server Builder hmr', () => {
const target = { project: 'app', target: 'serve' };
let architect: Architect;
// We use runs like this to ensure it WILL stop the servers at the end of each tests.
let runs: BuilderRun[];

beforeEach(async () => {
await host.initialize().toPromise();
architect = (await createArchitect(host.root())).architect;
runs = [];
});
afterEach(async () => {
await host.restore().toPromise();
await Promise.all(runs.map(r => r.stop()));
});

it('adds HMR accept code in all JS bundles', async () => {
const run = await architect.scheduleTarget(target, { hmr: true });
runs.push(run);
const output = await run.result as DevServerBuilderOutput;
expect(output.success).toBe(true);
expect(output.baseUrl).toBe('https://localhost:4200/');

const polyfills = await fetch('https://localhost:4200/polyfills.js');
expect(await polyfills.text()).toContain('ngHmrAccept(module);');

const main = await fetch('https://localhost:4200/main.js');
expect(await main.text()).toContain('ngHmrAccept(module);');
}, 30000);
});
15 changes: 15 additions & 0 deletions packages/angular_devkit/build_angular/src/dev-server/index.ts
Expand Up @@ -38,6 +38,7 @@ import { assertCompatibleAngularVersion } from '../utils/version';
import { getIndexInputFile, getIndexOutputFile } from '../utils/webpack-browser-config';
import { addError, addWarning } from '../utils/webpack-diagnostics';
import { normalizeExtraEntryPoints } from '../webpack/configs';
import { HmrLoader } from '../webpack/plugins/hmr/hmr-loader';
import { IndexHtmlWebpackPlugin } from '../webpack/plugins/index-html-webpack-plugin';
import { createWebpackLoggingCallback } from '../webpack/utils/stats';
import { Schema } from './schema';
Expand Down Expand Up @@ -591,6 +592,20 @@ function _addLiveReload(
}

webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());

const hmrLoader: webpack.RuleSetRule = {
loader: HmrLoader,
include: [browserOptions.main].map(p => path.resolve(root, p)),
};

if (typeof webpackConfig.module !== 'object') {
webpackConfig.module = {
rules: [hmrLoader],
};
} else {
webpackConfig.module.rules.unshift(hmrLoader);
}

}
if (typeof webpackConfig.entry !== 'object' || Array.isArray(webpackConfig.entry)) {
webpackConfig.entry = {};
Expand Down
212 changes: 0 additions & 212 deletions packages/angular_devkit/build_angular/src/webpack/hmr.js

This file was deleted.

0 comments on commit 49841f8

Please sign in to comment.