feat(@angular/cli): hash loaded media by default (#4878)

Currently dev builds use `--output-hashing=none` by default.

This can cause image resources to be overwritten in dev if they have the same same.

This wasn't much of a problem before when only images in global CSS would be treated as resources, but now component css also does that.

Production builds are unaffected since they already use `--output-hashing=all`.

BREAKING CHANGE: dev builds will hash relative resources from CSS (images, etc).
This commit is contained in:
Filipe Silva 2017-02-22 15:52:11 +00:00 committed by GitHub
parent e4fc2947db
commit 1655e51e7e
5 changed files with 31 additions and 23 deletions

View File

@ -78,7 +78,7 @@ export class NgCliWebpackConfig {
const targetDefaults: any = {
development: {
environment: 'dev',
outputHashing: 'none',
outputHashing: 'media',
sourcemap: true,
extractCss: false
},

View File

@ -1,7 +1,9 @@
import * as fs from 'fs';
import { ng } from '../../utils/process';
import {
expectFileToMatch,
expectFileToExist,
expectFileMatchToExist,
writeMultipleFiles
} from '../../utils/fs';
import { expectToFail } from '../../utils/utils';
@ -33,24 +35,27 @@ export default function () {
.then(() => ng('build', '--extract-css', '--aot'))
// Check paths are correctly generated.
.then(() => expectFileToMatch('dist/styles.bundle.css',
`url\('\/assets\/global-img-absolute\.svg'\)`))
.then(() => expectFileToMatch('dist/styles.bundle.css', 'url\(global-img-relative.svg\)'))
/url\('\/assets\/global-img-absolute\.svg'\)/))
.then(() => expectFileToMatch('dist/styles.bundle.css',
/url\(global-img-relative\.[0-9a-f]{20}\.svg\)/))
.then(() => expectFileToMatch('dist/main.bundle.js',
`url\(\\'\/assets\/component-img-absolute\.svg\\'\)`))
.then(() => expectFileToMatch('dist/main.bundle.js', 'url\(component-img-relative\.svg\)'))
/url\(\\'\/assets\/component-img-absolute\.svg\\'\)/))
.then(() => expectFileToMatch('dist/main.bundle.js',
/url\(component-img-relative\.[0-9a-f]{20}\.svg\)/))
// Check files are correctly created.
.then(() => expectToFail(() => expectFileToExist('dist/global-img-absolute.svg')))
.then(() => expectFileToExist('dist/global-img-relative.svg'))
.then(() => expectToFail(() => expectFileToExist('dist/component-img-absolute.svg')))
.then(() => expectFileToExist('dist/component-img-relative.svg'))
.then(() => expectFileMatchToExist('./dist', /global-img-relative\.[0-9a-f]{20}\.svg/))
.then(() => expectFileMatchToExist('./dist', /component-img-relative\.[0-9a-f]{20}\.svg/))
// Also check with base-href and deploy-url flags.
.then(() => ng('build', '--base-href=/base/', '--deploy-url=deploy/',
'--extract-css', '--aot'))
.then(() => expectFileToMatch('dist/styles.bundle.css',
`url\('\/base\/deploy\/assets\/global-img-absolute\.svg'\)`))
.then(() => expectFileToMatch('dist/styles.bundle.css', 'url\(global-img-relative.svg\)'))
/url\('\/base\/deploy\/assets\/global-img-absolute\.svg'\)/))
.then(() => expectFileToMatch('dist/styles.bundle.css',
/url\(global-img-relative\.[0-9a-f]{20}\.svg\)/))
.then(() => expectFileToMatch('dist/main.bundle.js',
`url\(\\'\/base\/deploy\/assets\/component-img-absolute\.svg\\'\)`))
/url\(\\'\/base\/deploy\/assets\/component-img-absolute\.svg\\'\)/))
.then(() => expectFileToMatch('dist/main.bundle.js',
'url\(deploy/component-img-relative\.svg\)'));
/url\(deploy\/component-img-relative\.[0-9a-f]{20}\.svg\)/));
}

View File

@ -16,7 +16,7 @@ export default function () {
.then(() => ng('build', '--deploy-url=deployUrl/', '--extract-css'))
.then(() => expectFileToMatch('dist/index.html', 'deployUrl/main.bundle.js'))
// verify --deploy-url isn't applied to extracted css urls
.then(() => expectFileToMatch('dist/styles.bundle.css', 'url\(more.svg\)'))
.then(() => expectFileToMatch('dist/styles.bundle.css', /url\(more\.[0-9a-f]{20}\.svg\)/))
// verify option also works in config
.then(() => updateJsonFile('.angular-cli.json', configJson => {
const app = configJson['apps'][0];
@ -27,5 +27,5 @@ export default function () {
// verify --deploy-url is applied to non-extracted css urls
.then(() => ng('build', '--deploy-url=deployUrl/', '--extract-css=false'))
.then(() => expectFileToMatch('dist/styles.bundle.js',
'__webpack_require__.p \+ \"more.svg\"'));
/__webpack_require__.p \+ \"more\.[0-9a-f]{20}\.svg\"/));
}

View File

@ -1,17 +1,10 @@
import {stripIndents} from 'common-tags';
import * as fs from 'fs';
import {ng} from '../../utils/process';
import { writeMultipleFiles, expectFileToMatch } from '../../utils/fs';
import { writeMultipleFiles, expectFileToMatch, expectFileMatchToExist } from '../../utils/fs';
function verifyMedia(css: RegExp, content: RegExp) {
return new Promise((resolve, reject) => {
const [fileName] = fs.readdirSync('./dist').filter(name => name.match(css));
if (!fileName) {
reject(new Error(`File ${fileName} was expected to exist but not found...`));
}
resolve(fileName);
})
.then(fileName => expectFileToMatch(`dist/${fileName}`, content));
return expectFileMatchToExist('./dist', css)
.then(fileName => expectFileToMatch(`dist/${fileName}`, content));
}
export default function() {

View File

@ -120,6 +120,16 @@ export function prependToFile(filePath: string, text: string, options?: any) {
}
export function expectFileMatchToExist(dir: string, regex: RegExp) {
return new Promise((resolve, reject) => {
const [fileName] = fs.readdirSync(dir).filter(name => name.match(regex));
if (!fileName) {
reject(new Error(`File ${regex} was expected to exist but not found...`));
}
resolve(fileName);
});
}
export function expectFileToExist(fileName: string) {
return new Promise((resolve, reject) => {
fs.exists(fileName, (exist) => {