mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-22 23:15:56 +08:00
Adds the flag 'serviceWorker' to angular-cli.json that enables support for @angular/service-worker. When this flag is true, production builds will be set up with a service worker. A ngsw-manifest.json file will be generated (or augmented) in the dist/ root, and the service worker script will be copied there. A short script will be added to index.html to register the service worker. @angular/service-worker is a dependency of @angular/cli, but not of generated projects. It is desirable for users to be able to update the version of @angular/service-worker used in their apps independently of the CLI version. Thus, the CLI will error if serviceWorker=true but @angular/service-worker is not installed in the application's node_modules, as it pulls all the service worker scripts from there. If the flag is false the effect on the CLI is minimal - the webpack plugins associated with the SW are not even require()'d. Closes #4544
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as glob from 'glob';
|
|
import * as denodeify from 'denodeify';
|
|
|
|
const globPromise = <any>denodeify(glob);
|
|
const statPromise = <any>denodeify(fs.stat);
|
|
|
|
function isDirectory(path: string) {
|
|
try {
|
|
return fs.statSync(path).isDirectory();
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export interface GlobCopyWebpackPluginOptions {
|
|
patterns: string[];
|
|
globOptions: any;
|
|
}
|
|
|
|
export class GlobCopyWebpackPlugin {
|
|
constructor(private options: GlobCopyWebpackPluginOptions) { }
|
|
|
|
apply(compiler: any): void {
|
|
let { patterns, globOptions } = this.options;
|
|
let context = globOptions.cwd || compiler.options.context;
|
|
let optional = !!globOptions.optional;
|
|
|
|
// convert dir patterns to globs
|
|
patterns = patterns.map(pattern => isDirectory(path.resolve(context, pattern))
|
|
? pattern += '/**/*'
|
|
: pattern
|
|
);
|
|
|
|
// force nodir option, since we can't add dirs to assets
|
|
globOptions.nodir = true;
|
|
|
|
compiler.plugin('emit', (compilation: any, cb: any) => {
|
|
let globs = patterns.map(pattern => globPromise(pattern, globOptions));
|
|
|
|
let addAsset = (relPath: string) => compilation.assets[relPath]
|
|
// don't re-add to assets
|
|
? Promise.resolve()
|
|
: statPromise(path.resolve(context, relPath))
|
|
.then((stat: any) => compilation.assets[relPath] = {
|
|
size: () => stat.size,
|
|
source: () => fs.readFileSync(path.resolve(context, relPath))
|
|
})
|
|
.catch((err: any) => optional ? Promise.resolve() : Promise.reject(err));
|
|
|
|
Promise.all(globs)
|
|
// flatten results
|
|
.then(globResults => [].concat.apply([], globResults))
|
|
// add each file to compilation assets
|
|
.then((relPaths: string[]) =>
|
|
Promise.all(relPaths.map((relPath: string) => addAsset(relPath))))
|
|
.catch((err) => compilation.errors.push(err))
|
|
.then(() => cb());
|
|
});
|
|
}
|
|
}
|