UNPKG

8.79 kBPlain TextView Raw
1/**
2 * @license
3 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
4 * This code may only be used under the BSD style license found at
5 * http://polymer.github.io/LICENSE.txt
6 * The complete set of authors may be found at
7 * http://polymer.github.io/AUTHORS.txt
8 * The complete set of contributors may be found at
9 * http://polymer.github.io/CONTRIBUTORS.txt
10 * Code distributed by Google as part of the polymer project is also
11 * subject to an additional IP rights grant found at
12 * http://polymer.github.io/PATENTS.txt
13 */
14
15import {BrowserCapability} from 'browser-capabilities';
16
17export type JsCompileTarget = 'es5'|'es2015'|'es2016'|'es2017'|'es2018';
18
19export interface ProjectBuildOptions {
20 /**
21 * The name of this build, used to determine the output directory name.
22 */
23 name?: string;
24
25 /**
26 * A build preset for this build. A build can inherit some base configuration
27 * from a named preset.
28 */
29 preset?: string;
30
31 /**
32 * Generate a service worker for your application to cache all files and
33 * assets on the client.
34 *
35 * Polymer CLI will generate a service worker for your build using the
36 * [sw-precache library](https://github.com/GoogleChrome/sw-precache). To
37 * customize your service worker, create a sw-precache-config.js file in your
38 * project directory that exports your configuration. See the [sw-precache
39 * README](https://github.com/GoogleChrome/sw-precache) for a list of all
40 * supported options.
41 *
42 * Note that the sw-precache library uses a cache-first strategy for maximum
43 * speed and makes some other assumptions about how your service worker should
44 * behave. Read the "Considerations" section of the sw-precache README to make
45 * sure that this is suitable for your application.
46 */
47 addServiceWorker?: boolean;
48
49 /**
50 * If `true`, generate an [HTTP/2 Push
51 * Manifest](https://github.com/GoogleChrome/http2-push-manifest) for your
52 * application.
53 */
54 addPushManifest?: boolean;
55
56 /**
57 * A config file that's passed to the [sw-precache
58 * library](https://github.com/GoogleChrome/sw-precache). See [its
59 * README](https://github.com/GoogleChrome/sw-precache) for details of the
60 * format of this file.
61 *
62 * Ignored if `addServiceWorker` is not `true`.
63 *
64 * Defaults to `"sw-precache-config.js`.
65 */
66 swPrecacheConfig?: string;
67
68 /**
69 * Insert prefetch link elements into your fragments so that all dependencies
70 * are prefetched immediately. Add dependency prefetching by inserting `<link
71 * rel="prefetch">` tags into entrypoint and `<link rel="import">` tags into
72 * fragments and shell for all dependencies.
73 *
74 * Note this option may trigger duplicate requests. See
75 * https://github.com/Polymer/polymer-build/issues/239 for details.
76 */
77 insertPrefetchLinks?: boolean;
78
79 /**
80 * By default, fragments are unbundled. This is optimal for HTTP/2-compatible
81 * servers and clients.
82 *
83 * If the --bundle flag is supplied, all fragments are bundled together to
84 * reduce the number of file requests. This is optimal for sending to clients
85 * or serving from servers that are not HTTP/2 compatible.
86 */
87 bundle?: boolean|{
88
89 /** URLs of files and/or folders that should not be inlined. */
90 excludes?: string[],
91
92 /** Inline external CSS file contents into <style> tags. */
93 inlineCss?: boolean,
94
95 /** Inline external Javascript file contents into <script> tags. */
96 inlineScripts?: boolean,
97
98 /** Rewrite element attributes inside of templates when inlining html. */
99 rewriteUrlsInTemplates?: boolean,
100
101 /** Create identity source maps for inline scripts. */
102 sourcemaps?: boolean,
103
104 /**
105 * Remove all comments except those tagged '@license', or starting with
106 * `<!--!` or `<!--#`, when true.
107 */
108 stripComments?: boolean,
109
110 /** Remove unreachable/unused code when bundling. */
111 treeshake?: boolean,
112 };
113
114 /** Options for processing HTML. */
115 html?: {
116 /** Minify HTMl by removing comments and whitespace. */
117 minify?: boolean|{
118 /** HTML files listed here will not be minified. */
119 exclude?: string[],
120 },
121 };
122
123 /** Options for processing CSS. */
124 css?: {
125 /** Minify inlined and external CSS. */
126 minify?: boolean|{
127 /** CSS files listed here will not be minified. */
128 exclude?: string[],
129 },
130 };
131
132 /** Options for processing JavaScript. */
133 js?: {
134 /** Minify inlined and external JavaScript. */
135 minify?: boolean|{
136 /** JavaScript files listed here will not be minified. */
137 exclude?: string[],
138 },
139
140 /** Use babel to compile all ES6 JS down to ES5 for older browsers. */
141 compile?:
142 boolean|JsCompileTarget|{
143 target?: JsCompileTarget;
144 /** JavaScript files listed here will not be compiled. */
145 exclude?: string[],
146 },
147
148 /** Transform ES modules to AMD modules. */
149 transformModulesToAmd?: boolean,
150 };
151
152 /**
153 * Capabilities required for a browser to consume this build. Values include
154 * `es2015` and `push`. See canonical list at:
155 * https://github.com/Polymer/prpl-server-node/blob/master/src/capabilities.ts
156 *
157 * This field is purely a hint to servers reading this configuration, and
158 * does not affect the build process. A server supporting differential
159 * serving (e.g. prpl-server) can use this field to help decide which build
160 * to serve to a given user agent.
161 */
162 browserCapabilities?: BrowserCapability[];
163
164 /**
165 * Update the entrypoint's `<base>` tag, to support serving this build from a
166 * non-root path, such as when doing differential serving based on user
167 * agent. Requires that a `<base>` tag already exists. This works well in
168 * conjunction with the convention of using relative URLs for static
169 * resources and absolute URLs for application routes.
170 *
171 * If `true`, use the build `name`. If a `string`, use that value.
172 * Leading/trailing slashes are optional.
173 */
174 basePath?: boolean|string;
175}
176
177export const buildPresets = new Map<string, ProjectBuildOptions>([
178 [
179 'es5-bundled',
180 {
181 name: 'es5-bundled',
182 js: {
183 minify: true,
184 compile: 'es5',
185 transformModulesToAmd: true,
186 },
187 css: {minify: true},
188 html: {minify: true},
189 bundle: true,
190 addServiceWorker: true,
191 addPushManifest: false,
192 }
193 ],
194 [
195 'es6-bundled',
196 {
197 name: 'es6-bundled',
198 browserCapabilities: ['es2015'],
199 js: {
200 minify: true,
201 compile: 'es2015',
202 transformModulesToAmd: true,
203 },
204 css: {minify: true},
205 html: {minify: true},
206 bundle: true,
207 addServiceWorker: true,
208 addPushManifest: false,
209 }
210 ],
211 [
212 'es6-unbundled',
213 {
214 name: 'es6-unbundled',
215 browserCapabilities: ['es2015', 'push'],
216 js: {
217 minify: true,
218 compile: 'es2015',
219 transformModulesToAmd: true,
220 },
221 css: {minify: true},
222 html: {minify: true},
223 bundle: false,
224 addServiceWorker: true,
225 addPushManifest: true,
226 }
227 ],
228 [
229 'uncompiled-bundled',
230 {
231 name: 'uncompiled-bundled',
232 browserCapabilities: ['es2018', 'modules'],
233 js: {minify: true},
234 css: {minify: true},
235 html: {minify: true},
236 bundle: true,
237 addServiceWorker: true,
238 addPushManifest: false,
239 }
240 ],
241 [
242 'uncompiled-unbundled',
243 {
244 name: 'uncompiled-unbundled',
245 browserCapabilities: ['es2018', 'modules', 'push'],
246 js: {minify: true},
247 css: {minify: true},
248 html: {minify: true},
249 bundle: false,
250 addServiceWorker: true,
251 addPushManifest: true,
252 }
253 ],
254]);
255
256export function isValidPreset(presetName: string) {
257 return buildPresets.has(presetName);
258}
259
260/**
261 * Apply a build preset (if a valid one exists on the config object) by
262 * deep merging the given config with the preset values.
263 */
264export function applyBuildPreset(config: ProjectBuildOptions) {
265 const presetName = config.preset;
266 if (!presetName || !isValidPreset(presetName)) {
267 return config;
268 }
269
270 const presetConfig = buildPresets.get(presetName) || {};
271 const mergedConfig = Object.assign({}, presetConfig, config);
272 // Object.assign is shallow, so we need to make sure we properly merge these
273 // deep options as well.
274 // NOTE(fks) 05-05-2017: While a little annoying, we use multiple
275 // Object.assign() calls here so that we do not filter-out additional
276 // user-defined build options at the config level.
277 mergedConfig.js = Object.assign({}, presetConfig.js, config.js);
278 mergedConfig.css = Object.assign({}, presetConfig.css, config.css);
279 mergedConfig.html = Object.assign({}, presetConfig.html, config.html);
280 return mergedConfig;
281}