Skip to content

Commit

Permalink
feat(@angular-devkit/build-webpack): add package
Browse files Browse the repository at this point in the history
  • Loading branch information
filipesilva authored and hansl committed Jun 6, 2018
1 parent 2ab8b76 commit f8b5a99
Show file tree
Hide file tree
Showing 41 changed files with 902 additions and 40 deletions.
10 changes: 10 additions & 0 deletions .monorepo.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@
"hash": "bea6085c247179eedf6a2d312ea5509b",
"snapshotRepo": "angular/angular-devkit-build-angular-builds"
},
"@angular-devkit/build-webpack": {
"name": "Build Webpack",
"links": [
{
"label": "README",
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_webpack/README.md"
}
],
"version": "0.0.0"
},
"@angular-devkit/core": {
"name": "Core",
"links": [
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ This is a monorepo which contains many packages:
**Build Angular** | [`@angular-devkit/build-angular`](https://npmjs.com/package/@angular-devkit/build-angular) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fbuild-angular/latest.svg)](https://npmjs.com/package/@angular-devkit/build-angular) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_angular/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-build-angular-builds)
**Build NgPackagr** | [`@angular-devkit/build-ng-packagr`](https://npmjs.com/package/@angular-devkit/build-ng-packagr) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fbuild-ng-packagr/latest.svg)](https://npmjs.com/package/@angular-devkit/build-ng-packagr) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_ng_packagr/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-build-ng-packagr-builds)
**Build Optimizer** | [`@angular-devkit/build-optimizer`](https://npmjs.com/package/@angular-devkit/build-optimizer) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fbuild-optimizer/latest.svg)](https://npmjs.com/package/@angular-devkit/build-optimizer) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_optimizer/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-build-optimizer-builds)
**Build Webpack** | [`@angular-devkit/build-webpack`](https://npmjs.com/package/@angular-devkit/build-webpack) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fbuild-webpack/latest.svg)](https://npmjs.com/package/@angular-devkit/build-webpack) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_webpack/README.md)
**Core** | [`@angular-devkit/core`](https://npmjs.com/package/@angular-devkit/core) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fcore/latest.svg)](https://npmjs.com/package/@angular-devkit/core) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/core/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-core-builds)
**Schematics** | [`@angular-devkit/schematics`](https://npmjs.com/package/@angular-devkit/schematics) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fschematics/latest.svg)](https://npmjs.com/package/@angular-devkit/schematics) | [![README](https://img.shields.io/badge/README--green.svg)](https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md) [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-schematics-builds)
**Schematics CLI** | [`@angular-devkit/schematics-cli`](https://npmjs.com/package/@angular-devkit/schematics-cli) | [![latest](https://img.shields.io/npm/v/%40angular-devkit%2Fschematics-cli/latest.svg)](https://npmjs.com/package/@angular-devkit/schematics-cli) | [![snapshot](https://img.shields.io/badge/snapshot--blue.svg)](https://github.com/angular/angular-devkit-schematics-cli-builds)
Expand Down
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"@types/semver": "^5.3.30",
"@types/source-map": "0.5.2",
"@types/webpack": "^4.1.3",
"@types/webpack-dev-server": "^2.9.4",
"@types/webpack-sources": "^0.1.4",
"ajv": "~6.4.0",
"autoprefixer": "^8.4.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/angular_devkit/build_webpack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Webpack Builder for Architect

WIP
15 changes: 15 additions & 0 deletions packages/angular_devkit/build_webpack/builders.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "../architect/src/builders-schema.json",
"builders": {
"webpack": {
"class": "./src/webpack",
"schema": "./src/webpack/schema.json",
"description": "Build a webpack app."
},
"webpack-dev-server": {
"class": "./src/webpack-dev-server",
"schema": "./src/webpack-dev-server/schema.json",
"description": "Serve a webpack app."
}
}
}
20 changes: 20 additions & 0 deletions packages/angular_devkit/build_webpack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@angular-devkit/build-webpack",
"version": "0.0.0",
"description": "Webpack Builder for Architect",
"main": "src/index.js",
"typings": "src/index.d.ts",
"builders": "builders.json",
"scripts": {
"preinstall": "echo DO NOT INSTALL THIS PROJECT, ONLY THE ROOT PROJECT. && exit 1"
},
"dependencies": {
"@angular-devkit/architect": "0.0.0",
"@angular-devkit/core": "0.0.0",
"rxjs": "^6.0.0"
},
"peerDependencies": {
"webpack": "~4.6.0",
"webpack-dev-server": "^3.1.4"
}
}
10 changes: 10 additions & 0 deletions packages/angular_devkit/build_webpack/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @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
*/

export * from './webpack';
export * from './webpack-dev-server';
17 changes: 17 additions & 0 deletions packages/angular_devkit/build_webpack/src/test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @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 { TestProjectHost } from '@angular-devkit/architect/testing';
import { join, normalize } from '@angular-devkit/core';


const devkitRoot = normalize((global as any)._DevKitRoot); // tslint:disable-line:no-any
const basicWorkspaceRoot = join(devkitRoot, 'tests/@angular_devkit/build_webpack/basic-app/');
export const basicHost = new TestProjectHost(basicWorkspaceRoot);
const angularWorkspaceRoot = join(devkitRoot, 'tests/@angular_devkit/build_webpack/angular-app/');
export const angularHost = new TestProjectHost(angularWorkspaceRoot);
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @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 {
BuildEvent,
Builder,
BuilderConfiguration,
BuilderContext,
} from '@angular-devkit/architect';
import { Path, getSystemPath, normalize, resolve } from '@angular-devkit/core';
import { Observable, from } from 'rxjs';
import { concatMap } from 'rxjs/operators';
import * as webpack from 'webpack';
import * as WebpackDevServer from 'webpack-dev-server';
import { LoggingCallback, defaultLoggingCb } from '../webpack';
import { WebpackDevServerBuilderSchema } from './schema';


export class WebpackDevServerBuilder implements Builder<WebpackDevServerBuilderSchema> {

constructor(public context: BuilderContext) { }

run(builderConfig: BuilderConfiguration<WebpackDevServerBuilderSchema>): Observable<BuildEvent> {
const configPath = resolve(this.context.workspace.root,
normalize(builderConfig.options.webpackConfig));

return this.loadWebpackConfig(getSystemPath(configPath)).pipe(
concatMap(config => this.runWebpackDevServer(config)),
);
}

public loadWebpackConfig(webpackConfigPath: string): Observable<webpack.Configuration> {
return from(import(webpackConfigPath));
}

public runWebpackDevServer(
webpackConfig: webpack.Configuration,
devServerCfg?: WebpackDevServer.Configuration,
loggingCb: LoggingCallback = defaultLoggingCb,
): Observable<BuildEvent> {
return new Observable(obs => {
const devServerConfig = devServerCfg || webpackConfig.devServer || {};
devServerConfig.host = devServerConfig.host || 'localhost';
devServerConfig.port = devServerConfig.port || 8080;

if (devServerConfig.stats) {
webpackConfig.stats = devServerConfig.stats;
}
// Disable stats reporting by the devserver, we have our own logger.
devServerConfig.stats = false;

const webpackCompiler = webpack(webpackConfig);
const server = new WebpackDevServer(webpackCompiler, devServerConfig);

webpackCompiler.hooks.done.tap('build-webpack', (stats) => {
// Log stats.
loggingCb(stats, webpackConfig, this.context.logger);

obs.next({ success: !stats.hasErrors() });
});

server.listen(
devServerConfig.port,
devServerConfig.host,
(err) => {
if (err) {
obs.error(err);
}
},
);

// Teardown logic. Close the server when unsubscribed from.
return () => server.close();
});
}
}


export default WebpackDevServerBuilder;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @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 { request, runTargetSpec } from '@angular-devkit/architect/testing';
import { from } from 'rxjs';
import { concatMap, take, tap } from 'rxjs/operators';
import { basicHost } from '../test-utils';


describe('Dev Server Builder', () => {
const webpackTargetSpec = { project: 'app', target: 'serve' };

beforeEach(done => basicHost.initialize().toPromise().then(done, done.fail));
afterEach(done => basicHost.restore().toPromise().then(done, done.fail));

it('works', (done) => {
runTargetSpec(basicHost, webpackTargetSpec).pipe(
tap((buildEvent) => expect(buildEvent.success).toBe(true)),
concatMap(() => from(request('http://localhost:8080/bundle.js'))),
tap(response => expect(response).toContain(`console.log('hello world')`)),
take(1),
).toPromise().then(done, done.fail);
}, 30000);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @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
*/
export interface WebpackDevServerBuilderSchema {
/**
* The path to the Webpack configuration file.
*/
webpackConfig: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Webpack Dev-Server Builder",
"description": "Webpack Dev-Server Builder schema for Architect.",
"type": "object",
"properties": {
"webpackConfig": {
"type": "string",
"description": "The path to the Webpack configuration file."
}
},
"additionalProperties": false,
"required": [
"webpackConfig"
]
}
87 changes: 87 additions & 0 deletions packages/angular_devkit/build_webpack/src/webpack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @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 {
BuildEvent,
Builder,
BuilderConfiguration,
BuilderContext,
} from '@angular-devkit/architect';
import { Path, getSystemPath, logging, normalize, resolve } from '@angular-devkit/core';
import { Observable, from } from 'rxjs';
import { concatMap } from 'rxjs/operators';
import * as webpack from 'webpack';
import { WebpackBuilderSchema } from './schema';


export interface LoggingCallback {
(stats: webpack.Stats, config: webpack.Configuration, logger: logging.Logger): void;
}

export const defaultLoggingCb: LoggingCallback = (stats, config, logger) =>
logger.info(stats.toString(config.stats));

export class WebpackBuilder implements Builder<WebpackBuilderSchema> {

constructor(public context: BuilderContext) { }

run(builderConfig: BuilderConfiguration<WebpackBuilderSchema>): Observable<BuildEvent> {
const configPath = resolve(this.context.workspace.root,
normalize(builderConfig.options.webpackConfig));

return this.loadWebpackConfig(getSystemPath(configPath)).pipe(
concatMap(config => this.runWebpack(config)),
);
}

public loadWebpackConfig(webpackConfigPath: string): Observable<webpack.Configuration> {
return from(import(webpackConfigPath));
}

public runWebpack(
config: webpack.Configuration, loggingCb = defaultLoggingCb,
): Observable<BuildEvent> {
return new Observable(obs => {
const webpackCompiler = webpack(config);

const callback: webpack.compiler.CompilerCallback = (err, stats) => {
if (err) {
return obs.error(err);
}

// Log stats.
loggingCb(stats, config, this.context.logger);

obs.next({ success: !stats.hasErrors() });

if (!config.watch) {
obs.complete();
}
};

try {
if (config.watch) {
const watchOptions = config.watchOptions || {};
const watching = webpackCompiler.watch(watchOptions, callback);

// Teardown logic. Close the watcher when unsubscribed from.
return () => watching.close(() => { });
} else {
webpackCompiler.run(callback);
}
} catch (err) {
if (err) {
this.context.logger.error(
'\nAn error occured during the build:\n' + ((err && err.stack) || err));
}
throw err;
}
});
}
}

export default WebpackBuilder;

0 comments on commit f8b5a99

Please sign in to comment.