UNPKG

6.75 kBPlain TextView Raw
1import rollup_cjs from '@rollup/plugin-commonjs';
2import rollup_multi from '@rollup/plugin-multi-entry';
3import rollup_re from '@rollup/plugin-node-resolve';
4import * as fs from 'fs-extra-plus';
5/////// for handlebars
6import { precompile as hbsPrecompile } from 'hbsp'; // promise style
7import * as Path from 'path';
8//////// for Postcss
9import postcss from "postcss";
10/////// for JS
11import * as rollup from 'rollup';
12import rollup_ts from 'rollup-plugin-typescript2'; // TODO: might want to update to @rollup/plugin-typescript (But it is a different implementation)
13import { now } from './utils';
14
15const processors = [
16 require("autoprefixer"),
17 require("postcss-import"),
18 require("postcss-mixins"),
19 require("postcss-nested")
20];
21
22// --------- For Handlebars --------- //
23export async function tmplFiles(files: string[], distFile: string) {
24
25 await fs.saferRemove([distFile]);
26
27 const templateContent = [];
28
29 for (let file of files) {
30
31 const htmlTemplate = await fs.readFile(file, "utf8");
32 const template = await hbsPrecompile(file, htmlTemplate);
33 templateContent.push(template);
34 }
35
36 await fs.writeFile(distFile, templateContent.join("\n"), "utf8");
37}
38// --------- /For Handlebars --------- //
39
40// --------- For postCss --------- //
41export async function pcssFiles(entries: string[], distFile: string) {
42
43 const mapFile = distFile + ".map";
44 let pcssResult: any;
45 try {
46
47 await fs.saferRemove([distFile, mapFile]);
48
49 const processor = postcss(processors);
50 const pcssNodes = [];
51
52 // we parse all of the .pcss files
53 for (let srcFile of entries) {
54 // read the file
55 let pcss = await fs.readFile(srcFile, "utf8");
56
57 const pcssNode = postcss.parse(pcss, {
58 from: srcFile
59 });
60 pcssNodes.push(pcssNode);
61
62 }
63
64 // build build the combined rootNode and its result
65 let rootNode = null;
66 for (let pcssNode of pcssNodes) {
67 rootNode = (rootNode) ? rootNode.append(pcssNode) : pcssNode;
68 }
69 const rootNodeResult = rootNode!.toResult();
70
71 // we process the rootNodeResult
72 pcssResult = await processor.process(rootNodeResult, {
73 from: "undefined",
74 to: distFile,
75 map: { inline: false }
76 });
77 } catch (ex) {
78 console.log(`postcss ERROR - Cannot process ${distFile} because (setting css empty file) \n${ex}`);
79 // we write the .css and .map files
80 await fs.writeFile(distFile, "", "utf8");
81 await fs.writeFile(mapFile, "", "utf8");
82 return;
83 }
84
85 // we write the .css and .map files
86 await fs.writeFile(distFile, pcssResult.css, "utf8");
87 await fs.writeFile(mapFile, pcssResult.map.toString(), "utf8");
88}
89// --------- /For postCss --------- //
90
91
92// --------- For Rollup (JavaScript) --------- //
93export interface RollupFilesOptions {
94 ts?: boolean;
95 /* {importName: globalName} - (default undefined) define the list of global names (assumed to be mapped to window._name_) */
96 globals?: { [importName: string]: string };
97 watch: boolean;
98 tsconfig?: any;
99}
100const defaultOpts: RollupFilesOptions = {
101 ts: true,
102 watch: false
103};
104
105/**
106 * @param {*} opts
107 * - ts?: boolean - (default true)
108 * -
109 * - watch: true | false (default false)
110 */
111export async function rollupFiles(entries: string[], distFile: string, opts: RollupFilesOptions) {
112 opts = Object.assign({}, defaultOpts, opts);
113
114 await fs.saferRemove("./.rpt2_cache");
115
116 // delete the previous ouutput files
117 const mapFile = distFile + ".map";
118 try {
119 // Note: Do not delete the distFile if we are in watch mode, otherwise, rollup throw an uncatched promise exception
120 if (!opts.watch) {
121 await fs.saferRemove(distFile);
122 }
123 await fs.saferRemove(mapFile);
124 } catch (ex) {
125 console.log(`Can't delete dist files`, ex);
126 }
127
128
129 // set the default rollup input options
130 const inputOptions: any = {
131 input: entries,
132 plugins: [rollup_multi(), rollup_cjs(), rollup_re()]
133 };
134
135 // --------- Exclude 3rd Party circular Dependencies --------- //
136 const excludeCircularWarningByImporters = ['node_modules/d3', 'node_modules/moment'];
137 inputOptions.onwarn = function onwarn(warning: any) {
138 let skip = false;
139
140 if (warning.code === 'CIRCULAR_DEPENDENCY') {
141 for (let skipImporter of excludeCircularWarningByImporters) {
142 if (warning.importer.startsWith(skipImporter)) {
143 skip = true;
144 break;
145 }
146 }
147 }
148 // NOTE: 2019-01-10 for now skip the plugin warning because of ONGENERATE_HOOK_DEPRECATED on rpt2
149 if (warning.code === 'PLUGIN_WARNING') {
150 skip = true;
151 }
152
153 if (!skip) {
154 console.log(`rollup warning - ${warning.message}`);
155 }
156 };
157 // --------- /Exclude 3rd Party circular Dependencies --------- //
158
159 // set the default rollup output options
160 // make the name from file name "web/js/lib-bundle.js" : "lib_bundle"
161 const name = Path.parse(distFile).name.replace(/\W+/g, "_");
162 const outputOptions: any = {
163 file: distFile,
164 format: 'iife',
165 name,
166 sourcemap: true,
167 sourcemapFile: mapFile
168 };
169
170 // if ts, then, we add the rollup_ts plugin
171 if (opts.ts || opts.tsconfig) {
172 let tsOpts: any = {
173 clean: true
174 };
175 if (opts.tsconfig) {
176 tsOpts.tsconfig = opts.tsconfig;
177 }
178 // Note: if we do not have clean:true, we get some exception when watch.
179 inputOptions.plugins.push(rollup_ts(tsOpts));
180 }
181
182 // if we have some globals, we add them accordingly
183 if (opts.globals) {
184 // for input, just set the external (clone to be safe(r))
185 inputOptions.external = Object.keys(opts.globals);
186 outputOptions.globals = opts.globals;
187 }
188
189 try {
190 // if it is watch mode, we do the watch
191 if (opts.watch) {
192 //wathOptions = { inputOptions };
193 let watchOptions = { ...inputOptions };
194 watchOptions.output = outputOptions;
195 watchOptions.watch = { chokidar: true };
196
197 const watcher = rollup.watch(watchOptions);
198 let startTime: number;
199
200 watcher.on('event', async function (evt) {
201 // console.log('rollup watch', evt.code, evt.output);
202 if (evt.code === 'START') {
203 startTime = now();
204 } else if (evt.code === 'END') {
205 let size = (await fs.stat(distFile)).size;
206 size = Math.round(size / 1000.0);
207 console.log(`Recompile ${distFile} - ${Math.round(now() - startTime)}ms - ${size} kb`);
208 } else if (evt.code === 'ERROR') {
209 console.log(`ERROR - Rollup/Typescript error when processing: ${distFile}`);
210 console.log("\t" + evt.error);
211 }
212
213 });
214
215
216 }
217 // otherwise, we do the full build
218 else {
219 // bundle
220 const bundle = await rollup.rollup(inputOptions);
221
222 // write
223 await bundle.write(outputOptions);
224 }
225
226
227 // make sure the .rpt2_cache/ folder is delete (apparently, clean:true does not work)
228 //await fs.remove("./.rpt2_cache");
229 } catch (ex) {
230 // make sure we write nothing in the file, to know nothing got compiled and fail early
231 await fs.writeFile(distFile, "", "utf8");
232 throw ex;
233 }
234}
235// --------- /For Rollup (JavaScript) --------- //
236
237