UNPKG

6.72 kBPlain TextView Raw
1import { now, saferRemove } from './utils';
2import * as Path from 'path';
3import * as fs from 'fs-extra-plus';
4
5//////// for Postcss
6const postcss = require("postcss");
7const processors = [
8 require("autoprefixer"),
9 require("postcss-import"),
10 require("postcss-mixins"),
11 require("postcss-nested")
12];
13
14/////// for JS
15import * as rollup from 'rollup';
16import rollup_cjs = require('rollup-plugin-commonjs');
17import rollup_re = require('rollup-plugin-node-resolve');
18import rollup_ts = require('rollup-plugin-typescript2');
19import rollup_multi = require('rollup-plugin-multi-entry');
20
21/////// for handlebars
22import { precompile as hbsPrecompile } from 'hbsp'; // promise style
23
24// --------- For Handlebars --------- //
25export async function tmplFiles(files: string[], distFile: string) {
26
27 await fs.saferRemove([distFile]);
28
29 var templateContent = [];
30
31 for (let file of files) {
32
33 let htmlTemplate = await fs.readFile(file, "utf8");
34 let template = await hbsPrecompile(file, htmlTemplate);
35 templateContent.push(template);
36 }
37
38 await fs.writeFile(distFile, templateContent.join("\n"), "utf8");
39}
40// --------- /For Handlebars --------- //
41
42// --------- For postCss --------- //
43export async function pcssFiles(entries: string[], distFile: string) {
44
45 var mapFile = distFile + ".map";
46 try {
47
48 await fs.saferRemove([distFile, mapFile]);
49
50 var processor = postcss(processors);
51 var pcssNodes = [];
52
53 // we parse all of the .pcss files
54 for (let srcFile of entries) {
55 // read the file
56 let pcss = await fs.readFile(srcFile, "utf8");
57
58 var pcssNode = postcss.parse(pcss, {
59 from: srcFile
60 });
61 pcssNodes.push(pcssNode);
62 }
63
64 // build build the combined rootNode and its result
65 var rootNode = null;
66 for (let pcssNode of pcssNodes) {
67 rootNode = (rootNode) ? rootNode.append(pcssNode) : pcssNode;
68 }
69 var rootNodeResult = rootNode.toResult();
70
71 // we process the rootNodeResult
72 var 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, "utf8");
88}
89// --------- /For postCss --------- //
90
91
92// --------- For Rollup (JavaScript) --------- //
93interface 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}
100var 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 saferRemove("./.rpt2_cache", false);
115
116 // delete the previous ouutput files
117 var 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 saferRemove(distFile, false);
122 }
123 await saferRemove(mapFile, false);
124 } catch (ex) {
125 console.log(`Can't delete dist files`, ex);
126 }
127
128 // set the default rollup input options
129 const inputOptions: any = {
130 input: entries,
131 plugins: [rollup_multi(), rollup_cjs(), rollup_re()]
132 };
133
134 // --------- Exclude 3rd Party circular Dependencies --------- //
135 const excludeCircularWarningByImporters = ['node_modules/d3'];
136 inputOptions.onwarn = function onwarn(warning: any) {
137 let skip = false;
138
139 if (warning.code === 'CIRCULAR_DEPENDENCY') {
140 for (let skipImporter of excludeCircularWarningByImporters) {
141 if (warning.importer.startsWith(skipImporter)) {
142 skip = true;
143 break;
144 }
145 }
146 }
147 // NOTE: 2019-01-10 for now skip the plugin warning because of ONGENERATE_HOOK_DEPRECATED on rpt2
148 if (warning.code === 'PLUGIN_WARNING') {
149 skip = true;
150 }
151
152 if (!skip) {
153 console.log(`rollup warning - ${warning.message}`);
154 }
155 };
156 // --------- /Exclude 3rd Party circular Dependencies --------- //
157
158 // set the default rollup output options
159 // make the name from file name "web/js/lib-bundle.js" : "lib_bundle"
160 var name = Path.parse(distFile).name.replace(/\W+/g, "_");
161 const outputOptions: any = {
162 file: distFile,
163 format: 'iife',
164 name: name,
165 sourcemap: true,
166 sourcemapFile: mapFile
167 };
168
169 // if ts, then, we add the rollup_ts plugin
170 if (opts.ts || opts.tsconfig) {
171 let tsOpts: any = {
172 clean: true
173 };
174 if (opts.tsconfig) {
175 tsOpts.tsconfig = opts.tsconfig;
176 }
177 // Note: if we do not have clean:true, we get some exception when watch.
178 inputOptions.plugins.push(rollup_ts(tsOpts));
179 }
180
181 // if we have some globals, we add them accordingly
182 if (opts.globals) {
183 // for input, just set the external (clone to be safe(r))
184 inputOptions.external = Object.keys(opts.globals);
185 outputOptions.globals = opts.globals;
186 }
187
188 try {
189 // if it is watch mode, we do the watch
190 if (opts.watch) {
191 //wathOptions = { inputOptions };
192 let watchOptions = { ...inputOptions };
193 watchOptions.output = outputOptions;
194 watchOptions.watch = { chokidar: true };
195
196 const watcher = rollup.watch(watchOptions);
197 let startTime: number;
198
199 watcher.on('event', function (evt) {
200 // console.log('rollup watch', evt.code, evt.output);
201 if (evt.code === 'START') {
202 startTime = now();
203 } else if (evt.code === 'END') {
204 console.log(`Recompile ${distFile} done: ${Math.round(now() - startTime)}ms`);
205 } else if (evt.code === 'ERROR') {
206 console.log(`ERROR - Rollup/Typescript error when processing: ${distFile}`);
207 console.log("\t" + evt.error);
208 } else if (evt.code === 'FATAL') {
209 console.log(`FATAL ERROR - Rollup/Typescript fatal error when processing ${distFile}\n
210 >>>>>>>> MUST RESTART WATCH SESSION <<<<<<<<\n\n`, 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