build(ivy): create hello world rollup (#22004)
This is a customization of the rollup_bundle rule from rules_nodejs which adds the build-optimizer as a plugin. Add a functional test with fast round-trip that asserts the minified app still works. Publish the min.js artifact on circleCI so we can track its size. PR Close #22004
This commit is contained in:
parent
2707012181
commit
370ab66c4f
|
@ -64,6 +64,12 @@ jobs:
|
||||||
# See https://github.com/bazelbuild/bazel/issues/4257
|
# See https://github.com/bazelbuild/bazel/issues/4257
|
||||||
- run: bazel query --output=label '//modules/... union //packages/... union //tools/...' | xargs bazel test --config=ci
|
- run: bazel query --output=label '//modules/... union //packages/... union //tools/...' | xargs bazel test --config=ci
|
||||||
|
|
||||||
|
# CircleCI will allow us to go back and view/download these artifacts from past builds.
|
||||||
|
# Also we can use a service like https://buildsize.org/ to automatically track binary size of these artifacts.
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
||||||
|
destination: packages/core/test/bundling/hello_world/bundle.min.js
|
||||||
|
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: *cache_key
|
key: *cache_key
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -32,6 +32,7 @@ filegroup(
|
||||||
"reflect-metadata",
|
"reflect-metadata",
|
||||||
"source-map-support",
|
"source-map-support",
|
||||||
"minimist",
|
"minimist",
|
||||||
|
"tslib",
|
||||||
] for ext in [
|
] for ext in [
|
||||||
"*.js",
|
"*.js",
|
||||||
"*.json",
|
"*.json",
|
||||||
|
|
14
WORKSPACE
14
WORKSPACE
|
@ -5,7 +5,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
git_repository(
|
git_repository(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
||||||
commit = "230d39a391226f51c03448f91eb61370e2e58c42",
|
commit = "5307b572d86a0764bd86a5681fc72cca016e9390",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||||
|
@ -56,3 +56,15 @@ http_archive(
|
||||||
strip_prefix = "bazel-9755c72b48866ed034bd28aa033e9abd27431b1e",
|
strip_prefix = "bazel-9755c72b48866ed034bd28aa033e9abd27431b1e",
|
||||||
sha256 = "5b8443fc3481b5fcd9e7f348e1dd93c1397f78b223623c39eb56494c55f41962",
|
sha256 = "5b8443fc3481b5fcd9e7f348e1dd93c1397f78b223623c39eb56494c55f41962",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# We have a source dependency on the Devkit repository, because it's built with
|
||||||
|
# Bazel.
|
||||||
|
# This allows us to edit sources and have the effect appear immediately without
|
||||||
|
# re-packaging or "npm link"ing.
|
||||||
|
# Even better, things like aspects will visit the entire graph including
|
||||||
|
# ts_library rules in the devkit repository.
|
||||||
|
git_repository(
|
||||||
|
name = "angular_devkit",
|
||||||
|
remote = "https://github.com/angular/devkit.git",
|
||||||
|
commit = "69fcdee61c5ff3f08aa609dec69155dfd29c809a",
|
||||||
|
)
|
||||||
|
|
|
@ -60,6 +60,7 @@ module.exports = function(config) {
|
||||||
'dist/all/@angular/compiler-cli/**',
|
'dist/all/@angular/compiler-cli/**',
|
||||||
'dist/all/@angular/compiler/test/aot/**',
|
'dist/all/@angular/compiler/test/aot/**',
|
||||||
'dist/all/@angular/compiler/test/render3/**',
|
'dist/all/@angular/compiler/test/render3/**',
|
||||||
|
'dist/all/@angular/core/test/bundling/**',
|
||||||
'dist/all/@angular/examples/**/e2e_test/*',
|
'dist/all/@angular/examples/**/e2e_test/*',
|
||||||
'dist/all/@angular/language-service/**',
|
'dist/all/@angular/language-service/**',
|
||||||
'dist/all/@angular/router/test/**',
|
'dist/all/@angular/router/test/**',
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "angular-srcs",
|
"name": "angular-srcs",
|
||||||
"version": "TODO this should be 6.0.0-beta.0, workaround",
|
|
||||||
"version": "6.0.0-beta.2",
|
"version": "6.0.0-beta.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"branchPattern": "2.0.*",
|
"branchPattern": "2.0.*",
|
||||||
|
|
|
@ -1 +1,19 @@
|
||||||
# Empty marker file, indicating this directory is a Bazel package.
|
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||||
|
|
||||||
|
nodejs_binary(
|
||||||
|
name = "rollup_with_build_optimizer",
|
||||||
|
data = ["@angular_devkit//packages/angular_devkit/build_optimizer:lib"],
|
||||||
|
# Since our rule extends the one in rules_nodejs, we use the same runtime
|
||||||
|
# dependency @build_bazel_rules_nodejs_rollup_deps. We don't need any
|
||||||
|
# additional npm dependencies when we run rollup or uglify.
|
||||||
|
entry_point = "build_bazel_rules_nodejs_rollup_deps/node_modules/rollup/bin/rollup",
|
||||||
|
node_modules = "@build_bazel_rules_nodejs_rollup_deps//:node_modules",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
nodejs_binary(
|
||||||
|
name = "modify_tsconfig",
|
||||||
|
data = ["modify_tsconfig.js"],
|
||||||
|
entry_point = "angular/packages/bazel/src/modify_tsconfig.js",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
"""Provides ES5 syntax with ESModule import/exports.
|
||||||
|
|
||||||
|
This exposes another flavor of output JavaScript, which is ES5 syntax
|
||||||
|
with ES2015 module syntax (import/export).
|
||||||
|
All Bazel rules should consume the standard dev or prod mode.
|
||||||
|
However we need to publish this flavor on NPM, so it's necessary to be able
|
||||||
|
to produce it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The provider downstream rules use to access the outputs
|
||||||
|
ESM5Info = provider(
|
||||||
|
doc = "Typescript compilation outputs in ES5 syntax with ES Modules",
|
||||||
|
fields = {
|
||||||
|
"transitive_output": """Dict of [rootDir, .js depset] entries.
|
||||||
|
|
||||||
|
The value is a depset of the .js output files.
|
||||||
|
The key is the prefix that should be stripped off the files
|
||||||
|
when resolving modules, eg. for file
|
||||||
|
bazel-bin/[external/wkspc/]path/to/package/label.esm5/path/to/package/file.js
|
||||||
|
the rootdir would be
|
||||||
|
bazel-bin/[external/wkspc/]path/to/package/label.esm5""",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def _map_closure_path(file):
|
||||||
|
result = file.short_path[:-len(".closure.js")]
|
||||||
|
# short_path is meant to be used when accessing runfiles in a binary, where
|
||||||
|
# the CWD is inside the current repo. Therefore files in external repo have a
|
||||||
|
# short_path of ../external/wkspc/path/to/package
|
||||||
|
# We want to strip the first two segments from such paths.
|
||||||
|
if (result.startswith("../")):
|
||||||
|
result = "/".join(result.split("/")[2:])
|
||||||
|
return result + ".js"
|
||||||
|
|
||||||
|
def _join(array):
|
||||||
|
return "/".join([p for p in array if p])
|
||||||
|
|
||||||
|
def _esm5_outputs_aspect(target, ctx):
|
||||||
|
if not hasattr(target, "typescript"):
|
||||||
|
return []
|
||||||
|
|
||||||
|
# We create a new tsconfig.json file that will have our compilation settings
|
||||||
|
tsconfig = ctx.actions.declare_file("%s_esm5.tsconfig.json" % target.label.name)
|
||||||
|
|
||||||
|
workspace = target.label.workspace_root if target.label.workspace_root else ""
|
||||||
|
|
||||||
|
# re-root the outputs under a ".esm5" directory so the path don't collide
|
||||||
|
out_dir = ctx.label.name + ".esm5"
|
||||||
|
if workspace:
|
||||||
|
out_dir = out_dir + "/" + workspace
|
||||||
|
|
||||||
|
outputs = [ctx.actions.declare_file(_join([out_dir, _map_closure_path(f)]))
|
||||||
|
for f in target.typescript.replay_params.outputs
|
||||||
|
if not f.short_path.endswith(".externs.js")]
|
||||||
|
|
||||||
|
ctx.actions.run(
|
||||||
|
executable = ctx.executable._modify_tsconfig,
|
||||||
|
inputs = [target.typescript.replay_params.tsconfig],
|
||||||
|
outputs = [tsconfig],
|
||||||
|
arguments = [
|
||||||
|
target.typescript.replay_params.tsconfig.path,
|
||||||
|
tsconfig.path,
|
||||||
|
_join([workspace, target.label.package, ctx.label.name + ".esm5"]),
|
||||||
|
ctx.bin_dir.path
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx.action(
|
||||||
|
progress_message = "Compiling TypeScript (ES5 with ES Modules) %s" % target.label,
|
||||||
|
inputs = target.typescript.replay_params.inputs + [tsconfig],
|
||||||
|
outputs = outputs,
|
||||||
|
arguments = [tsconfig.path],
|
||||||
|
executable = target.typescript.replay_params.compiler,
|
||||||
|
execution_requirements = {
|
||||||
|
"supports-workers": "0",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
root_dir = _join([
|
||||||
|
ctx.bin_dir.path,
|
||||||
|
workspace,
|
||||||
|
target.label.package,
|
||||||
|
ctx.label.name + ".esm5",
|
||||||
|
])
|
||||||
|
|
||||||
|
transitive_output={root_dir: depset(outputs)}
|
||||||
|
for dep in ctx.rule.attr.deps:
|
||||||
|
if ESM5Info in dep:
|
||||||
|
transitive_output.update(dep[ESM5Info].transitive_output)
|
||||||
|
|
||||||
|
return [ESM5Info(
|
||||||
|
transitive_output = transitive_output,
|
||||||
|
)]
|
||||||
|
|
||||||
|
# Downstream rules can use this aspect to access the ESM5 output flavor.
|
||||||
|
# Only terminal rules (those which expect never to be used in deps[]) should do
|
||||||
|
# this.
|
||||||
|
esm5_outputs_aspect = aspect(
|
||||||
|
implementation = _esm5_outputs_aspect,
|
||||||
|
# Recurse to the deps of any target we visit
|
||||||
|
attr_aspects = ['deps'],
|
||||||
|
attrs = {
|
||||||
|
"_modify_tsconfig": attr.label(
|
||||||
|
default = Label("//packages/bazel/src:modify_tsconfig"),
|
||||||
|
executable = True,
|
||||||
|
cfg = "host"),
|
||||||
|
# We must list tsc_wrapped here to ensure it's built before the action runs
|
||||||
|
# For some reason, having the compiler output as an input to the action above
|
||||||
|
# is not sufficient.
|
||||||
|
"_tsc_wrapped": attr.label(
|
||||||
|
default = Label("@build_bazel_rules_typescript//internal/tsc_wrapped:tsc_wrapped_bin"),
|
||||||
|
executable = True,
|
||||||
|
cfg = "host",
|
||||||
|
),
|
||||||
|
# Same comment as for tsc_wrapped above.
|
||||||
|
"_ngc_wrapped": attr.label(
|
||||||
|
default = Label("//packages/bazel/src/ngc-wrapped"),
|
||||||
|
executable = True,
|
||||||
|
cfg = "host",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Read a tsconfig.json file intended to produce production mode
|
||||||
|
* JS output, modify it to produce esm5 output instead, and write the result
|
||||||
|
* to disk.
|
||||||
|
*/
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
function main(args) {
|
||||||
|
if (args.length < 3) {
|
||||||
|
console.error('Usage: $0 input.tsconfig.json output.tsconfig.json newRoot binDir');
|
||||||
|
}
|
||||||
|
[input, output, newRoot, binDir] = args;
|
||||||
|
|
||||||
|
const data = JSON.parse(fs.readFileSync(input, {encoding: 'utf-8'}));
|
||||||
|
data['compilerOptions']['target'] = 'es5';
|
||||||
|
data['bazelOptions']['es5Mode'] = true;
|
||||||
|
data['bazelOptions']['tsickle'] = false;
|
||||||
|
data['compilerOptions']['outDir'] = path.join(data['compilerOptions']['outDir'], newRoot);
|
||||||
|
if (data['angularCompilerOptions']) {
|
||||||
|
data['angularCompilerOptions']['expectedOut'] =
|
||||||
|
data['angularCompilerOptions']['expectedOut'].map(
|
||||||
|
f => f.replace(/\.closure\.js$/, '.js').replace(binDir, path.join(binDir, newRoot)));
|
||||||
|
}
|
||||||
|
fs.writeFileSync(output, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
process.exitCode = main(process.argv.slice(2));
|
||||||
|
}
|
|
@ -180,6 +180,7 @@ def ngc_compile_action(ctx, label, inputs, outputs, messages_out, tsconfig_file,
|
||||||
tsconfig = tsconfig_file,
|
tsconfig = tsconfig_file,
|
||||||
inputs = inputs,
|
inputs = inputs,
|
||||||
outputs = outputs,
|
outputs = outputs,
|
||||||
|
compiler = ctx.executable.compiler,
|
||||||
)
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
"""This provides a variant of rollup_bundle that works better for Angular apps.
|
||||||
|
|
||||||
|
It registers @angular-devkit/build-optimizer as a rollup plugin, to get
|
||||||
|
better optimization. It also uses ESM5 format inputs, as this is what
|
||||||
|
build-optimizer is hard-coded to look for and transform.
|
||||||
|
"""
|
||||||
|
|
||||||
|
load("@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl",
|
||||||
|
"rollup_module_mappings_aspect",
|
||||||
|
"ROLLUP_ATTRS",
|
||||||
|
"ROLLUP_OUTPUTS",
|
||||||
|
"write_rollup_config",
|
||||||
|
"run_rollup",
|
||||||
|
"run_uglify")
|
||||||
|
load("@build_bazel_rules_nodejs//internal:collect_es6_sources.bzl", collect_es2015_sources = "collect_es6_sources")
|
||||||
|
load(":esm5.bzl", "esm5_outputs_aspect", "ESM5Info")
|
||||||
|
|
||||||
|
PACKAGES=["core", "common"]
|
||||||
|
PLUGIN_CONFIG="{sideEffectFreeModules: [\n%s]}" % ",\n".join(
|
||||||
|
[" 'packages/{0}/{0}.esm5'".format(p) for p in PACKAGES])
|
||||||
|
BO_ROLLUP="angular_devkit/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
|
||||||
|
BO_PLUGIN="require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG)
|
||||||
|
|
||||||
|
def _ng_rollup_bundle(ctx):
|
||||||
|
# We don't expect anyone to make use of this bundle yet, but it makes this rule
|
||||||
|
# compatible with rollup_bundle which allows them to be easily swapped back and
|
||||||
|
# forth.
|
||||||
|
esm2015_rollup_config = write_rollup_config(ctx, filename = "_%s.rollup_es6.conf.js")
|
||||||
|
run_rollup(ctx, collect_es2015_sources(ctx), esm2015_rollup_config, ctx.outputs.build_es6)
|
||||||
|
|
||||||
|
esm5_sources = []
|
||||||
|
root_dirs = []
|
||||||
|
|
||||||
|
for dep in ctx.attr.deps:
|
||||||
|
if ESM5Info in dep:
|
||||||
|
# TODO(alexeagle): we could make the module resolution in the rollup plugin
|
||||||
|
# faster if we kept the files grouped with their root dir. This approach just
|
||||||
|
# passes in both lists and requires multiple lookups (with expensive exception
|
||||||
|
# handling) to locate the files again.
|
||||||
|
transitive_output = dep[ESM5Info].transitive_output
|
||||||
|
root_dirs.extend(transitive_output.keys())
|
||||||
|
esm5_sources.extend(transitive_output.values())
|
||||||
|
|
||||||
|
rollup_config = write_rollup_config(ctx, [BO_PLUGIN], root_dirs)
|
||||||
|
run_rollup(ctx, depset(transitive = esm5_sources).to_list(), rollup_config, ctx.outputs.build_es5)
|
||||||
|
|
||||||
|
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min)
|
||||||
|
run_uglify(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min_debug, debug = True)
|
||||||
|
|
||||||
|
return DefaultInfo(files=depset([ctx.outputs.build_es5_min]))
|
||||||
|
|
||||||
|
ng_rollup_bundle = rule(
|
||||||
|
implementation = _ng_rollup_bundle,
|
||||||
|
attrs = dict(ROLLUP_ATTRS, **{
|
||||||
|
"deps": attr.label_list(aspects = [
|
||||||
|
rollup_module_mappings_aspect,
|
||||||
|
esm5_outputs_aspect,
|
||||||
|
]),
|
||||||
|
"_rollup": attr.label(
|
||||||
|
executable = True,
|
||||||
|
cfg="host",
|
||||||
|
default = Label("@angular//packages/bazel/src:rollup_with_build_optimizer")),
|
||||||
|
}),
|
||||||
|
outputs = ROLLUP_OUTPUTS,
|
||||||
|
)
|
|
@ -0,0 +1,45 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
load("//tools:defaults.bzl", "ts_library")
|
||||||
|
load("//packages/bazel/src:ng_rollup_bundle.bzl", "ng_rollup_bundle")
|
||||||
|
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")
|
||||||
|
|
||||||
|
ts_library(
|
||||||
|
name = "hello_world",
|
||||||
|
srcs = ["index.ts"],
|
||||||
|
deps = [
|
||||||
|
"//packages/core",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ng_rollup_bundle(
|
||||||
|
name = "bundle",
|
||||||
|
# TODO(alexeagle): This is inconsistent.
|
||||||
|
# We try to teach users to always have their workspace at the start of a
|
||||||
|
# path, to disambiguate from other workspaces.
|
||||||
|
# Here, the rule implementation is looking in an execroot where the layout
|
||||||
|
# has an "external" directory for external dependencies.
|
||||||
|
# This should probably start with "angular/" and let the rule deal with it.
|
||||||
|
entry_point = "packages/core/test/bundling/hello_world/index.js",
|
||||||
|
deps = [
|
||||||
|
":hello_world",
|
||||||
|
"//packages/core",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ts_library(
|
||||||
|
name = "test_lib",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = ["domino_typings.d.ts"] + glob(["*_spec.ts"]),
|
||||||
|
deps = ["//packages:types"],
|
||||||
|
)
|
||||||
|
|
||||||
|
jasmine_node_test(
|
||||||
|
name = "test",
|
||||||
|
data = [
|
||||||
|
":bundle",
|
||||||
|
":bundle.js",
|
||||||
|
":bundle.min_debug.js",
|
||||||
|
],
|
||||||
|
deps = [":test_lib"],
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module 'domino' {
|
||||||
|
function createWindow(html: string, url: string): Window;
|
||||||
|
const impl: {Element: any};
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* @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 {ɵT as T, ɵb1 as b1, ɵdefineComponent as defineComponent, ɵrenderComponent as renderComponent, ɵt as t} from '@angular/core';
|
||||||
|
|
||||||
|
class HelloWorld {
|
||||||
|
name = 'World';
|
||||||
|
|
||||||
|
static ngComponentDef = defineComponent({
|
||||||
|
type: HelloWorld,
|
||||||
|
tag: 'hello-world',
|
||||||
|
factory: () => new HelloWorld(),
|
||||||
|
template: function HelloWorldTemplate(ctx: HelloWorld, cm: boolean) {
|
||||||
|
if (cm) {
|
||||||
|
T(0);
|
||||||
|
}
|
||||||
|
t(0, b1('Hello ', ctx.name, '!'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderComponent(HelloWorld);
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* @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 * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
const UTF8 = {
|
||||||
|
encoding: 'utf-8'
|
||||||
|
};
|
||||||
|
const PACKAGE = 'angular/packages/core/test/bundling/hello_world';
|
||||||
|
|
||||||
|
import * as domino from 'domino';
|
||||||
|
|
||||||
|
describe('treeshaking with uglify', () => {
|
||||||
|
let content: string;
|
||||||
|
beforeAll(() => {
|
||||||
|
content = fs.readFileSync(
|
||||||
|
path.join(process.env['TEST_SRCDIR'], PACKAGE, 'bundle.min_debug.js'), UTF8);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should drop unused TypeScript helpers',
|
||||||
|
() => { expect(content).not.toContain('__asyncGenerator'); });
|
||||||
|
|
||||||
|
it('should not contain rxjs from commonjs distro', () => {
|
||||||
|
expect(content).not.toContain('commonjsGlobal');
|
||||||
|
expect(content).not.toContain('createCommonjsModule');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not contain zone.js', () => { expect(content).not.toContain('scheduleMicroTask'); });
|
||||||
|
|
||||||
|
describe('functional test in domino', () => {
|
||||||
|
let document: Document;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const window = domino.createWindow('', 'http://localhost');
|
||||||
|
(global as any).document = document = window.document;
|
||||||
|
// Trick to avoid Event patching from
|
||||||
|
// https://github.com/angular/angular/blob/7cf5e95ac9f0f2648beebf0d5bd9056b79946970/packages/platform-browser/src/dom/events/dom_events.ts#L112-L132
|
||||||
|
// It fails with Domino with TypeError: Cannot assign to read only property
|
||||||
|
// 'stopImmediatePropagation' of object '#<Event>'
|
||||||
|
(global as any).Event = null;
|
||||||
|
|
||||||
|
document.body.innerHTML = '<hello-world></hello-world>';
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
(global as any).document = undefined;
|
||||||
|
(global as any).Element = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should render hello world when not minified', () => {
|
||||||
|
require(path.join(PACKAGE, 'bundle.js'));
|
||||||
|
expect(document.body.textContent).toEqual('Hello World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render hello world when debug minified', () => {
|
||||||
|
require(path.join(PACKAGE, 'bundle.min_debug.js'));
|
||||||
|
expect(document.body.textContent).toEqual('Hello World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render hello world when fully minified', () => {
|
||||||
|
require(path.join(PACKAGE, 'bundle.min.js'));
|
||||||
|
expect(document.body.textContent).toEqual('Hello World!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -14,13 +14,9 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
||||||
# Filesystem interactions #
|
# Filesystem interactions #
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
# Don't create bazel-* symlinks in the WORKSPACE directory.
|
# Put bazel's symlinks under dist, so results go to dist/bin
|
||||||
# These require .gitignore and may scare users.
|
# There is still a `bazel-out` symlink created in the project root.
|
||||||
# Also, it's a workaround for https://github.com/bazelbuild/rules_typescript/issues/12
|
build --symlink_prefix=dist/
|
||||||
# which affects the common case of having `tsconfig.json` in the WORKSPACE directory.
|
|
||||||
#
|
|
||||||
# Instead, you should run `bazel info bazel-bin` to find out where the outputs went.
|
|
||||||
build --symlink_prefix=/
|
|
||||||
|
|
||||||
# Performance: avoid stat'ing input files
|
# Performance: avoid stat'ing input files
|
||||||
build --watchfs
|
build --watchfs
|
||||||
|
@ -50,3 +46,6 @@ build:ci --noshow_progress
|
||||||
|
|
||||||
# Don't run manual tests on CI
|
# Don't run manual tests on CI
|
||||||
test:ci --test_tag_filters=-manual
|
test:ci --test_tag_filters=-manual
|
||||||
|
|
||||||
|
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||||
|
test:ci --flaky_test_attempts=2
|
|
@ -59,6 +59,7 @@ var specFiles: any =
|
||||||
'@angular/examples/**',
|
'@angular/examples/**',
|
||||||
'@angular/platform-browser/**',
|
'@angular/platform-browser/**',
|
||||||
'@angular/platform-browser-dynamic/**',
|
'@angular/platform-browser-dynamic/**',
|
||||||
|
'@angular/core/test/bundling/**',
|
||||||
'@angular/core/test/zone/**',
|
'@angular/core/test/zone/**',
|
||||||
'@angular/core/test/render3/**',
|
'@angular/core/test/render3/**',
|
||||||
'@angular/core/test/fake_async_spec.*',
|
'@angular/core/test/fake_async_spec.*',
|
||||||
|
|
Loading…
Reference in New Issue