Skip to content

Commit

Permalink
feat(custom-webpack): add extract-i18n builder (#832)
Browse files Browse the repository at this point in the history
  • Loading branch information
just-jeb authored Sep 10, 2020
1 parent 756a264 commit 15f95d0
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 60 deletions.
43 changes: 39 additions & 4 deletions packages/custom-webpack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Allow customizing build configuration without ejecting webpack configuration (`n
Where:
- [project] is the name of the project to which you want to add the builder
- [architect-target] is the name of build target you want to run (build, serve, test etc. or any custom target)
- [browser|server|karma|dev-server] one of the supported builders - [browser](#Custom-webpack-browser), [server](#Custom-webpack-server), [karma](#Custom-webpack-Karma) or [dev-server](#Custom-webpack-dev-server)
- [browser|server|karma|dev-server|extract-i18n] one of the supported builders - [browser](#Custom-webpack-browser), [server](#Custom-webpack-server), [karma](#Custom-webpack-Karma), [dev-server](#Custom-webpack-dev-server) or [extract-i18n](#Custom-webpack-extract-i18n)
3. If `[architect-target]` is not one of the predefined targets (like build, serve, test etc.) then run it like this:
`ng run [project]:[architect-target]`
If it is one of the predefined targets, you can run it with `ng [architect-target]`
Expand Down Expand Up @@ -65,10 +65,11 @@ Allow customizing build configuration without ejecting webpack configuration (`n
- [@angular-builders/custom-webpack:server](#Custom-webpack-server)
- [@angular-builders/custom-webpack:karma](#Custom-webpack-Karma)
- [@angular-builders/custom-webpack:dev-server](#Custom-webpack-dev-server)
- [@angular-builders/custom-webpack:extract-i18n](#Custom-webpack-extract-i18n)
## Custom Webpack `browser`
Extended `@angular-devkit/build-angular:browser` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` tranformations.
Extended `@angular-devkit/build-angular:browser` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` transformations.
The builder will run the same build as `@angular-devkit/build-angular:browser` does with extra parameters that are specified in the provided webpack configuration. It will also run transformation on `index.html` if specified.
Builder options:
Expand Down Expand Up @@ -138,7 +139,7 @@ In this example `dev-server` will use `custom-webpack:browser` builder, hence mo
## Custom Webpack `server`
Extended `@angular-devkit/build-angular:server` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` tranformations.
Extended `@angular-devkit/build-angular:server` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` transformations.
The builder will run the same build as `@angular-devkit/build-angular:server` does with extra parameters that are specified in the provided webpack configuration.
Builder options:
Expand Down Expand Up @@ -172,7 +173,7 @@ Since loaders are evaluated [from right to left](https://webpack.js.org/concepts
## Custom Webpack `karma`
Extended `@angular-devkit/build-angular:karma` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` tranformations.
Extended `@angular-devkit/build-angular:karma` builder that allows to specify additional webpack configuration (on top of the existing under the hood) and `index.html` transformations.
The builder will run the same build as `@angular-devkit/build-angular:karma` does with extra parameters that are specified in the provided webpack configuration.
Builder options:
Expand All @@ -198,6 +199,40 @@ Builder options:
}
```
## Custom Webpack `extract-i18n`
Enhanced `@angular-devkit/build-angular:extract-i18n` builder that leverages the custom webpack builder to get webpack configuration.
The builder uses `customWebpackConfiguration` from `browserTarget` to run the extraction process while taking into account changes in your custom webpack config.
Thus, if you use `@angular-builders/custom-webpack:extract-i18n` along with `@angular-builders/custom-webpack:browser`, `ng extract-i18n` will run with custom configuration provided in the latter.
### Example
`angular.json`:
```js
"architect": {
...
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./extra-webpack.config.js"
},
...
}
},
"extract-i18n": {
"builder": "@angular-builders/custom-webpack:extract-i18n",
"options": {
"browserTarget": "my-project:build"
}
}
```
In this example `extract-i18n` will use `custom-webpack:browser` builder, hence modified webpack config, when invoking the extract-i18n target.
# Custom Webpack Config Object
This option defines your custom webpack configuration. If not specified at all, plain Angular build will run.
Expand Down
5 changes: 5 additions & 0 deletions packages/custom-webpack/builders.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
"implementation": "./dist/karma",
"schema": "./dist/karma/schema.json",
"description": "Karma server extended with custom webpack config"
},
"extract-i18n": {
"implementation": "./dist/extract-i18n",
"schema": "./dist/extract-i18n/schema.json",
"description": "Extract i18n extended with custom webpack config"
}
}
}
12 changes: 5 additions & 7 deletions packages/custom-webpack/src/browser/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { BrowserBuilderOptions, executeBrowserBuilder } from '@angular-devkit/build-angular';
import { json } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import { getTransforms } from '../common';
import { getTransforms } from '../transform-factories';
import { CustomWebpackSchema } from '../custom-webpack-schema';

export type CustomWebpackBrowserSchema = BrowserBuilderOptions & CustomWebpackSchema;

export function buildCustomWebpackBrowser(
export const buildCustomWebpackBrowser = (
options: CustomWebpackBrowserSchema,
context: BuilderContext
): Observable<BuilderOutput> {
return executeBrowserBuilder(options, context, getTransforms(options, context));
}
): ReturnType<typeof executeBrowserBuilder> =>
executeBrowserBuilder(options, context, getTransforms(options, context));

export default createBuilder<json.JsonObject & CustomWebpackBrowserSchema>(
buildCustomWebpackBrowser
Expand Down
33 changes: 5 additions & 28 deletions packages/custom-webpack/src/dev-server/index.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,7 @@
import { BuilderContext, createBuilder, targetFromTargetString } from '@angular-devkit/architect';
import {
DevServerBuilderOptions,
DevServerBuilderOutput,
executeDevServerBuilder,
} from '@angular-devkit/build-angular';
import { from, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { getTransforms } from '../common';
import { CustomWebpackSchema } from '../custom-webpack-schema';
import { createBuilder } from '@angular-devkit/architect';
import { DevServerBuilderOptions, executeDevServerBuilder } from '@angular-devkit/build-angular';
import { executeBrowserBasedBuilder } from '../generic-browser-builder';

export const serveCustomWebpackBrowser = (
options: DevServerBuilderOptions,
context: BuilderContext
): Observable<DevServerBuilderOutput> => {
async function setup() {
const browserTarget = targetFromTargetString(options.browserTarget);
return (context.getTargetOptions(browserTarget) as unknown) as CustomWebpackSchema;
}

return from(setup()).pipe(
switchMap(customWebpackOptions =>
executeDevServerBuilder(options, context, getTransforms(customWebpackOptions, context))
)
);
};

export default createBuilder<DevServerBuilderOptions, DevServerBuilderOutput>(
serveCustomWebpackBrowser
export default createBuilder<DevServerBuilderOptions>(
executeBrowserBasedBuilder(executeDevServerBuilder)
);
10 changes: 10 additions & 0 deletions packages/custom-webpack/src/extract-i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createBuilder } from '@angular-devkit/architect';
import {
executeExtractI18nBuilder,
ExtractI18nBuilderOptions,
} from '@angular-devkit/build-angular';
import { executeBrowserBasedBuilder } from '../generic-browser-builder';

export default createBuilder<ExtractI18nBuilderOptions>(
executeBrowserBasedBuilder(executeExtractI18nBuilder)
);
5 changes: 5 additions & 0 deletions packages/custom-webpack/src/extract-i18n/schema.ext.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Custom webpack extract-i18n schema for Build Facade",
"id": "BuildCustomWebpackExtractI18nSchema",
"description": "Extract i18n target options"
}
44 changes: 44 additions & 0 deletions packages/custom-webpack/src/generic-browser-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
BuilderContext,
targetFromTargetString,
BuilderHandlerFn,
} from '@angular-devkit/architect';
import { ExecutionTransformer } from '@angular-devkit/build-angular';
import { IndexHtmlTransform } from '@angular-devkit/build-angular/src/angular-cli-files/utilities/index-file/write-index-html';
import { from } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Configuration } from 'webpack';
import { CustomWebpackSchema } from './custom-webpack-schema';
import { getTransforms } from './transform-factories';
import { json } from '@angular-devkit/core';

export interface BrowserTargetOptions {
browserTarget: string;
}

export type BuilderExecutor<O extends BrowserTargetOptions & json.JsonObject> = (
options: O,
context: BuilderContext,
transforms?: {
webpackConfiguration?: ExecutionTransformer<Configuration>;
indexHtml?: IndexHtmlTransform;
}
) => any;

export const executeBrowserBasedBuilder = <O extends BrowserTargetOptions & json.JsonObject>(
executebBuilder: BuilderExecutor<O>
): BuilderHandlerFn<O> => (
options: O,
context: BuilderContext
): ReturnType<typeof executebBuilder> => {
async function setup() {
const browserTarget = targetFromTargetString(options.browserTarget);
return (context.getTargetOptions(browserTarget) as unknown) as CustomWebpackSchema;
}

return from(setup()).pipe(
switchMap(customWebpackOptions =>
executebBuilder(options, context, getTransforms(customWebpackOptions, context))
)
);
};
4 changes: 3 additions & 1 deletion packages/custom-webpack/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ export * from './browser';
export * from './karma';
export * from './server';
export * from './dev-server';
export * from './common';
export * from './extract-i18n';
export * from './transform-factories';
export * from './generic-browser-builder';
export { TargetOptions } from './type-definition';
12 changes: 5 additions & 7 deletions packages/custom-webpack/src/karma/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@
* Created by Evgeny Barabanov on 05/10/2018.
*/

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { executeKarmaBuilder, KarmaBuilderOptions } from '@angular-devkit/build-angular';
import { json } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import { customWebpackConfigTransformFactory } from '../common';
import { customWebpackConfigTransformFactory } from '../transform-factories';
import { CustomWebpackSchema } from '../custom-webpack-schema';

export type CustomWebpackKarmaBuildSchema = KarmaBuilderOptions & CustomWebpackSchema;

export function buildCustomWebpackKarma(
export const buildCustomWebpackKarma = (
options: CustomWebpackKarmaBuildSchema,
context: BuilderContext
): Observable<BuilderOutput> {
return executeKarmaBuilder(options, context, {
): ReturnType<typeof executeKarmaBuilder> =>
executeKarmaBuilder(options, context, {
webpackConfiguration: customWebpackConfigTransformFactory(options, context),
});
}

export default createBuilder<json.JsonObject & CustomWebpackKarmaBuildSchema>(
buildCustomWebpackKarma
Expand Down
10 changes: 6 additions & 4 deletions packages/custom-webpack/src/schemes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ module.exports = [
},
{
originalSchemaPath: '@angular-devkit/build-angular/src/dev-server/schema.json',
schemaExtensionPaths: [
`${__dirname}/dev-server/schema.ext.json`,
`${__dirname}/schema.ext.json`,
],
schemaExtensionPaths: [`${__dirname}/dev-server/schema.ext.json`],
newSchemaPath: `${__dirname}/../dist/dev-server/schema.json`,
},
{
originalSchemaPath: '@angular-devkit/build-angular/src/extract-i18n/schema.json',
schemaExtensionPaths: [`${__dirname}/extract-i18n/schema.ext.json`],
newSchemaPath: `${__dirname}/../dist/extract-i18n/schema.json`,
},
];
9 changes: 4 additions & 5 deletions packages/custom-webpack/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/ar
import { executeServerBuilder, ServerBuilderOptions } from '@angular-devkit/build-angular';
import { json } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import { customWebpackConfigTransformFactory } from '../common';
import { customWebpackConfigTransformFactory } from '../transform-factories';
import { CustomWebpackSchema } from '../custom-webpack-schema';

export type CustomWebpackServerSchema = ServerBuilderOptions & CustomWebpackSchema;

export function buildCustomWebpackServer(
export const buildCustomWebpackServer = (
options: CustomWebpackServerSchema,
context: BuilderContext
): Observable<BuilderOutput> {
return executeServerBuilder(options, context, {
): ReturnType<typeof executeServerBuilder> =>
executeServerBuilder(options, context, {
webpackConfiguration: customWebpackConfigTransformFactory(options, context),
});
}

export default createBuilder<json.JsonObject & CustomWebpackServerSchema>(buildCustomWebpackServer);
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { BuilderContext } from '@angular-devkit/architect';
import { ExecutionTransformer } from '@angular-devkit/build-angular';
import { IndexHtmlTransform } from '@angular-devkit/build-angular/src/angular-cli-files/utilities/index-file/write-index-html';
import { normalize, getSystemPath } from '@angular-devkit/core';

import { getSystemPath, normalize } from '@angular-devkit/core';
import { Configuration } from 'webpack';

import { CustomWebpackBuilder } from './custom-webpack-builder';
import { CustomWebpackSchema } from './custom-webpack-schema';
import { tsNodeRegister } from './utils';

export const customWebpackConfigTransformFactory: (
options: CustomWebpackSchema,
context: BuilderContext
) => ExecutionTransformer<Configuration> = (options, { workspaceRoot, target }) => browserWebpackConfig => {
) => ExecutionTransformer<Configuration> = (
options,
{ workspaceRoot, target }
) => browserWebpackConfig => {
return CustomWebpackBuilder.buildWebpackConfig(
normalize(workspaceRoot),
options.customWebpackConfig,
Expand Down

0 comments on commit 15f95d0

Please sign in to comment.