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 |
|
15 | import {BrowserCapability} from 'browser-capabilities';
|
16 |
|
17 | export type JsCompileTarget = 'es5'|'es2015'|'es2016'|'es2017'|'es2018';
|
18 |
|
19 | export 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 |
|
177 | export 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 |
|
256 | export 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 | */
|
264 | export 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 | }
|