build.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #!/usr/bin/env node
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. const fs = require('fs');
  21. const config = require('./config.js');
  22. const commander = require('commander');
  23. const chalk = require('chalk');
  24. const rollup = require('rollup');
  25. const prePublish = require('./pre-publish');
  26. const transformDEV = require('./transform-dev');
  27. async function run() {
  28. /**
  29. * Tips for `commander`:
  30. * (1) If arg xxx not specified, `commander.xxx` is undefined.
  31. * Otherwise:
  32. * If '-x, --xxx', `commander.xxx` can only be true/false, even if '--xxx yyy' input.
  33. * If '-x, --xxx <some>', the 'some' string is required, or otherwise error will be thrown.
  34. * If '-x, --xxx [some]', the 'some' string is optional, that is, `commander.xxx` can be boolean or string.
  35. * (2) `node ./build/build.js --help` will print helper info and exit.
  36. */
  37. let descIndent = ' ';
  38. let egIndent = ' ';
  39. commander
  40. .usage('[options]')
  41. .description([
  42. 'Build echarts and generate result files in directory `echarts/dist`.',
  43. '',
  44. ' For example:',
  45. '',
  46. egIndent + 'node build/build.js --prepublish'
  47. + '\n' + descIndent + '# Only prepublish.',
  48. egIndent + 'node build/build.js --type ""'
  49. + '\n' + descIndent + '# Only generate `dist/echarts.js`.',
  50. egIndent + 'node build/build.js --type common --min'
  51. + '\n' + descIndent + '# Only generate `dist/echarts.common.min.js`.',
  52. egIndent + 'node build/build.js --type simple --min'
  53. + '\n' + descIndent + '# Only generate `dist/echarts-en.simple.min.js`.',
  54. ].join('\n'))
  55. .option(
  56. '--prepublish',
  57. 'Build all for release'
  58. )
  59. .option(
  60. '--min',
  61. 'Whether to compress the output file, and remove error-log-print code.'
  62. )
  63. .option(
  64. '--type <type name>', [
  65. 'Can be "simple" or "common" or "all" (default). Or can be simple,common,all to build multiple. For example,',
  66. descIndent + '`--type ""` or `--type "common"`.'
  67. ].join('\n'))
  68. .option(
  69. '--format <format>',
  70. 'The format of output bundle. Can be "umd", "amd", "iife", "cjs", "esm".'
  71. )
  72. .parse(process.argv);
  73. let isPrePublish = !!commander.prepublish;
  74. let buildType = commander.type || 'all';
  75. let opt = {
  76. min: commander.min,
  77. format: commander.format || 'umd'
  78. };
  79. validateIO(opt.input, opt.output);
  80. if (isPrePublish) {
  81. await prePublish();
  82. }
  83. else if (buildType === 'extension') {
  84. const cfgs = [
  85. config.createBMap(opt),
  86. config.createDataTool(opt)
  87. ];
  88. await build(cfgs);
  89. }
  90. else if (buildType === 'ssr') {
  91. const cfgs = [
  92. config.createSSRClient(opt)
  93. ];
  94. await build(cfgs);
  95. }
  96. else if (buildType === 'myTransform') {
  97. const cfgs = [
  98. config.createMyTransform(opt)
  99. ];
  100. await build(cfgs);
  101. }
  102. else {
  103. const types = buildType.split(',').map(a => a.trim());
  104. // Since 5.5.0, echarts/package.json added `{"type": "module"}`, and added
  105. // echarts/dist/package.json with `{"type": "commonjs"}`, both of which makes
  106. // echarts/dist/echarts.esm.js can not be recognized as esm any more (at least
  107. // in webpack5 and nodejs) any more. So we provides echarts/dist/echarts.esm.mjs.
  108. // But for backward compat, we still provide provides echarts/dist/echarts.esm.js.
  109. const isBuildingDistESM = (opt.format || '').toLowerCase() === 'esm';
  110. if (isBuildingDistESM) {
  111. await makeConfigAndBuild(opt, '.js');
  112. await makeConfigAndBuild(opt, '.mjs');
  113. }
  114. else {
  115. await makeConfigAndBuild(opt);
  116. }
  117. async function makeConfigAndBuild(opt, fileExtension) {
  118. const cfgs = types.map(type =>
  119. config.createECharts({
  120. ...opt,
  121. type,
  122. fileExtension
  123. })
  124. );
  125. await build(cfgs);
  126. }
  127. }
  128. }
  129. function checkBundleCode(cfg) {
  130. // Make sure process.env.NODE_ENV is eliminated.
  131. for (let output of cfg.output) {
  132. let code = fs.readFileSync(output.file, {encoding: 'utf-8'});
  133. if (!code) {
  134. throw new Error(`${output.file} is empty`);
  135. }
  136. transformDEV.recheckDEV(code);
  137. console.log(chalk.green.dim('Check code: correct.'));
  138. }
  139. }
  140. function validateIO(input, output) {
  141. if ((input != null && output == null)
  142. || (input == null && output != null)
  143. ) {
  144. throw new Error('`input` and `output` must be both set.');
  145. }
  146. }
  147. /**
  148. * @param {Array.<Object>} configs A list of rollup configs:
  149. * See: <https://rollupjs.org/#big-list-of-options>
  150. * For example:
  151. * [
  152. * {
  153. * ...inputOptions,
  154. * output: [outputOptions],
  155. * },
  156. * ...
  157. * ]
  158. */
  159. async function build(configs) {
  160. console.log(chalk.yellow(`
  161. NOTICE: If you are using 'npm run build'. Run 'npm run prepare' before build !!!
  162. `));
  163. console.log(chalk.yellow(`
  164. NOTICE: If you are using syslink on zrender. Run 'npm run prepare' in zrender first !!
  165. `));
  166. for (let singleConfig of configs) {
  167. console.log(
  168. chalk.cyan.dim('\Bundling '),
  169. chalk.cyan(singleConfig.input)
  170. );
  171. console.time('rollup build');
  172. const bundle = await rollup.rollup(singleConfig);
  173. for (let output of singleConfig.output) {
  174. console.log(
  175. chalk.green.dim('Created '),
  176. chalk.green(output.file),
  177. chalk.green.dim(' successfully.')
  178. );
  179. await bundle.write(output);
  180. };
  181. console.timeEnd('rollup build');
  182. checkBundleCode(singleConfig);
  183. }
  184. }
  185. async function main() {
  186. try {
  187. await run();
  188. }
  189. catch (err) {
  190. console.log(chalk.red('BUILD ERROR!'));
  191. // rollup parse error.
  192. if (err) {
  193. if (err.loc) {
  194. console.warn(chalk.red(`${err.loc.file} (${err.loc.line}:${err.loc.column})`));
  195. console.warn(chalk.red(err.message));
  196. }
  197. if (err.frame) {
  198. console.warn(chalk.red(err.frame));
  199. }
  200. console.log(chalk.red(err ? err.stack : err));
  201. err.id != null && console.warn(chalk.red(`id: ${err.id}`));
  202. err.hook != null && console.warn(chalk.red(`hook: ${err.hook}`));
  203. err.code != null && console.warn(chalk.red(`code: ${err.code}`));
  204. err.plugin != null && console.warn(chalk.red(`plugin: ${err.plugin}`));
  205. }
  206. // console.log(err);
  207. }
  208. }
  209. main();