提交 9e06beba 编写于 作者: S sushuang

Move build helper to zr.

上级 3e721e12
const assert = require('assert');
function plugin({types, template}, options) {
return {
visitor: {
IfStatement: {
exit(path) {
removeDEV(path);
}
}
}
};
}
plugin.recheckDEV = function (code) {
const index = code.indexOf('__DEV__');
assert(index < 0, `Still has __DEV__, position: ${index}`);
};
module.exports = plugin;
function removeDEV(path) {
if (path.node.test.name === '__DEV__') {
path.remove();
}
}
......@@ -5,9 +5,10 @@ const fs = require('fs');
const {resolve} = require('path');
const config = require('./config.js');
const commander = require('commander');
const {build, watch, color} = require('./helper');
const {build, watch, color} = require('zrender/build/helper');
const ecLangPlugin = require('./rollup-plugin-ec-lang');
const prePublish = require('./pre-publish');
const recheckDEV = require('zrender/build/babel-plugin-transform-remove-dev').recheckDEV;
function run() {
......@@ -35,6 +36,8 @@ function run() {
+ '\n' + descIndent + '# Build all to `dist` folder.',
egIndent + 'node build/build.js --prepublish'
+ '\n' + descIndent + '# Only prepublish.',
egIndent + 'node build/build.js --removedev'
+ '\n' + descIndent + '# Remove __DEV__ code. If --min, __DEV__ always be removed.',
egIndent + 'node build/build.js --type ""'
+ '\n' + descIndent + '# Only generate `dist/echarts.js`.',
egIndent + 'node build/build.js --type common --min'
......@@ -65,6 +68,10 @@ function run() {
'--prepublish',
'Build all for release'
)
.option(
'--removedev',
'Remove __DEV__ code. If --min, __DEV__ always be removed.'
)
.option(
'--min',
'Whether to compress the output file, and remove error-log-print code.'
......@@ -97,19 +104,22 @@ function run() {
let isPrePublish = !!commander.prepublish;
let opt = {
lang: commander.lang || null,
lang: commander.lang,
min: commander.min,
type: commander.type || '',
input: commander.input,
output: commander.output,
format: commander.format,
sourcemap: commander.sourcemap,
format: commander.format || 'umd',
removeDev: commander.removedev,
addBundleVersion: isWatch
};
validateIO(opt.input, opt.output);
validateLang(opt.lang, opt.output);
normalizeParams(opt);
// Clear `echarts/dist`
if (isRelease) {
fsExtra.removeSync(getPath('./dist'));
......@@ -131,8 +141,10 @@ function run() {
{min: false, lang: 'en'},
{min: true, lang: 'en'}
].forEach(function (opt) {
['', 'simple', 'common'].forEach(function (type) {
let singleOpt = Object.assign({type}, opt);
normalizeParams(singleOpt);
let singleConfig = config.createECharts(singleOpt);
configs.push(singleConfig);
......@@ -156,7 +168,23 @@ function run() {
}).catch(handleBuildError);
}
else {
build([config.createECharts(opt)]).catch(handleBuildError);
let cfg = config.createECharts(opt);
build([cfg])
.then(function () {
if (opt.removeDev) {
checkCode(cfg);
}
})
.catch(handleBuildError);
}
}
function normalizeParams(opt) {
if (opt.sourcemap == null) {
opt.sourcemap = !(opt.min || opt.type);
}
if (opt.removeDev == null) {
opt.removeDev = !!opt.min;
}
}
......@@ -170,9 +198,7 @@ function checkCode(singleConfig) {
if (!code) {
throw new Error(`${singleConfig.output.file} is empty`);
}
if (code.indexOf('__DEV__') >= 0) {
throw new Error('__DEV__ is not removed.');
}
recheckDEV(code);
console.log(color('fgGreen', 'dim')('Check code: correct.'));
}
......
/* global process */
const nodeResolvePlugin = require('rollup-plugin-node-resolve');
const uglifyPlugin = require('rollup-plugin-uglify');
const ecDevPlugin = require('./rollup-plugin-ec-dev');
const ecRemoveDevPlugin = require('./rollup-plugin-ec-remove-dev');
const ecLangPlugin = require('./rollup-plugin-ec-lang');
const {resolve} = require('path');
......@@ -9,14 +8,13 @@ function getPathBasedOnECharts(path) {
return resolve(__dirname, '../', path);
}
/**
* @param {boolean} [min=false]
* @param {string} [lang=null] null/undefined/'' or 'en' or 'fi' or a file path
* @param {boolean} [addBundleVersion=false]
*/
function getPlugins(min, lang, addBundleVersion) {
function getPlugins({min, lang, sourcemap, removeDev, addBundleVersion}) {
let plugins = [];
removeDev && plugins.push(
ecRemoveDevPlugin({sourcemap})
);
lang && plugins.push(
ecLangPlugin({lang})
);
......@@ -37,9 +35,9 @@ function getPlugins(min, lang, addBundleVersion) {
// Currently, in uglify:
// `var vx; if(vx) {...}` can not be removed.
// `if (__DEV__) {...}` can be removed if `__DEV__` is defined as `false` in `global_defs`.
'global_defs': {
__DEV__: false
},
// 'global_defs': {
// __DEV__: false
// },
'dead_code': true
}
}));
......@@ -55,23 +53,21 @@ function getPlugins(min, lang, addBundleVersion) {
* @param {string} [opt.input=undefined] If set, `opt.output` is required too, and `opt.type` is ignored.
* @param {string} [opt.output=undefined] If set, `opt.input` is required too, and `opt.type` is ignored.
* @param {boolean} [opt.sourcemap] If set, `opt.input` is required too, and `opt.type` is ignored.
* @param {boolean} [opt.removeDev]
* @param {string} [opt.format='umd'] If set, `opt.input` is required too, and `opt.type` is ignored.
* @param {boolean} [opt.addBundleVersion=false] Only for debug in watch, prompt that the two build is different.
*/
exports.createECharts = function (opt) {
opt = opt || {};
exports.createECharts = function (opt = {}) {
let srcType = opt.type ? '.' + opt.type : '.all';
let postfixType = opt.type ? '.' + opt.type : '';
let postfixMin = opt.min ? '.min' : '';
let postfixLang = opt.lang ? '-' + opt.lang.toLowerCase() : '';
let isCustom;
let input = opt.input;
let output = opt.output;
let sourcemap = opt.sourcemap;
let format = opt.format || 'umd';
if (input != null || output != null) {
isCustom = true;
// Based on process.cwd();
input = resolve(input);
output = resolve(output);
......@@ -79,13 +75,10 @@ exports.createECharts = function (opt) {
else {
input = getPathBasedOnECharts(`./echarts${srcType}.js`);
output = getPathBasedOnECharts(`dist/echarts${postfixLang}${postfixType}${postfixMin}.js`);
if (sourcemap == null) {
sourcemap = !opt.min && !opt.type;
}
}
return {
plugins: getPlugins(opt.min, opt.lang, opt.addBundleVersion),
plugins: getPlugins(opt),
input: input,
legacy: true, // Support IE8-
output: {
......@@ -112,7 +105,7 @@ exports.createBMap = function (min) {
let postfix = min ? '.min' : '';
return {
plugins: getPlugins(min),
plugins: getPlugins({min}),
input: getPathBasedOnECharts(`./extension-src/bmap/bmap.js`),
legacy: true, // Support IE8-
external: ['echarts'],
......@@ -139,7 +132,7 @@ exports.createBMap = function (min) {
exports.createDataTool = function (min) {
let postfix = min ? '.min' : '';
return {
plugins: getPlugins(min),
plugins: getPlugins({min}),
input: getPathBasedOnECharts(`./extension-src/dataTool/index.js`),
legacy: true, // Support IE8-
external: ['echarts'],
......
let path = require('path');
let babel = require('@babel/core');
let fs = require('fs');
let transformPluginPath = path.resolve(__dirname, './babel-plugin-transform-modules-commonjs-ec');
// let transformPluginPath = '@babel/plugin-transform-modules-commonjs';
// let fileName = path.resolve(__dirname, '../src/ExtensionAPI.js');
// let fileName = path.resolve(__dirname, '../src/util/graphic.js');
// let fileName = path.resolve(__dirname, '../index.blank.js');
// let fileName = path.resolve(__dirname, '../src/chart/bar/BarSeries.js');
// let fileName = path.resolve(__dirname, '../test/esm2cjs/a.js');
let fileName = path.resolve(__dirname, '../test/esm2cjs/a.js');
let result = babel.transformFileSync(fileName, {
plugins: [
[transformPluginPath, {
// strict: true
loose: true
}]
]
});
let outputFile = path.resolve(__dirname, '../../tmp/babel.output.js');
// console.log(outputFile);
fs.writeFileSync(outputFile, result.code, {encoding:'utf-8'});
const rollup = require('rollup');
/**
* @param {Array.<Object>} configs A list of rollup configs:
* See: <https://rollupjs.org/#big-list-of-options>
* For example:
* [
* {
* ...inputOptions,
* output: [outputOptions],
* watch: {chokidar, include, exclude}
* },
* ...
* ]
* @return {Promise}
*/
exports.build = function (configs) {
return new Promise(function (promiseResolve, promiseReject) {
let index = 0;
buildSingle();
function buildSingle() {
let singleConfig = configs[index++];
if (!singleConfig) {
promiseResolve();
return;
}
console.log(
color('fgCyan', 'dim')('\nBundles '),
color('fgCyan')(singleConfig.input),
color('fgCyan', 'dim')('=>'),
color('fgCyan')(singleConfig.output.file),
color('fgCyan', 'dim')(' ...')
);
rollup
.rollup(singleConfig)
.then(function (bundle) {
return bundle.write(singleConfig.output);
})
.then(function () {
console.log(
color('fgGreen', 'dim')('Created '),
color('fgGreen')(singleConfig.output.file),
color('fgGreen', 'dim')(' successfully.')
);
buildSingle();
})
.catch(function (err) {
console.log(color('fgRed')(err));
promiseReject();
});
}
});
};
/**
* @param {Object} singleConfig A single rollup config:
* See: <https://rollupjs.org/#big-list-of-options>
* For example:
* {
* ...inputOptions,
* output: [outputOptions],
* watch: {chokidar, include, exclude}
* }
*/
exports.watch = function (singleConfig) {
let watcher = rollup.watch(singleConfig);
watcher.on('event', function (event) {
// event.code can be one of:
// START — the watcher is (re)starting
// BUNDLE_START — building an individual bundle
// BUNDLE_END — finished building a bundle
// END — finished building all bundles
// ERROR — encountered an error while bundling
// FATAL — encountered an unrecoverable error
if (event.code !== 'START' && event.code !== 'END') {
console.log(
color('fgBlue')('[' + getTimeString() + ']'),
color('dim')('build'),
event.code.replace(/_/g, ' ').toLowerCase()
);
}
if (event.code === 'ERROR' || event.code === 'FATAL') {
printCodeError(event.error);
}
if (event.code === 'BUNDLE_END') {
printWatchResult(event);
}
});
};
function printWatchResult(event) {
console.log(
color('fgGreen', 'dim')('Created'),
color('fgGreen')(event.output.join(', ')),
color('fgGreen', 'dim')('in'),
color('fgGreen')(event.duration),
color('fgGreen', 'dim')('ms.')
);
}
function printCodeError(error) {
console.log('\n' + color()(error.code));
if (error.code === 'PARSE_ERROR') {
console.log(
color()('line'),
color('fgCyan')(error.loc.line),
color()('column'),
color('fgCyan')(error.loc.column),
color()('in'),
color('fgCyan')(error.loc.file)
);
}
if (error.frame) {
console.log('\n' + color('fgRed')(error.frame));
}
console.log(color('dim')('\n' + error.stack));
}
function getTimeString() {
return (new Date()).toLocaleString();
}
const COLOR_RESET = '\x1b[0m';
const COLOR_MAP = {
bright: '\x1b[1m',
dim: '\x1b[2m',
underscore: '\x1b[4m',
blink: '\x1b[5m',
reverse: '\x1b[7m',
hidden: '\x1b[8m',
fgBlack: '\x1b[30m',
fgRed: '\x1b[31m',
fgGreen: '\x1b[32m',
fgYellow: '\x1b[33m',
fgBlue: '\x1b[34m',
fgMagenta: '\x1b[35m',
fgCyan: '\x1b[36m',
fgWhite: '\x1b[37m',
bgBlack: '\x1b[40m',
bgRed: '\x1b[41m',
bgGreen: '\x1b[42m',
bgYellow: '\x1b[43m',
bgBlue: '\x1b[44m',
bgMagenta: '\x1b[45m',
bgCyan: '\x1b[46m',
bgWhite: '\x1b[47m'
};
/**
* Print colored text with `console.log`.
*
* Usage:
* let color = require('colorConsole');
* color('fgCyan')('some text'); // cyan text.
* color('fgCyan', 'bright')('some text'); // bright cyan text.
* color('fgCyan', 'bgRed')('some text') // cyan text and red background.
*/
let color = exports.color = function () {
let prefix = [];
for (let i = 0; i < arguments.length; i++) {
let color = COLOR_MAP[arguments[i]];
color && prefix.push(color);
}
prefix = prefix.join('');
return function (text) {
return prefix + text + COLOR_RESET;
};
};
......@@ -5,58 +5,44 @@
* (3) Mount `echarts/src/export.js` to `echarts/lib/echarts.js`.
*/
const {resolve, join} = require('path');
const path = require('path');
const fsExtra = require('fs-extra');
const fs = require('fs');
const babel = require('@babel/core');
const esm2cjsPlugin = require('./babel-plugin-transform-modules-commonjs-ec');
const removeDEVPlugin = require('./babel-plugin-transform-remove-dev');
const {color} = require('./helper');
const {color, travelSrcDir, prePulishSrc} = require('zrender/build/helper');
const ecDir = resolve(__dirname, '..');
const srcDir = resolve(__dirname, '../src');
const extensionSrcDir = resolve(__dirname, '../extension-src');
const extensionDir = resolve(__dirname, '../extension');
const libDir = resolve(__dirname, '../lib');
const REG_SRC = /^[^.].*[.]js$/;
const REG_DIR = /^[^.].*$/;
const ecDir = path.resolve(__dirname, '..');
const srcDir = path.resolve(__dirname, '../src');
const extensionSrcDir = path.resolve(__dirname, '../extension-src');
const extensionDir = path.resolve(__dirname, '../extension');
const libDir = path.resolve(__dirname, '../lib');
module.exports = function () {
fsExtra.removeSync(libDir);
fsExtra.ensureDirSync(libDir);
// fsExtra.copySync(getPath('./src'), getPath('./lib'));
travelDir(srcDir, '.', ({fileName, basePath, absolutePath}) => {
transform(absolutePath, resolve(libDir, basePath, fileName));
});
travelDir(extensionSrcDir, '.', ({fileName, basePath, absolutePath}) => {
transform(absolutePath, resolve(extensionDir, basePath, fileName));
travelSrcDir(srcDir, ({fileName, relativePath, absolutePath}) => {
prePulishSrc({
inputPath: absolutePath,
outputPath: path.resolve(libDir, relativePath, fileName),
transform
});
});
// transform(resolve(ecDir, 'echarts.all.js'), resolve(ecDir, 'index.js'));
// transform(resolve(ecDir, 'echarts.common.js'), resolve(ecDir, 'index.common.js'));
// transform(resolve(ecDir, 'echarts.simple.js'), resolve(ecDir, 'index.simple.js'));
function transform(inputPath, outputPath) {
console.log(
color('fgGreen', 'dim')('[transform] '),
color('fgGreen')(inputPath),
color('fgGreen', 'dim')('...')
);
let {code} = babel.transformFileSync(inputPath, {
plugins: [removeDEVPlugin, esm2cjsPlugin]
travelSrcDir(extensionSrcDir, ({fileName, relativePath, absolutePath}) => {
prePulishSrc({
inputPath: absolutePath,
outputPath: path.resolve(extensionDir, relativePath, fileName),
transform
});
});
if (inputPath !== resolve(ecDir, 'src/config.js')) {
removeDEVPlugin.recheckDEV(code);
}
// prePulishSrc(path.resolve(ecDir, 'echarts.all.js'), path.resolve(ecDir, 'index.js'));
// prePulishSrc(path.resolve(ecDir, 'echarts.common.js'), path.resolve(ecDir, 'index.common.js'));
// prePulishSrc(path.resolve(ecDir, 'echarts.simple.js'), path.resolve(ecDir, 'index.simple.js'));
if (inputPath === resolve(ecDir, 'src/echarts.js')) {
function transform({code, inputPath, outputPath}) {
if (inputPath === path.resolve(ecDir, 'src/echarts.js')) {
// Using `echarts/echarts.blank.js` to overwrite `echarts/lib/echarts.js`
// for including exports API.
code +=
......@@ -70,35 +56,8 @@ module.exports = function () {
})();`;
}
code = esm2cjsPlugin.replaceInject(code);
fsExtra.ensureFileSync(outputPath);
fs.writeFileSync(outputPath, code, {encoding:'utf-8'});
return code;
}
console.log(color('fgGreen', 'bright')('All done.'));
};
function travelDir(tSrcDir, basePath, cb) {
travelSrcDir(basePath);
function travelSrcDir(basePath) {
const absolutePath = resolve(tSrcDir, basePath);
fs.readdirSync(absolutePath).forEach(fileName => {
const childAbsolutePath = resolve(absolutePath, fileName);
const stat = fs.statSync(childAbsolutePath);
if (stat.isDirectory()) {
if (REG_DIR.test(fileName)) {
travelSrcDir(join(basePath, fileName));
}
}
else if (stat.isFile()) {
if (REG_SRC.test(fileName)) {
cb({fileName, basePath: basePath, absolutePath: childAbsolutePath});
}
}
});
}
}
/**
* Remove the code of `if (__DEV__) { ... }`.
*
* Usage:
*
* import ecRemoveDevPlugin from 'echats/build/rollup-plugin-ec-remove-dev';
* let rollupConfig = {
* plugins: [
* ecRemoveDevPlugin(),
* ...
* ]
* };
*/
const babel = require('@babel/core');
const removeDEVPlugin = require('zrender/build/babel-plugin-transform-remove-dev');
/**
* @param {Object} [opt]
* @param {Object} [opt.sourcemap]
*/
module.exports = function ({sourcemap} = {}) {
return {
transform: function (sourceCode) {
let {code, map} = babel.transform(sourceCode, {
plugins: [removeDEVPlugin],
sourceMaps: sourcemap
});
return {code, map};
}
};
};
// See `echarts/build/rollup-plugin-ec-dev`.
// Enable DEV mode when using source code without build. which has no __DEV__ variable
// In build process 'typeof __DEV__' will be replace with 'boolean'
// So this code will be removed or disabled anyway after built.
// if (typeof __DEV__ === 'undefined') {
// // In browser
// if (typeof window !== 'undefined') {
// window.__DEV__ = true;
// }
// // In node
// else if (typeof global !== 'undefined') {
// global.__DEV__ = true;
// }
// }
// (1) The code `if (__DEV__) ...` can be removed by build tool.
// (2) If intend to use `__DEV__`, this module should be imported. Use a global
// variable `__DEV__` may cause that miss the declaration (see #6535), or the
// declaration is behind of the using position (for example in `Model.extent`,
// And tools like rollup can not analysis the dependency if not import).
export var __DEV__ = true;
var __DEV__;
// In browser
if (typeof window !== 'undefined') {
__DEV__ = window.__DEV__;
}
// In node
else if (typeof global !== 'undefined') {
__DEV__ = global.__DEV__;
}
if (typeof __DEV__ === 'undefined') {
__DEV__ = true;
}
export {__DEV__};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册