From 5cb7fc7ea58b22ea574abf17f4f4e7334e68fe3d Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Tue, 5 Sep 2017 13:22:48 +0100 Subject: [PATCH] fix(@angular/cli): fix asset watching https://github.com/kevlened/copy-webpack-plugin is now used instead of the custom plugin, it has since implemented the features we needed. Fix #7521 --- package-lock.json | 903 +++--------------- package.json | 2 + .../cli/models/webpack-configs/common.ts | 47 +- .../cli/models/webpack-configs/production.ts | 5 + .../cli/models/webpack-configs/utils.ts | 6 + packages/@angular/cli/package.json | 1 + .../cli/plugins/glob-copy-webpack-plugin.ts | 20 +- packages/@angular/cli/plugins/karma.ts | 13 +- packages/@angular/cli/tasks/eject.ts | 10 +- .../@angular/cli/utilities/is-directory.ts | 9 + 10 files changed, 187 insertions(+), 829 deletions(-) create mode 100644 packages/@angular/cli/utilities/is-directory.ts diff --git a/package-lock.json b/package-lock.json index 12a8326207cf..57bff5d23332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,6 +90,15 @@ "integrity": "sha1-FPKYk5kusyVZS4PXOa8C8rZSD0Y=", "dev": true }, + "@types/copy-webpack-plugin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/copy-webpack-plugin/-/copy-webpack-plugin-4.0.0.tgz", + "integrity": "sha1-v9qPXtOIzwnEJqvlER/Mt/PyXw0=", + "requires": { + "@types/minimatch": "3.0.0", + "@types/webpack": "3.0.9" + } + }, "@types/denodeify": { "version": "1.2.30", "resolved": "https://registry.npmjs.org/@types/denodeify/-/denodeify-1.2.30.tgz", @@ -164,8 +173,7 @@ "@types/minimatch": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.0.tgz", - "integrity": "sha512-BnRgLPs1oy9gV8b4dAW8jilIa7Kpe3uNucAvv4RkY7Yt6rj9E6Kk4Qa/18LOSinA+XDBPdzx3MqYPEP5mw8rDA==", - "dev": true + "integrity": "sha512-BnRgLPs1oy9gV8b4dAW8jilIa7Kpe3uNucAvv4RkY7Yt6rj9E6Kk4Qa/18LOSinA+XDBPdzx3MqYPEP5mw8rDA==" }, "@types/minimist": { "version": "1.2.0", @@ -185,8 +193,7 @@ "@types/node": { "version": "6.0.87", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.87.tgz", - "integrity": "sha512-Xo0pYENOBaGtJUhi50KH6gdBNQmZQQxAwBArsJpBd15ncoz+LZD5Ev14vuezcw62CsQ1q6bM++7jA6jfwaAbfQ==", - "dev": true + "integrity": "sha512-Xo0pYENOBaGtJUhi50KH6gdBNQmZQQxAwBArsJpBd15ncoz+LZD5Ev14vuezcw62CsQ1q6bM++7jA6jfwaAbfQ==" }, "@types/request": { "version": "2.0.1", @@ -217,20 +224,17 @@ "@types/source-map": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/@types/source-map/-/source-map-0.5.1.tgz", - "integrity": "sha512-/GVAjL1Y8puvZab63n8tsuBiYwZt1bApMdx58/msQ9ID5T05ov+wm/ZV1DvYC/DKKEygpTJViqQvkh5Rhrl4CA==", - "dev": true + "integrity": "sha512-/GVAjL1Y8puvZab63n8tsuBiYwZt1bApMdx58/msQ9ID5T05ov+wm/ZV1DvYC/DKKEygpTJViqQvkh5Rhrl4CA==" }, "@types/tapable": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-0.2.3.tgz", - "integrity": "sha1-CIiw8gzH5Y4cIqGIi06WPu+qgQo=", - "dev": true + "integrity": "sha1-CIiw8gzH5Y4cIqGIi06WPu+qgQo=" }, "@types/uglify-js": { "version": "2.6.29", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-2.6.29.tgz", "integrity": "sha512-BdFLCZW0GTl31AbqXSak8ss/MqEZ3DN2MH9rkAyGoTuzK7ifGUlX+u0nfbWeTsa7IPcZhtn8BlpYBXSV+vqGhQ==", - "dev": true, "requires": { "@types/source-map": "0.5.1" } @@ -239,7 +243,6 @@ "version": "3.0.9", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-3.0.9.tgz", "integrity": "sha512-xXqusBBKbYb8fA1jtE3iO75uRW1ejqGuH93V+6fhbfNY59ndKjfhftJVxcSaYAMDjmFTRBHy82d+513JKuHD5g==", - "dev": true, "requires": { "@types/node": "6.0.87", "@types/tapable": "0.2.3", @@ -980,7 +983,6 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", - "fsevents": "1.1.2", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -1616,6 +1618,84 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "copy-webpack-plugin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.0.1.tgz", + "integrity": "sha1-lyjjg7lDFgUNDHRjlY8rhcCqggA=", + "requires": { + "bluebird": "2.11.0", + "fs-extra": "0.26.7", + "glob": "6.0.4", + "is-glob": "3.1.0", + "loader-utils": "0.2.17", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "node-dir": "0.1.17" + }, + "dependencies": { + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.1" + } + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, "core-js": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", @@ -3002,791 +3082,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", - "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", - "optional": true, - "requires": { - "nan": "2.6.2", - "node-pre-gyp": "0.6.36" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "optional": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "optional": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.36", - "bundled": true, - "optional": true, - "requires": { - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "optional": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "optional": true - } - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -4966,6 +4261,14 @@ "is-buffer": "1.1.5" } }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, "lazy-cache": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", @@ -5479,6 +4782,14 @@ "lower-case": "1.1.4" } }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "requires": { + "minimatch": "3.0.4" + } + }, "node-forge": { "version": "0.6.33", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", diff --git a/package.json b/package.json index 282baba556aa..9f8fa594217c 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "chalk": "^2.0.1", "circular-dependency-plugin": "^3.0.0", "common-tags": "^1.3.1", + "copy-webpack-plugin": "^4.0.1", "core-object": "^3.1.0", "css-loader": "^0.28.1", "cssnano": "^3.10.0", @@ -105,6 +106,7 @@ "@angular/core": "^4.0.0", "@types/chalk": "^0.4.28", "@types/common-tags": "^1.2.4", + "@types/copy-webpack-plugin": "^4.0.0", "@types/denodeify": "^1.2.30", "@types/express": "^4.0.32", "@types/fs-extra": "^4.0.0", diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index f211a79ed41e..82afcaab7cff 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -1,9 +1,10 @@ import * as webpack from 'webpack'; import * as path from 'path'; -import { GlobCopyWebpackPlugin } from '../../plugins/glob-copy-webpack-plugin'; +import * as CopyWebpackPlugin from 'copy-webpack-plugin'; import { NamedLazyChunksWebpackPlugin } from '../../plugins/named-lazy-chunks-webpack-plugin'; import { InsertConcatAssetsWebpackPlugin } from '../../plugins/insert-concat-assets-webpack-plugin'; -import { extraEntryParser, getOutputHashFormat } from './utils'; +import { extraEntryParser, getOutputHashFormat, AssetPattern } from './utils'; +import { isDirectory } from '../../utilities/is-directory'; import { WebpackConfigOptions } from '../webpack-config'; const ConcatPlugin = require('webpack-concat-plugin'); @@ -84,10 +85,44 @@ export function getCommonConfig(wco: WebpackConfigOptions) { // process asset entries if (appConfig.assets) { - extraPlugins.push(new GlobCopyWebpackPlugin({ - patterns: appConfig.assets, - globOptions: { cwd: appRoot, dot: true, ignore: '**/.gitkeep' } - })); + const copyWebpackPluginPatterns = appConfig.assets.map((asset: string | AssetPattern) => { + // Convert all string assets to object notation. + asset = typeof asset === 'string' ? { glob: asset } : asset; + // Add defaults. + // Input is always resolved relative to the appRoot. + asset.input = path.resolve(appRoot, asset.input || ''); + asset.output = asset.output || ''; + asset.glob = asset.glob || ''; + + // Ensure trailing slash. + if (isDirectory(path.resolve(asset.input))) { + asset.input += '/'; + } + + // Convert dir patterns to globs. + if (isDirectory(path.resolve(asset.input, asset.glob))) { + asset.glob = asset.glob + '/**/*'; + } + + return { + context: asset.input, + to: asset.output, + from: { + glob: asset.glob, + dot: true + } + }; + }); + const copyWebpackPluginOptions = { ignore: ['.gitkeep'] }; + + const copyWebpackPluginInstance = new CopyWebpackPlugin(copyWebpackPluginPatterns, + copyWebpackPluginOptions); + + // Save options so we can use them in eject. + (copyWebpackPluginInstance as any)['copyWebpackPluginPatterns'] = copyWebpackPluginPatterns; + (copyWebpackPluginInstance as any)['copyWebpackPluginOptions'] = copyWebpackPluginOptions; + + extraPlugins.push(copyWebpackPluginInstance); } if (buildOptions.progress) { diff --git a/packages/@angular/cli/models/webpack-configs/production.ts b/packages/@angular/cli/models/webpack-configs/production.ts index cc581bbcc285..dc81100d2085 100644 --- a/packages/@angular/cli/models/webpack-configs/production.ts +++ b/packages/@angular/cli/models/webpack-configs/production.ts @@ -58,6 +58,11 @@ export const getProdConfig = function (wco: WebpackConfigOptions) { `); } + // CopyWebpackPlugin replaces GlobCopyWebpackPlugin, but AngularServiceWorkerPlugin depends + // on specific behaviour from latter. + // AngularServiceWorkerPlugin expects the ngsw-manifest.json to be present in the 'emit' phase + // but with CopyWebpackPlugin it's only there on 'after-emit'. + // So for now we keep it here, but if AngularServiceWorkerPlugin changes we remove it. extraPlugins.push(new GlobCopyWebpackPlugin({ patterns: [ 'ngsw-manifest.json', diff --git a/packages/@angular/cli/models/webpack-configs/utils.ts b/packages/@angular/cli/models/webpack-configs/utils.ts index e09592d6e127..4eee09a29e78 100644 --- a/packages/@angular/cli/models/webpack-configs/utils.ts +++ b/packages/@angular/cli/models/webpack-configs/utils.ts @@ -87,3 +87,9 @@ export function getOutputHashFormat(option: string, length = 20): HashFormat { /* tslint:enable:max-line-length */ return hashFormats[option] || hashFormats['none']; } + +export interface AssetPattern { + glob: string; + input?: string; + output?: string; +} diff --git a/packages/@angular/cli/package.json b/packages/@angular/cli/package.json index a1caa063b35a..fdac6d70b8aa 100644 --- a/packages/@angular/cli/package.json +++ b/packages/@angular/cli/package.json @@ -36,6 +36,7 @@ "chalk": "^2.0.1", "circular-dependency-plugin": "^3.0.0", "common-tags": "^1.3.1", + "copy-webpack-plugin": "^4.0.1", "core-object": "^3.1.0", "css-loader": "^0.28.1", "cssnano": "^3.10.0", diff --git a/packages/@angular/cli/plugins/glob-copy-webpack-plugin.ts b/packages/@angular/cli/plugins/glob-copy-webpack-plugin.ts index 248ad293ba4c..28c67b917e3f 100644 --- a/packages/@angular/cli/plugins/glob-copy-webpack-plugin.ts +++ b/packages/@angular/cli/plugins/glob-copy-webpack-plugin.ts @@ -2,33 +2,21 @@ import * as fs from 'fs'; import * as path from 'path'; import * as glob from 'glob'; import * as denodeify from 'denodeify'; +import { AssetPattern } from '../models/webpack-configs/utils'; +import { isDirectory } from '../utilities/is-directory'; const flattenDeep = require('lodash/flattenDeep'); const globPromise = denodeify(glob); const statPromise = denodeify(fs.stat); -function isDirectory(path: string) { - try { - return fs.statSync(path).isDirectory(); - } catch (_) { - return false; - } -} - interface Asset { originPath: string; destinationPath: string; relativePath: string; } -export interface Pattern { - glob: string; - input?: string; - output?: string; -} - export interface GlobCopyWebpackPluginOptions { - patterns: (string | Pattern)[]; + patterns: (string | AssetPattern)[]; globOptions: any; } @@ -79,7 +67,7 @@ export class GlobCopyWebpackPlugin { compiler.plugin('emit', (compilation: any, cb: any) => { // Create an array of promises for each pattern glob - const globs = patterns.map((pattern: Pattern) => new Promise((resolve, reject) => + const globs = patterns.map((pattern: AssetPattern) => new Promise((resolve, reject) => // Individual patterns can override cwd globPromise(pattern.glob, Object.assign({}, globOptions, { cwd: pattern.input })) // Map the results onto an Asset diff --git a/packages/@angular/cli/plugins/karma.ts b/packages/@angular/cli/plugins/karma.ts index 2853440cbb1d..69dd4b305df6 100644 --- a/packages/@angular/cli/plugins/karma.ts +++ b/packages/@angular/cli/plugins/karma.ts @@ -4,7 +4,8 @@ import * as glob from 'glob'; import * as webpack from 'webpack'; const webpackDevMiddleware = require('webpack-dev-middleware'); -import { Pattern } from './glob-copy-webpack-plugin'; +import { AssetPattern } from '../models/webpack-configs/utils'; +import { isDirectory } from '../utilities/is-directory'; import { WebpackTestConfig, WebpackTestOptions } from '../models/webpack-test-config'; import { KarmaWebpackThrowError } from './karma-webpack-throw-error'; @@ -22,14 +23,6 @@ const getAppFromConfig = require('../utilities/app-utils').getAppFromConfig; let blocked: any[] = []; let isBlocked = false; -function isDirectory(path: string) { - try { - return fs.statSync(path).isDirectory(); - } catch (_) { - return false; - } -} - // Add files to the Karma files array. function addKarmaFiles(files: any[], newFiles: any[], prepend = false) { const defaults = { @@ -82,7 +75,7 @@ const init: any = (config: any, emitter: any, customFileHandlers: any) => { // Add assets. This logic is mimics the one present in GlobCopyWebpackPlugin. if (appConfig.assets) { config.proxies = config.proxies || {}; - appConfig.assets.forEach((pattern: Pattern) => { + appConfig.assets.forEach((pattern: AssetPattern) => { // Convert all string patterns to Pattern type. pattern = typeof pattern === 'string' ? { glob: pattern } : pattern; // Add defaults. diff --git a/packages/@angular/cli/tasks/eject.ts b/packages/@angular/cli/tasks/eject.ts index baf67aa6661d..242404503843 100644 --- a/packages/@angular/cli/tasks/eject.ts +++ b/packages/@angular/cli/tasks/eject.ts @@ -161,6 +161,7 @@ class JsonWebpackSerializer { private _pluginsReplacer(plugins: any[]) { return plugins.map(plugin => { let args = plugin.options || undefined; + const serializer = (args: any) => JSON.stringify(args, (k, v) => this._replacer(k, v), 2); switch (plugin.constructor) { case ProgressPlugin: @@ -231,11 +232,17 @@ class JsonWebpackSerializer { default: if (plugin.constructor.name == 'AngularServiceWorkerPlugin') { this._addImport('@angular/service-worker/build/webpack', plugin.constructor.name); + } else if (plugin['copyWebpackPluginPatterns']) { + // CopyWebpackPlugin doesn't have a constructor nor save args. + this.variableImports['copy-webpack-plugin'] = 'CopyWebpackPlugin'; + const patternsSerialized = serializer(plugin['copyWebpackPluginPatterns']); + const optionsSerialized = serializer(plugin['copyWebpackPluginOptions']) || 'undefined'; + return `\uFF02CopyWebpackPlugin(${patternsSerialized}, ${optionsSerialized})\uFF02`; } break; } - const argsSerialized = JSON.stringify(args, (k, v) => this._replacer(k, v), 2) || ''; + const argsSerialized = serializer(args) || ''; return `\uFF02${plugin.constructor.name}(${argsSerialized})\uFF02`; }); } @@ -538,6 +545,7 @@ export default Task.extend({ 'url-loader', 'circular-dependency-plugin', 'webpack-concat-plugin', + 'copy-webpack-plugin', ].forEach((packageName: string) => { packageJson['devDependencies'][packageName] = ourPackageJson['dependencies'][packageName]; }); diff --git a/packages/@angular/cli/utilities/is-directory.ts b/packages/@angular/cli/utilities/is-directory.ts new file mode 100644 index 000000000000..f8a4b82b83fb --- /dev/null +++ b/packages/@angular/cli/utilities/is-directory.ts @@ -0,0 +1,9 @@ +import * as fs from 'fs'; + +export function isDirectory(path: string) { + try { + return fs.statSync(path).isDirectory(); + } catch (_) { + return false; + } +}