mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-20 13:32:43 +08:00
fix(@angular/cli): stabilize webpack module identifiers
This provides increased viability for long-term caching by limiting the changes to the content of output files due to webpack module identifier changes. Close #4733
This commit is contained in:
parent
c99a7168d5
commit
26d1e41eb8
@ -69,6 +69,7 @@ export const getProdConfig = function (wco: WebpackConfigOptions) {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
}),
|
||||
new (<any>webpack).HashedModuleIdsPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin(<any>{
|
||||
mangle: { screw_ie8: true },
|
||||
compress: { screw_ie8: true, warnings: buildOptions.verbose },
|
||||
|
@ -175,6 +175,9 @@ class JsonWebpackSerializer {
|
||||
case webpack.NoEmitOnErrorsPlugin:
|
||||
this._addImport('webpack', 'NoEmitOnErrorsPlugin');
|
||||
break;
|
||||
case (<any>webpack).HashedModuleIdsPlugin:
|
||||
this._addImport('webpack', 'HashedModuleIdsPlugin');
|
||||
break;
|
||||
case webpack.optimize.UglifyJsPlugin:
|
||||
this._addImport('webpack.optimize', 'UglifyJsPlugin');
|
||||
break;
|
||||
|
@ -5,52 +5,92 @@ import {ng} from '../../utils/process';
|
||||
import {writeFile} from '../../utils/fs';
|
||||
import {addImportToModule} from '../../utils/ast';
|
||||
|
||||
const OUTPUT_RE = /(main|polyfills|vendor|inline|styles|\d+)\.[a-z0-9]+\.(chunk|bundle)\.(js|css)$/;
|
||||
|
||||
function generateFileHashMap(): Map<string, string> {
|
||||
const hashes = new Map<string, string>();
|
||||
|
||||
fs.readdirSync('./dist')
|
||||
.forEach(name => {
|
||||
if (!name.match(OUTPUT_RE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [module, hash] = name.split('.');
|
||||
hashes.set(module, hash);
|
||||
});
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
||||
function validateHashes(
|
||||
oldHashes: Map<string, string>,
|
||||
newHashes: Map<string, string>,
|
||||
shouldChange: Array<string>): void {
|
||||
|
||||
console.log(' Validating hashes...');
|
||||
console.log(` Old hashes: ${JSON.stringify([...oldHashes])}`);
|
||||
console.log(` New hashes: ${JSON.stringify([...newHashes])}`);
|
||||
|
||||
oldHashes.forEach((hash, module) => {
|
||||
if (hash == newHashes.get(module)) {
|
||||
if (shouldChange.includes(module)) {
|
||||
throw new Error(`Module "${module}" did not change hash (${hash})...`);
|
||||
}
|
||||
} else if (!shouldChange.includes(module)) {
|
||||
throw new Error(`Module "${module}" changed hash (${hash})...`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default function() {
|
||||
const oldHashes: {[module: string]: string} = {};
|
||||
const newHashes: {[module: string]: string} = {};
|
||||
let oldHashes: Map<string, string>;
|
||||
let newHashes: Map<string, string>;
|
||||
// First, collect the hashes.
|
||||
return Promise.resolve()
|
||||
.then(() => ng('generate', 'module', 'lazy', '--routing'))
|
||||
.then(() => addImportToModule('src/app/app.module.ts', oneLine`
|
||||
RouterModule.forRoot([{ path: "lazy", loadChildren: "./lazy/lazy.module#LazyModule" }])
|
||||
`, '@angular/router'))
|
||||
.then(() => addImportToModule(
|
||||
'src/app/app.module.ts', 'ReactiveFormsModule', '@angular/forms'))
|
||||
.then(() => ng('build', '--prod'))
|
||||
.then(() => {
|
||||
fs.readdirSync('./dist')
|
||||
.forEach(name => {
|
||||
if (!name.match(/(main|inline|styles|\d+)\.[a-z0-9]+\.bundle\.(js|css)/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [module, hash] = name.split('.');
|
||||
oldHashes[module] = hash;
|
||||
});
|
||||
oldHashes = generateFileHashMap();
|
||||
})
|
||||
.then(() => writeFile('src/app/app.component.css', 'h1 { margin: 5px; }'))
|
||||
.then(() => writeFile('src/styles.css', 'body { background: red; }'))
|
||||
.then(() => ng('build', '--prod'))
|
||||
.then(() => {
|
||||
fs.readdirSync('./dist')
|
||||
.forEach(name => {
|
||||
if (!name.match(/(main|inline|styles|\d+)\.[a-z0-9]+\.bundle\.(js|css)/)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [module, hash] = name.split('.');
|
||||
newHashes[module] = hash;
|
||||
});
|
||||
newHashes = generateFileHashMap();
|
||||
})
|
||||
.then(() => {
|
||||
console.log(' Validating hashes...');
|
||||
console.log(` Old hashes: ${JSON.stringify(oldHashes)}`);
|
||||
console.log(` New hashes: ${JSON.stringify(newHashes)}`);
|
||||
|
||||
Object.keys(oldHashes)
|
||||
.forEach(module => {
|
||||
if (oldHashes[module] == newHashes[module]) {
|
||||
throw new Error(`Module "${module}" did not change hash (${oldHashes[module]})...`);
|
||||
}
|
||||
});
|
||||
validateHashes(oldHashes, newHashes, []);
|
||||
oldHashes = newHashes;
|
||||
})
|
||||
.then(() => writeFile('src/styles.css', 'body { background: blue; }'))
|
||||
.then(() => ng('build', '--prod'))
|
||||
.then(() => {
|
||||
newHashes = generateFileHashMap();
|
||||
})
|
||||
.then(() => {
|
||||
validateHashes(oldHashes, newHashes, ['styles']);
|
||||
oldHashes = newHashes;
|
||||
})
|
||||
.then(() => writeFile('src/app/app.component.css', 'h1 { margin: 10px; }'))
|
||||
.then(() => ng('build', '--prod'))
|
||||
.then(() => {
|
||||
newHashes = generateFileHashMap();
|
||||
})
|
||||
.then(() => {
|
||||
validateHashes(oldHashes, newHashes, ['inline', 'main']);
|
||||
oldHashes = newHashes;
|
||||
})
|
||||
.then(() => addImportToModule(
|
||||
'src/app/lazy/lazy.module.ts', 'ReactiveFormsModule', '@angular/forms'))
|
||||
.then(() => ng('build', '--prod'))
|
||||
.then(() => {
|
||||
newHashes = generateFileHashMap();
|
||||
})
|
||||
.then(() => {
|
||||
validateHashes(oldHashes, newHashes, ['inline', '0']);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user