polymer-project-config
Version:
reads, validates, and shapes your polymer.json project configuration
282 lines (254 loc) • 8.79 kB
text/typescript
/**
* @license
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
import {BrowserCapability} from 'browser-capabilities';
export type JsCompileTarget = 'es5'|'es2015'|'es2016'|'es2017'|'es2018';
export interface ProjectBuildOptions {
/**
* The name of this build, used to determine the output directory name.
*/
name?: string;
/**
* A build preset for this build. A build can inherit some base configuration
* from a named preset.
*/
preset?: string;
/**
* Generate a service worker for your application to cache all files and
* assets on the client.
*
* Polymer CLI will generate a service worker for your build using the
* [sw-precache library](https://github.com/GoogleChrome/sw-precache). To
* customize your service worker, create a sw-precache-config.js file in your
* project directory that exports your configuration. See the [sw-precache
* README](https://github.com/GoogleChrome/sw-precache) for a list of all
* supported options.
*
* Note that the sw-precache library uses a cache-first strategy for maximum
* speed and makes some other assumptions about how your service worker should
* behave. Read the "Considerations" section of the sw-precache README to make
* sure that this is suitable for your application.
*/
addServiceWorker?: boolean;
/**
* If `true`, generate an [HTTP/2 Push
* Manifest](https://github.com/GoogleChrome/http2-push-manifest) for your
* application.
*/
addPushManifest?: boolean;
/**
* A config file that's passed to the [sw-precache
* library](https://github.com/GoogleChrome/sw-precache). See [its
* README](https://github.com/GoogleChrome/sw-precache) for details of the
* format of this file.
*
* Ignored if `addServiceWorker` is not `true`.
*
* Defaults to `"sw-precache-config.js`.
*/
swPrecacheConfig?: string;
/**
* Insert prefetch link elements into your fragments so that all dependencies
* are prefetched immediately. Add dependency prefetching by inserting `<link
* rel="prefetch">` tags into entrypoint and `<link rel="import">` tags into
* fragments and shell for all dependencies.
*
* Note this option may trigger duplicate requests. See
* https://github.com/Polymer/polymer-build/issues/239 for details.
*/
insertPrefetchLinks?: boolean;
/**
* By default, fragments are unbundled. This is optimal for HTTP/2-compatible
* servers and clients.
*
* If the --bundle flag is supplied, all fragments are bundled together to
* reduce the number of file requests. This is optimal for sending to clients
* or serving from servers that are not HTTP/2 compatible.
*/
bundle?: boolean|{
/** URLs of files and/or folders that should not be inlined. */
excludes?: string[],
/** Inline external CSS file contents into <style> tags. */
inlineCss?: boolean,
/** Inline external Javascript file contents into <script> tags. */
inlineScripts?: boolean,
/** Rewrite element attributes inside of templates when inlining html. */
rewriteUrlsInTemplates?: boolean,
/** Create identity source maps for inline scripts. */
sourcemaps?: boolean,
/**
* Remove all comments except those tagged '@license', or starting with
* `<!--!` or `<!--#`, when true.
*/
stripComments?: boolean,
/** Remove unreachable/unused code when bundling. */
treeshake?: boolean,
};
/** Options for processing HTML. */
html?: {
/** Minify HTMl by removing comments and whitespace. */
minify?: boolean|{
/** HTML files listed here will not be minified. */
exclude?: string[],
},
};
/** Options for processing CSS. */
css?: {
/** Minify inlined and external CSS. */
minify?: boolean|{
/** CSS files listed here will not be minified. */
exclude?: string[],
},
};
/** Options for processing JavaScript. */
js?: {
/** Minify inlined and external JavaScript. */
minify?: boolean|{
/** JavaScript files listed here will not be minified. */
exclude?: string[],
},
/** Use babel to compile all ES6 JS down to ES5 for older browsers. */
compile?:
boolean|JsCompileTarget|{
target?: JsCompileTarget;
/** JavaScript files listed here will not be compiled. */
exclude?: string[],
},
/** Transform ES modules to AMD modules. */
transformModulesToAmd?: boolean,
};
/**
* Capabilities required for a browser to consume this build. Values include
* `es2015` and `push`. See canonical list at:
* https://github.com/Polymer/prpl-server-node/blob/master/src/capabilities.ts
*
* This field is purely a hint to servers reading this configuration, and
* does not affect the build process. A server supporting differential
* serving (e.g. prpl-server) can use this field to help decide which build
* to serve to a given user agent.
*/
browserCapabilities?: BrowserCapability[];
/**
* Update the entrypoint's `<base>` tag, to support serving this build from a
* non-root path, such as when doing differential serving based on user
* agent. Requires that a `<base>` tag already exists. This works well in
* conjunction with the convention of using relative URLs for static
* resources and absolute URLs for application routes.
*
* If `true`, use the build `name`. If a `string`, use that value.
* Leading/trailing slashes are optional.
*/
basePath?: boolean|string;
}
export const buildPresets = new Map<string, ProjectBuildOptions>([
[
'es5-bundled',
{
name: 'es5-bundled',
js: {
minify: true,
compile: 'es5',
transformModulesToAmd: true,
},
css: {minify: true},
html: {minify: true},
bundle: true,
addServiceWorker: true,
addPushManifest: false,
}
],
[
'es6-bundled',
{
name: 'es6-bundled',
browserCapabilities: ['es2015'],
js: {
minify: true,
compile: 'es2015',
transformModulesToAmd: true,
},
css: {minify: true},
html: {minify: true},
bundle: true,
addServiceWorker: true,
addPushManifest: false,
}
],
[
'es6-unbundled',
{
name: 'es6-unbundled',
browserCapabilities: ['es2015', 'push'],
js: {
minify: true,
compile: 'es2015',
transformModulesToAmd: true,
},
css: {minify: true},
html: {minify: true},
bundle: false,
addServiceWorker: true,
addPushManifest: true,
}
],
[
'uncompiled-bundled',
{
name: 'uncompiled-bundled',
browserCapabilities: ['es2018', 'modules'],
js: {minify: true},
css: {minify: true},
html: {minify: true},
bundle: true,
addServiceWorker: true,
addPushManifest: false,
}
],
[
'uncompiled-unbundled',
{
name: 'uncompiled-unbundled',
browserCapabilities: ['es2018', 'modules', 'push'],
js: {minify: true},
css: {minify: true},
html: {minify: true},
bundle: false,
addServiceWorker: true,
addPushManifest: true,
}
],
]);
export function isValidPreset(presetName: string) {
return buildPresets.has(presetName);
}
/**
* Apply a build preset (if a valid one exists on the config object) by
* deep merging the given config with the preset values.
*/
export function applyBuildPreset(config: ProjectBuildOptions) {
const presetName = config.preset;
if (!presetName || !isValidPreset(presetName)) {
return config;
}
const presetConfig = buildPresets.get(presetName) || {};
const mergedConfig = Object.assign({}, presetConfig, config);
// Object.assign is shallow, so we need to make sure we properly merge these
// deep options as well.
// NOTE(fks) 05-05-2017: While a little annoying, we use multiple
// Object.assign() calls here so that we do not filter-out additional
// user-defined build options at the config level.
mergedConfig.js = Object.assign({}, presetConfig.js, config.js);
mergedConfig.css = Object.assign({}, presetConfig.css, config.css);
mergedConfig.html = Object.assign({}, presetConfig.html, config.html);
return mergedConfig;
}