Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Commit

Permalink
Merge New Build Permutation Support (#551)
Browse files Browse the repository at this point in the history
* Convert build to single build stream (#509)

* Convert build to single build stream, add bundled flag

* Clarify `--add-prefetch` build flag (#510)

* rename confusing --insert-dependency-links flag to --prefetch-dependencies

* rename prefetchDepedencies to addPrefetchLinks

* rename to insert-prefetch-links

* respond to review comments

* Cleanup how optimize streams work, in preparation for babel stream (#524)

* Cleanup how optimize streams work, in preparation for babel stream

* death to lets

* redeisn optimize interface

* pull stream piping into a helper function

* rollback cli dash-case naming

* remove unused gulpif

* update buildoptions to match planned polymer.json options

* add babel to build stream, replace uglify with babili es2015 minifier (#525)

* Cleanup how optimize streams work, in preparation for babel stream

* add babel to build stream

* death to lets

* redeisn optimize interface

* pull stream piping into a helper function

* rollback cli dash-case naming

* replace uglify with babili

* fix bad merge conflict

* fixup js-minify description

* remove unused gulpif

* update buildoptions to match planned polymer.json options

* remove old comment

* let to const

* add service worker flag to build command (#534)

* add service worker flag to build command

* reword flags and descriptions

* quick reword again

* get rid of skiplibcheck

* debug to info

* Add support for polymer.json build configurations (#545)

* Add support for named build permutations

* respond to PR feedback

* add comments on build function

* update logging to be cleaner

* update for new naming rules

* update polymer-project-config to v1.2.0

* Update CHANGELOG.md

* update polymer-build version, update shrinkwrap
  • Loading branch information
FredKSchott authored Jan 31, 2017
1 parent c231a2c commit e98176f
Show file tree
Hide file tree
Showing 15 changed files with 554 additions and 245 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Upcoming

- **New `build` Behavior**: New build options have been added to give you more control over the generated build. These options can be defined in your project's `polymer.json`, or via CLI flags. Run `polymer build --help` to see a list of new supported CLI flags.
- Multiple builds can now be defined in your project's `polymer.json`.
- **Previously default behaviors (minifying JavaScript, generating service workers, etc) are now turned off by default.**

## v0.18.0-alpha.9

Expand Down
206 changes: 188 additions & 18 deletions npm-shrinkwrap.json

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"author": "The Polymer Project Authors",
"license": "BSD-3-Clause",
"dependencies": {
"@types/babel-core": "^6.7.14",
"@types/chalk": "^0.4.31",
"@types/del": "^2.2.31",
"@types/findup-sync": "^0.3.29",
Expand All @@ -38,6 +39,10 @@
"@types/uglify-js": "^2.6.28",
"@types/vinyl": "^2.0.0",
"@types/vinyl-fs": "0.0.28",
"@types/yeoman-generator": "0.0.30",
"babel-core": "^6.17.0",
"babel-preset-babili": "0.0.9",
"babel-preset-es2015": "^6.18.0",
"bower": "1.8.0",
"bower-json": "^0.8.1",
"bower-logger": "^0.2.2",
Expand All @@ -61,13 +66,12 @@
"polylint": "^2.10.0",
"polymer-analyzer": "2.0.0-alpha.20",
"polymer-build": "^0.6.0",
"polymer-project-config": "^1.0.0",
"polymer-project-config": "^1.2.0",
"polyserve": "0.16.0-prerelease.9",
"request": "^2.72.0",
"resolve": "^1.1.7",
"tar-fs": "^1.12.0",
"temp": "^0.8.3",
"uglify-js": "^2.7.0",
"update-notifier": "^1.0.0",
"vinyl": "^1.1.1",
"vinyl-fs": "^2.4.3",
Expand Down
199 changes: 81 additions & 118 deletions src/build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,142 +12,105 @@
* http://polymer.github.io/PATENTS.txt
*/

import * as del from 'del';
import * as gulpif from 'gulp-if';
import * as path from 'path';
import * as logging from 'plylog';
import {dest} from 'vinyl-fs';

import mergeStream = require('merge-stream');
import {PolymerProject, addServiceWorker, forkStream, SWConfig} from 'polymer-build';

import {InlineCSSOptimizeStream, JSOptimizeStream, CSSOptimizeStream, HTMLOptimizeStream} from './optimize-streams';
import {PolymerProject, addServiceWorker, SWConfig} from 'polymer-build';

import {ProjectConfig} from 'polymer-project-config';
import {OptimizeOptions, getOptimizeStreams} from './optimize-streams';
import {ProjectConfig, ProjectBuildOptions} from 'polymer-project-config';
import {PrefetchTransform} from './prefetch';
import {waitFor} from './streams';
import {parsePreCacheConfig} from './sw-precache';
import {waitFor, pipeStreams} from './streams';
import {loadServiceWorkerConfig} from './load-config';

const logger = logging.getLogger('cli.build.build');
export const mainBuildDirectoryName = 'build';

const unbundledBuildDirectory = 'build/unbundled';
const bundledBuildDirectory = 'build/bundled';

export interface BuildOptions {
swPrecacheConfig?: string;
insertDependencyLinks?: boolean;
// TODO(fks) 07-21-2016: Fully complete these with available options
html?: {collapseWhitespace?: boolean; removeComments?: boolean};
css?: {stripWhitespace?: boolean};
js?: {minify?: boolean};
}

/**
* Generate a single build based on the given `options` ProjectBuildOptions.
* Note that this function is only concerned with that single build, and does
* not care about the collection of builds defined on the config.
*
* TODO(fks) 01-26-2017: Generate multiple builds with a single PolymerProject
* instance. Currently blocked because splitHtml() & rejoinHtml() cannot be run
* on multiple streams in parallel. See: https://github.com/Polymer/polymer-build/issues/113
*/
export async function build(
options: BuildOptions, config: ProjectConfig): Promise<void> {
let polymerProject = new PolymerProject(config);
options: ProjectBuildOptions, config: ProjectConfig): Promise<void> {
const buildName = options.name || 'default';
const optimizeOptions:
OptimizeOptions = {css: options.css, js: options.js, html: options.html};
const polymerProject = new PolymerProject(config);

// If no name is provided, write directly to the build/ directory.
// If a build name is provided, write to that subdirectory.
const buildDirectory = path.join(mainBuildDirectoryName, buildName);
logger.debug(`"${buildDirectory}": Building with options:`, options);

const sourcesStream = pipeStreams([
polymerProject.sources(),
polymerProject.splitHtml(),
getOptimizeStreams(optimizeOptions),
polymerProject.rejoinHtml()
]);

const depsStream = pipeStreams([
polymerProject.dependencies(),
polymerProject.splitHtml(),
getOptimizeStreams(optimizeOptions),
polymerProject.rejoinHtml()
]);

let buildStream: NodeJS.ReadableStream =
mergeStream(sourcesStream, depsStream);

if (options.bundle) {
buildStream = buildStream.pipe(polymerProject.bundler);
}

if (options.insertDependencyLinks) {
logger.debug(
`Additional dependency links will be inserted into application`);
if (options.insertPrefetchLinks) {
buildStream = buildStream.pipe(new PrefetchTransform(polymerProject));
}

// mix in optimization options from build command
// TODO: let this be set by the user
let optimizeOptions = {
html: Object.assign({removeComments: true}, options.html),
css: Object.assign({stripWhitespace: true}, options.css),
js: Object.assign({minify: true}, options.js),
};

logger.info(`Preparing build...`);
await del([unbundledBuildDirectory, bundledBuildDirectory]);

logger.info(`Building application...`);

logger.debug(`Reading source files...`);
let sourcesStream =
polymerProject.sources()
.pipe(polymerProject.splitHtml())
.pipe(gulpif(/\.js$/, new JSOptimizeStream(optimizeOptions.js)))
.pipe(gulpif(/\.css$/, new CSSOptimizeStream(optimizeOptions.css)))
// TODO(fks): Remove this InlineCSSOptimizeStream stream once CSS
// is properly being isolated by splitHtml() & rejoinHtml().
.pipe(gulpif(/\.html$/, new InlineCSSOptimizeStream(optimizeOptions.css)))
.pipe(gulpif(/\.html$/, new HTMLOptimizeStream(optimizeOptions.html)))
.pipe(polymerProject.rejoinHtml());

logger.debug(`Reading dependencies...`);
let depsStream =
polymerProject.dependencies()
.pipe(polymerProject.splitHtml())
.pipe(gulpif(/\.js$/, new JSOptimizeStream(optimizeOptions.js)))
.pipe(gulpif(/\.css$/, new CSSOptimizeStream(optimizeOptions.css)))
// TODO(fks): Remove this InlineCSSOptimizeStream stream once CSS
// is properly being isolated by splitHtml() & rejoinHtml().
.pipe(gulpif(/\.html$/, new InlineCSSOptimizeStream(optimizeOptions.css)))
.pipe(gulpif(/\.html$/, new HTMLOptimizeStream(optimizeOptions.html)))
.pipe(polymerProject.rejoinHtml());

let buildStream = mergeStream(sourcesStream, depsStream);

let unbundledPhase = forkStream(buildStream)
.once(
'data',
() => {
logger.info('Generating build/unbundled...');
})
.pipe(gulpif(
options.insertDependencyLinks || false,
new PrefetchTransform(polymerProject)))
.pipe(dest(unbundledBuildDirectory));

let bundledPhase = forkStream(buildStream)
.once(
'data',
() => {
logger.info('Generating build/bundled...');
})
.pipe(polymerProject.bundler)
.pipe(dest(bundledBuildDirectory));

let swPrecacheConfig = path.resolve(
buildStream.once('data', () => {
logger.info(`(${buildName}) Building...`);
});

// Finish the build stream by piping it into the final build directory.
buildStream = buildStream.pipe(dest(buildDirectory));

// If a service worker was requested, parse the service worker config file
// while the build is in progress. Loading the config file during the build
// saves the user ~300ms vs. loading it afterwards.
const swPrecacheConfigPath = path.resolve(
config.root, options.swPrecacheConfig || 'sw-precache-config.js');
let loadSWConfig = parsePreCacheConfig(swPrecacheConfig);
let swConfig: SWConfig|null = null;
if (options.addServiceWorker) {
swConfig = await loadServiceWorkerConfig(swPrecacheConfigPath);
}

loadSWConfig.then((swConfig) => {
// There is nothing left to do, so wait for the build stream to complete.
await waitFor(buildStream);

// addServiceWorker() reads from the file system, so we need to wait for
// the build stream to finish writing to disk before calling it.
if (options.addServiceWorker) {
logger.debug(`Generating service worker...`);
if (swConfig) {
logger.debug(`Service worker config found`, swConfig);
} else {
logger.debug(`No service worker configuration found at ${swPrecacheConfig
}, continuing with defaults`);
logger.debug(
`No service worker configuration found at ` +
`${swPrecacheConfigPath}, continuing with defaults`);
}
});
await addServiceWorker({
buildRoot: buildDirectory,
project: polymerProject,
swPrecacheConfig: swConfig || undefined,
bundled: options.bundle,
});
}

// Once the unbundled build stream is complete, create a service worker for
// the build
let unbundledPostProcessing =
Promise.all([loadSWConfig, waitFor(unbundledPhase)]).then((results) => {
let swConfig: SWConfig|undefined = results[0] || undefined;
return addServiceWorker({
buildRoot: unbundledBuildDirectory,
project: polymerProject,
swPrecacheConfig: swConfig,
});
});

// Once the bundled build stream is complete, create a service worker for the
// build
let bundledPostProcessing =
Promise.all([loadSWConfig, waitFor(bundledPhase)]).then((results) => {
let swConfig: SWConfig|undefined = results[0] || undefined;
return addServiceWorker({
buildRoot: bundledBuildDirectory,
project: polymerProject,
swPrecacheConfig: swConfig,
bundled: true,
});
});

await Promise.all([unbundledPostProcessing, bundledPostProcessing]);
logger.info('Build complete!');
logger.info(`(${buildName}) Build complete!`);
}
4 changes: 2 additions & 2 deletions src/build/sw-precache.ts → src/build/load-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import * as fs from 'fs';
import * as logging from 'plylog';
import {SWConfig} from 'polymer-build';

let logger = logging.getLogger('cli.build.sw-precache');
let logger = logging.getLogger('cli.build.load-config');

export function parsePreCacheConfig(configFile: string):
export function loadServiceWorkerConfig(configFile: string):
Promise<SWConfig|null> {
return new Promise<SWConfig|null>((resolve, _reject) => {
fs.stat(configFile, (statError) => {
Expand Down
Loading

0 comments on commit e98176f

Please sign in to comment.