chore(analytics): Build hello_world, check constraints
Create gulp targets to build `hello_world` and check its gzipped size against size constraints. See #5312, #5314
This commit is contained in:
parent
225b9d306b
commit
31f85f0297
|
@ -45,3 +45,6 @@ npm-debug.log
|
||||||
|
|
||||||
# build-analytics
|
# build-analytics
|
||||||
.build-analytics
|
.build-analytics
|
||||||
|
|
||||||
|
# built dart payload tests
|
||||||
|
/modules_dart/payload/**/build
|
||||||
|
|
36
gulpfile.js
36
gulpfile.js
|
@ -252,9 +252,10 @@ gulp.task('build/check.apidocs.dart',
|
||||||
// pubbuild
|
// pubbuild
|
||||||
// WARNING: this task is very slow (~15m as of July 2015)
|
// WARNING: this task is very slow (~15m as of July 2015)
|
||||||
|
|
||||||
gulp.task('build/pubbuild.dart',
|
gulp.task(
|
||||||
pubbuild(gulp, gulpPlugins,
|
'build/pubbuild.dart',
|
||||||
{src: CONFIG.dest.dart, dest: CONFIG.dest.js.dart2js, command: DART_SDK.PUB}));
|
pubbuild.subdirs(gulp, gulpPlugins,
|
||||||
|
{src: CONFIG.dest.dart, dest: CONFIG.dest.js.dart2js, command: DART_SDK.PUB}));
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
// formatting
|
// formatting
|
||||||
|
@ -584,6 +585,30 @@ gulp.task('test.unit.dart', function(done) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Dart Payload Size Test
|
||||||
|
// This test will fail if the size of our hello_world app goes beyond one of
|
||||||
|
// these values when compressed at the specified level.
|
||||||
|
// Measure in bytes.
|
||||||
|
var _DART_PAYLOAD_SIZE_LIMITS = {'uncompressed': 375 * 1024, 'gzip level=6': 105 * 1024};
|
||||||
|
gulp.task('test.payload.dart/ci', function(done) {
|
||||||
|
runSequence('build/packages.dart', '!pubget.payload.dart', '!pubbuild.payload.dart',
|
||||||
|
'!checkAndReport.payload.dart', done);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('!pubget.payload.dart',
|
||||||
|
pubget.dir(gulp, gulpPlugins,
|
||||||
|
{dir: 'modules_dart/payload/hello_world', command: DART_SDK.PUB}));
|
||||||
|
|
||||||
|
gulp.task('!pubbuild.payload.dart',
|
||||||
|
pubbuild.single(gulp, gulpPlugins,
|
||||||
|
{command: DART_SDK.PUB, src: 'modules_dart/payload/hello_world'}));
|
||||||
|
|
||||||
|
gulp.task('!checkAndReport.payload.dart', function() {
|
||||||
|
var reportSize = require('./tools/analytics/reportsize');
|
||||||
|
return reportSize('modules_dart/payload/hello_world/build/web/*.dart.js',
|
||||||
|
{failConditions: _DART_PAYLOAD_SIZE_LIMITS, prefix: 'hello_world'});
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('watch.dart.dev', function(done) {
|
gulp.task('watch.dart.dev', function(done) {
|
||||||
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
|
runSequence('build/tree.dart', 'build/pure-packages.dart', '!build/pubget.angular2.dart',
|
||||||
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
|
'!build/change_detect.dart', '!build/remove-pub-symlinks', 'build.dart.material.css',
|
||||||
|
@ -1053,10 +1078,9 @@ gulp.task('!bundle.copy', function() {
|
||||||
gulp.src('dist/js/bundle/**').pipe(gulp.dest('dist/js/dev/es5/bundle')));
|
gulp.src('dist/js/bundle/**').pipe(gulp.dest('dist/js/dev/es5/bundle')));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('!bundles.js.checksize', function() {
|
gulp.task('!bundles.js.checksize', function(done) {
|
||||||
var reportSize = require('./tools/analytics/reportsize');
|
var reportSize = require('./tools/analytics/reportsize');
|
||||||
return reportSize('dist/js/bundle/**', {printToConsole: false,
|
return reportSize('dist/js/bundle/**', {printToConsole: ['gzip level=2']});
|
||||||
reportAnalytics: true});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('bundles.js',
|
gulp.task('bundles.js',
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
name: hello_world
|
||||||
|
environment:
|
||||||
|
sdk: '>=1.10.0 <2.0.0'
|
||||||
|
dependencies:
|
||||||
|
observe: '^0.13.1'
|
||||||
|
angular2: any
|
||||||
|
browser: '^0.10.0'
|
||||||
|
dependency_overrides:
|
||||||
|
angular2:
|
||||||
|
path: ../../../dist/dart/angular2
|
||||||
|
transformers:
|
||||||
|
- angular2:
|
||||||
|
platform_directives: 'package:angular2/src/common/directives.dart#CORE_DIRECTIVES'
|
||||||
|
entry_points:
|
||||||
|
- web/index.dart
|
||||||
|
|
||||||
|
- $dart2js:
|
||||||
|
minify: true
|
||||||
|
commandLineOptions:
|
||||||
|
- --show-package-warnings
|
||||||
|
- --trust-type-annotations
|
||||||
|
- --trust-primitives
|
||||||
|
# Uncomment to generate summaries from dart2js
|
||||||
|
# - --dump-info
|
|
@ -0,0 +1,68 @@
|
||||||
|
library hello_world.index;
|
||||||
|
|
||||||
|
import "package:angular2/bootstrap.dart" show bootstrap;
|
||||||
|
import "package:angular2/core.dart"
|
||||||
|
show ElementRef, Component, Directive, Injectable;
|
||||||
|
import "package:angular2/render.dart" show Renderer;
|
||||||
|
|
||||||
|
main() {
|
||||||
|
// Bootstrapping only requires specifying a root component.
|
||||||
|
|
||||||
|
// The boundary between the Angular application and the rest of the page is
|
||||||
|
|
||||||
|
// the shadowDom of this root component.
|
||||||
|
|
||||||
|
// The selector of the component passed in is used to find where to insert the
|
||||||
|
|
||||||
|
// application.
|
||||||
|
|
||||||
|
// You can use the light dom of the <hello-app> tag as temporary content (for
|
||||||
|
|
||||||
|
// example 'Loading...') before the application is ready.
|
||||||
|
bootstrap(HelloCmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A service available to the Injector, used by the HelloCmp component.
|
||||||
|
@Injectable()
|
||||||
|
class GreetingService {
|
||||||
|
String greeting = "hello";
|
||||||
|
}
|
||||||
|
// Directives are light-weight. They don't allow new
|
||||||
|
|
||||||
|
// expression contexts (use @Component for those needs).
|
||||||
|
@Directive(selector: "[red]")
|
||||||
|
class RedDec {
|
||||||
|
// ElementRef is always injectable and it wraps the element on which the
|
||||||
|
|
||||||
|
// directive was found by the compiler.
|
||||||
|
RedDec(ElementRef el, Renderer renderer) {
|
||||||
|
renderer.setElementStyle(el, "color", "red");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Angular 2.0 supports 2 basic types of directives:
|
||||||
|
|
||||||
|
// - Component - the basic building blocks of Angular 2.0 apps. Backed by
|
||||||
|
|
||||||
|
// ShadowDom.(http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/)
|
||||||
|
|
||||||
|
// - Directive - add behavior to existing elements.
|
||||||
|
|
||||||
|
// @Component is AtScript syntax to annotate the HelloCmp class as an Angular
|
||||||
|
|
||||||
|
// 2.0 component.
|
||||||
|
@Component(
|
||||||
|
selector: "hello-app",
|
||||||
|
viewProviders: const [GreetingService],
|
||||||
|
template:
|
||||||
|
'''<div class="greeting">{{greeting}} <span red>world</span>!</div>
|
||||||
|
<button class="changeButton" (click)="changeGreeting()">change greeting</button>''',
|
||||||
|
directives: const [RedDec])
|
||||||
|
class HelloCmp {
|
||||||
|
String greeting;
|
||||||
|
HelloCmp(GreetingService service) {
|
||||||
|
this.greeting = service.greeting;
|
||||||
|
}
|
||||||
|
void changeGreeting() {
|
||||||
|
this.greeting = "howdy";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<title>Hello Angular 2.0</title>
|
||||||
|
<body>
|
||||||
|
<hello-app>
|
||||||
|
Loading...
|
||||||
|
</hello-app>
|
||||||
|
|
||||||
|
<script src="index.dart" type="application/dart"></script>
|
||||||
|
<script src="packages/browser/dart.js" type="text/javascript"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -22,11 +22,15 @@ const _gzipConfigs = {
|
||||||
|
|
||||||
const _defaultOptions = {
|
const _defaultOptions = {
|
||||||
// @type {Object<string, number>}
|
// @type {Object<string, number>}
|
||||||
// - Key(s) must match keys of `_gzipConfigs`.
|
// - Key(s) must match one of `_gzipConfigs` keys.
|
||||||
// - Values are the max size (in bytes) allowed for that configuration.
|
// - Values are the max size (in bytes) allowed for that configuration.
|
||||||
failConditions: {},
|
failConditions: {},
|
||||||
prefix: '',
|
prefix: '',
|
||||||
printToConsole: false,
|
// @type {Array<string>|boolean}
|
||||||
|
// Entries must match one of `_gzipConfigs` keys. These values will be
|
||||||
|
// printed to the screen.
|
||||||
|
// If this is the boolean value `true`, will print all to screen.
|
||||||
|
printToConsole: ['gzip level=6'],
|
||||||
reportAnalytics: true
|
reportAnalytics: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +45,7 @@ function reportSize(glob, options) {
|
||||||
options[key] = _defaultOptions[key];
|
options[key] = _defaultOptions[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var errStream = _checkFailConditionConfig(options.failConditions);
|
var errStream = _checkConfig(options);
|
||||||
if (errStream) {
|
if (errStream) {
|
||||||
return errStream;
|
return errStream;
|
||||||
}
|
}
|
||||||
|
@ -83,27 +87,29 @@ function reportSize(glob, options) {
|
||||||
if (options.reportAnalytics) {
|
if (options.reportAnalytics) {
|
||||||
analytics.bundleSize(filePath, fileLen, compressionLevel);
|
analytics.bundleSize(filePath, fileLen, compressionLevel);
|
||||||
}
|
}
|
||||||
if (options.printToConsole) {
|
if (_shouldPrint(options, compressionLevel)) {
|
||||||
console.log(` ${filePath} => ${fileLen} bytes (${compressionLevel})`)
|
console.log(` ${filePath} => ${fileLen} bytes (${compressionLevel})`)
|
||||||
}
|
}
|
||||||
if (options.failConditions.hasOwnProperty(compressionLevel)) {
|
if (options.failConditions.hasOwnProperty(compressionLevel)) {
|
||||||
if (options.failConditions[compressionLevel] < fileLen) {
|
if (options.failConditions[compressionLevel] < fileLen) {
|
||||||
errs.push(`Max size for "${compressionLevel}" is ` +
|
errs.push(`Max size for "${compressionLevel}" is ` +
|
||||||
`${options.failConditions[compressionLevel]}, but the size is now ${fileLen}.`);
|
`${options.failConditions[compressionLevel]}, but the size is now ${fileLen}.`);
|
||||||
if (options.printToConsole) {
|
|
||||||
console.log(` !!! ${errs[errs.length - 1]}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _shouldPrint(options, compressionLevel) {
|
||||||
|
const printAll = typeof options.printToConsole == 'boolean' && options.printToConsole;
|
||||||
|
return printAll || options.printToConsole.indexOf(compressionLevel) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an error stream if the fail conditions are not provided property.
|
// Returns an error stream if the fail conditions are not provided property.
|
||||||
// Returns `null` if everything is fine.
|
// Returns `null` if everything is fine.
|
||||||
function _checkFailConditionConfig(failConditions) {
|
function _checkConfig(config) {
|
||||||
for (const key in failConditions) {
|
for (const key in config.failConditions) {
|
||||||
if (failConditions.hasOwnProperty(key)) {
|
if (config.failConditions.hasOwnProperty(key)) {
|
||||||
if (!_gzipConfigs.hasOwnProperty(key)) {
|
if (!_gzipConfigs.hasOwnProperty(key)) {
|
||||||
var stream = new Stream();
|
var stream = new Stream();
|
||||||
stream.emit(
|
stream.emit(
|
||||||
|
@ -114,6 +120,19 @@ function _checkFailConditionConfig(failConditions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof config.printToConsole != 'boolean') {
|
||||||
|
for (var i = 0; i < config.printToConsole.length; ++i) {
|
||||||
|
const key = config.printToConsole[i];
|
||||||
|
if (!_gzipConfigs.hasOwnProperty(key)) {
|
||||||
|
var stream = new Stream();
|
||||||
|
stream.emit(
|
||||||
|
'error',
|
||||||
|
new Error(`Incorrect value "${key}" in printToConsole. Check _gzipConfigs.`));
|
||||||
|
stream.emit('end');
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ var path = require('path');
|
||||||
var glob = require('glob');
|
var glob = require('glob');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
module.exports = function(gulp, plugins, config) {
|
function buildAllWebSubdirs(gulp, plugins, config) {
|
||||||
return function() {
|
return function() {
|
||||||
var webFolders = [].slice.call(glob.sync(path.join(config.src, '*/web')));
|
var webFolders = [].slice.call(glob.sync(path.join(config.src, '*/web')));
|
||||||
return nextFolder();
|
return nextFolder();
|
||||||
|
@ -17,20 +17,34 @@ module.exports = function(gulp, plugins, config) {
|
||||||
}
|
}
|
||||||
var folder = path.resolve(path.join(webFolders.shift(), '..'));
|
var folder = path.resolve(path.join(webFolders.shift(), '..'));
|
||||||
var destFolder = path.resolve(path.join(config.dest, path.basename(folder)));
|
var destFolder = path.resolve(path.join(config.dest, path.basename(folder)));
|
||||||
var pubMode = config.mode || 'release';
|
|
||||||
var pubArgs = ['build', '--mode', pubMode, '-o', destFolder];
|
|
||||||
|
|
||||||
return util.processToPromise(spawn(config.command, pubArgs, {
|
const nextConfig = {
|
||||||
stdio: 'inherit',
|
command: config.command,
|
||||||
cwd: folder
|
dest: destFolder,
|
||||||
})).then(function() {
|
mode: config.mode,
|
||||||
|
src: folder
|
||||||
|
};
|
||||||
|
return single(nextConfig).then(function() {
|
||||||
return replaceDartWithJsScripts(gulp, destFolder);
|
return replaceDartWithJsScripts(gulp, destFolder);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return removeWebFolder(gulp, destFolder);
|
return removeWebFolder(gulp, destFolder);
|
||||||
}).then(nextFolder);
|
}).then(nextFolder);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
function single(config) {
|
||||||
|
var pubMode = config.mode || 'release';
|
||||||
|
var pubArgs = ['build', '--mode', pubMode];
|
||||||
|
if (config.dest) {
|
||||||
|
pubArgs = pubArgs.concat(['-o', config.dest]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.processToPromise(spawn(config.command, pubArgs, {
|
||||||
|
stdio: 'inherit',
|
||||||
|
cwd: config.src
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function replaceDartWithJsScripts(gulp, folder) {
|
function replaceDartWithJsScripts(gulp, folder) {
|
||||||
return util.streamToPromise(gulp.src(path.join(folder, '**/*.html'))
|
return util.streamToPromise(gulp.src(path.join(folder, '**/*.html'))
|
||||||
|
@ -45,6 +59,10 @@ function replaceDartWithJsScripts(gulp, folder) {
|
||||||
.pipe(gulp.dest(folder)));
|
.pipe(gulp.dest(folder)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function singleWrapper(gulp, plugins, config) {
|
||||||
|
return function() { return single(config); };
|
||||||
|
}
|
||||||
|
|
||||||
function removeWebFolder(gulp, folder) {
|
function removeWebFolder(gulp, folder) {
|
||||||
var folders = [].slice.call(glob.sync(path.join(folder, 'web', '*')));
|
var folders = [].slice.call(glob.sync(path.join(folder, 'web', '*')));
|
||||||
folders.forEach(function(subFolder) {
|
folders.forEach(function(subFolder) {
|
||||||
|
@ -53,3 +71,8 @@ function removeWebFolder(gulp, folder) {
|
||||||
fs.rmdirSync(path.join(folder, 'web'));
|
fs.rmdirSync(path.join(folder, 'web'));
|
||||||
return Q.resolve();
|
return Q.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
single: singleWrapper,
|
||||||
|
subdirs: buildAllWebSubdirs
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue