refactor(bazel): use web_package rule for index.html (#27995)

index.html needs to have the zone.js and the project bundle injected
using script tags. This used to be done explicitly by specifying a
new index.html but with `web_package` rule introduced in rules_nodejs,
it is now possible to perform the injection dynamically.

PR Close #27995
This commit is contained in:
Keen Yee Liau 2018-12-06 10:41:03 -08:00 committed by Andrew Kushnir
parent 2c9f0139a3
commit e8495b460f
5 changed files with 50 additions and 49 deletions

View File

@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"])
load("@angular//:index.bzl", "ng_module") load("@angular//:index.bzl", "ng_module")
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test_suite") load("@build_bazel_rules_typescript//:defs.bzl", "ts_library", "ts_web_test_suite")
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server") load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server")
load("@build_bazel_rules_nodejs//internal/web_package:web_package.bzl", "web_package")
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver") load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
ng_module( ng_module(
@ -33,22 +34,23 @@ rollup_bundle(
deps = ["//src"], deps = ["//src"],
) )
# Needed because the prodserver only loads static files that appear under this web_package(
# package. name = "prodapp",
genrule( assets = [
name = "zonejs", # do not sort
srcs = ["@npm//node_modules/zone.js:dist/zone.min.js"], "@npm//node_modules/zone.js:dist/zone.min.js",
outs = ["zone.min.js"], ":bundle.min.js",
cmd = "cp $< $@", ],
data = [
":bundle",
],
index_html = "index.html",
) )
history_server( history_server(
name = "prodserver", name = "prodserver",
data = [ data = [":prodapp"],
"index.html", templated_args = ["src/prodapp"],
":bundle",
":zonejs",
],
) )
ts_devserver( ts_devserver(
@ -63,8 +65,8 @@ ts_devserver(
static_files = [ static_files = [
"@npm//node_modules/zone.js:dist/zone.min.js", "@npm//node_modules/zone.js:dist/zone.min.js",
"@npm//node_modules/tslib:tslib.js", "@npm//node_modules/tslib:tslib.js",
"index.html",
], ],
index_html = "index.html",
deps = [":src"], deps = [":src"],
) )

View File

@ -81,7 +81,7 @@ export default function(options: BazelWorkspaceOptions): Rule {
const workspaceVersions = { const workspaceVersions = {
'RULES_NODEJS_VERSION': '0.16.5', 'RULES_NODEJS_VERSION': '0.16.5',
'RULES_TYPESCRIPT_VERSION': '0.22.0', 'RULES_TYPESCRIPT_VERSION': '0.22.1',
'ANGULAR_VERSION': existingVersions.Angular || clean(latestVersions.Angular), 'ANGULAR_VERSION': existingVersions.Angular || clean(latestVersions.Angular),
'RXJS_VERSION': existingVersions.RxJs || clean(latestVersions.RxJs), 'RXJS_VERSION': existingVersions.RxJs || clean(latestVersions.RxJs),
// TODO(kyliau): Consider moving this to latest-versions.ts // TODO(kyliau): Consider moving this to latest-versions.ts

View File

@ -1,16 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><%= utils.classify(name) %></title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="/zone.min.js"></script>
<script src="/bundle.min.js"></script>
</body>
</html>

View File

@ -15,6 +15,11 @@ import {validateProjectName} from '@schematics/angular/utility/validation';
import {getWorkspace} from '@schematics/angular/utility/config'; import {getWorkspace} from '@schematics/angular/utility/config';
import {Schema} from './schema'; import {Schema} from './schema';
/**
* Packages that build under Bazel require additional dev dependencies. This
* function adds those dependencies to "devDependencies" section in
* package.json.
*/
function addDevDependenciesToPackageJson(options: Schema) { function addDevDependenciesToPackageJson(options: Schema) {
return (host: Tree) => { return (host: Tree) => {
const packageJson = `${options.name}/package.json`; const packageJson = `${options.name}/package.json`;
@ -38,8 +43,8 @@ function addDevDependenciesToPackageJson(options: Schema) {
// TODO(kyliau): Consider moving this to latest-versions.ts // TODO(kyliau): Consider moving this to latest-versions.ts
'@bazel/bazel': '^0.21.0', '@bazel/bazel': '^0.21.0',
'@bazel/ibazel': '^0.9.0', '@bazel/ibazel': '^0.9.0',
'@bazel/karma': '^0.22.0', '@bazel/karma': '^0.22.1',
'@bazel/typescript': '^0.22.0', '@bazel/typescript': '^0.22.1',
}; };
const recorder = host.beginUpdate(packageJson); const recorder = host.beginUpdate(packageJson);
@ -53,7 +58,13 @@ function addDevDependenciesToPackageJson(options: Schema) {
}; };
} }
function overwriteMainAndIndex(options: Schema) { /**
* Append main.dev.ts and main.prod.ts to src directory. These files are needed
* by Bazel for devserver and prodserver, respectively. They are different from
* main.ts generated by CLI because they use platformBrowser (AOT) instead of
* platformBrowserDynamic (JIT).
*/
function addDevAndProdMainForAot(options: Schema) {
return (host: Tree) => { return (host: Tree) => {
let newProjectRoot = ''; let newProjectRoot = '';
try { try {
@ -63,18 +74,14 @@ function overwriteMainAndIndex(options: Schema) {
} }
const srcDir = `${newProjectRoot}/${options.name}/src`; const srcDir = `${newProjectRoot}/${options.name}/src`;
return mergeWith( return mergeWith(apply(url('./files'), [
apply( applyTemplates({
url('./files'), utils: strings,
[ ...options,
applyTemplates({ 'dot': '.',
utils: strings, }),
...options, move(srcDir),
'dot': '.', ]));
}),
move(srcDir),
]),
MergeStrategy.Overwrite);
}; };
} }
@ -199,8 +206,8 @@ export default function(options: Schema): Rule {
skipInstall: true, skipInstall: true,
}), }),
addDevDependenciesToPackageJson(options), addDevDependenciesToPackageJson(options),
addDevAndProdMainForAot(options),
schematic('bazel-workspace', options), schematic('bazel-workspace', options),
overwriteMainAndIndex(options),
overwriteGitignore(options), overwriteGitignore(options),
updateWorkspaceFileToUseBazelBuilder(options), updateWorkspaceFileToUseBazelBuilder(options),
]); ]);

View File

@ -70,14 +70,22 @@ describe('Ng-new Schematic', () => {
expect(files).toContain('/demo/src/main.ts'); expect(files).toContain('/demo/src/main.ts');
}); });
it('should overwrite index.html with script tags', () => { it('should not overwrite index.html with script tags', () => {
const options = {...defaultOptions}; const options = {...defaultOptions};
const host = schematicRunner.runSchematic('ng-new', options); const host = schematicRunner.runSchematic('ng-new', options);
const {files} = host; const {files} = host;
expect(files).toContain('/demo/src/index.html'); expect(files).toContain('/demo/src/index.html');
const content = host.readContent('/demo/src/index.html'); const content = host.readContent('/demo/src/index.html');
expect(content).toMatch('<script src="/zone.min.js"></script>'); expect(content).not.toMatch('<script src="/zone.min.js"></script>');
expect(content).toMatch('<script src="/bundle.min.js"></script>'); expect(content).not.toMatch('<script src="/bundle.min.js"></script>');
});
it('should generate main.dev.ts and main.prod.ts', () => {
const options = {...defaultOptions};
const host = schematicRunner.runSchematic('ng-new', options);
const {files} = host;
expect(files).toContain('/demo/src/main.dev.ts');
expect(files).toContain('/demo/src/main.prod.ts');
}); });
it('should overwrite .gitignore for bazel-out directory', () => { it('should overwrite .gitignore for bazel-out directory', () => {