From 55e5b473d002485d84023b19961f51278e99112d Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 5 Mar 2018 22:07:55 +0530 Subject: [PATCH] Better messages for build commands (#5117) * Better rollup messages in console * Remove 'docs folder not found' warning * Show production message * fix codacy --- frappe/build.py | 3 +- package.json | 8 +- rollup.config.js | 204 ------------------ rollup/build.js | 105 +++++++++ rollup/config.js | 136 ++++++++++++ .../frappe-html-plugin.js | 0 rollup.utils.js => rollup/rollup.utils.js | 30 ++- rollup/watch.js | 57 +++++ yarn.lock | 28 ++- 9 files changed, 358 insertions(+), 213 deletions(-) delete mode 100644 rollup.config.js create mode 100644 rollup/build.js create mode 100644 rollup/config.js rename frappe-html-plugin.js => rollup/frappe-html-plugin.js (100%) rename rollup.utils.js => rollup/rollup.utils.js (76%) create mode 100644 rollup/watch.js diff --git a/frappe/build.py b/frappe/build.py index 55d55af4e1..f156386de8 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -105,7 +105,8 @@ def make_asset_dirs(make_copy=False, restore=False): shutil.rmtree(target) os.symlink(source, target) else: - warnings.warn('Source {source} does not exist.'.format(source = source)) + # warnings.warn('Source {source} does not exist.'.format(source = source)) + pass def build(no_compress=False, verbose=False): assets_path = os.path.join(frappe.local.sites_path, "assets") diff --git a/package.json b/package.json index 3ca2a8a5a5..8f626ccc2c 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "frappe", "scripts": { - "build": "rollup -c --silent", - "production": "FRAPPE_ENV=production rollup -c", - "watch": "rollup -c -w" + "build": "node rollup/build.js", + "production": "FRAPPE_ENV=production node rollup/build.js", + "watch": "node rollup/watch.js" }, "repository": { "type": "git", @@ -19,6 +19,7 @@ "cookie": "^0.3.1", "express": "^4.16.2", "frappe-datatable": "frappe/datatable", + "frappe-gantt": "^0.1.0", "moment": "^2.20.1", "redis": "^2.8.0", "showdown": "^1.8.6", @@ -28,6 +29,7 @@ }, "devDependencies": { "babel-runtime": "^6.26.0", + "chalk": "^2.3.2", "rollup": "^0.55.3", "rollup-plugin-buble": "^0.19.2", "rollup-plugin-commonjs": "^8.3.0", diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index a5e0c46686..0000000000 --- a/rollup.config.js +++ /dev/null @@ -1,204 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const touch = require('touch'); - -const { - get_build_json_path, - get_app_path, - apps_list, - assets_path, - get_public_path, - bench_path, - sites_path -} = require('./rollup.utils'); - -const less = require('rollup-plugin-less'); -const multi_entry = require('rollup-plugin-multi-entry'); -const commonjs = require('rollup-plugin-commonjs'); -const node_resolve = require('rollup-plugin-node-resolve'); -const buble = require('rollup-plugin-buble'); -const uglify = require('rollup-plugin-uglify'); -const frappe_html = require('./frappe-html-plugin'); - -const production = process.env.FRAPPE_ENV === 'production'; - -ensure_js_css_dirs(); -build_libs(); - -function get_app_config(app) { - const build_map = get_build_json(app); - if (!build_map) return []; - - const js_config = Object.keys(build_map) - .filter(output_file => - output_file.endsWith('.js') && - // libs is built separately (to be deprecated) - !output_file.endsWith('libs.min.js') - ) - .map(output_file => { - - const input_files = build_map[output_file].map( - // make paths absolute - input_path => path.resolve(get_app_path(app), input_path) - ); - - return get_js_config(output_file, input_files); - }); - - const less_config = Object.keys(build_map) - .filter(output_file => - output_file.endsWith('.css') - ) - .map(output_file => { - - const input_files = build_map[output_file].map( - input_path => path.resolve(get_app_path(app), input_path) - ); - - return get_css_config(output_file, input_files); - }); - - return [].concat(js_config, less_config); -} - -function get_js_config(output_file, input_files) { - - const css_output_file = path.resolve(assets_path, 'css', path.basename(output_file).split('.js')[0] + '.css'); - - const plugins = [ - // enables array of inputs - multi_entry(), - // .html -> .js - frappe_html(), - // less -> css - less({ - output: css_output_file, - option: { - // so that other .less files can import variables.less from frappe directly - paths: [path.resolve(get_public_path('frappe'), 'less'), path.resolve(get_app_path('frappe'), '..')], - compress: production - }, - // include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')], - exclude: [] - }), - // ES6 -> ES5 - buble({ - objectAssign: 'Object.assign', - transforms: { - dangerousForOf: true - }, - exclude: [path.resolve(bench_path, '**/*.css'), path.resolve(bench_path, '**/*.less')] - }), - commonjs(), - node_resolve(), - production && uglify() - ]; - - return { - input: input_files, - plugins: plugins, - output: { - file: path.resolve(assets_path, output_file), - format: 'iife', - name: 'Rollup', - globals: { - 'jquery': 'window.jQuery' - }, - sourcemap: true - }, - context: 'window', - external: ['jquery'] - }; -} - -function get_css_config(output_file, input_files) { - const output_path = path.resolve(assets_path, output_file); - - // clear css file to avoid appending problem - delete_file(output_path); - - const plugins = [ - // enables array of inputs - multi_entry(), - // less -> css - less({ - output: output_path, - option: { - // so that other .less files can import variables.less from frappe directly - paths: [path.resolve(get_public_path('frappe'), 'less')], - compress: production - }, - include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')] - }) - ]; - - return { - input: input_files, - plugins: plugins, - output: { - // this file is always empty, remove it later? - file: path.resolve(assets_path, `css/rollup.manifest.css`), - format: 'cjs', - } - }; -} - -function ensure_js_css_dirs() { - const paths = [ - path.resolve(assets_path, 'js'), - path.resolve(assets_path, 'css') - ]; - paths.forEach(path => { - if (!fs.existsSync(path)) { - fs.mkdirSync(path); - } - }); - - // clear files in css folder - const css_path = path.resolve(assets_path, 'css'); - const files = fs.readdirSync(css_path); - - files.forEach(file => { - delete_file(path.resolve(css_path, file)); - }); -} - -function build_libs() { - const libs_path = 'js/libs.min.js'; - const input_files = get_build_json('frappe')[libs_path]; - - const libs_content = input_files.map(file_name => { - const full_path = path.resolve(get_app_path('frappe'), file_name); - return `/* ${file_name} */\n` + fs.readFileSync(full_path); - }).join('\n\n'); - - const target_path = path.resolve(assets_path, libs_path); - fs.writeFileSync(target_path, libs_content); - console.log('✨ Built libs.min.js'); // eslint-disable-line - touch(path.join(sites_path, '.build'), { force: true }); -} - -function get_all_apps_config() { - let configs = []; - apps_list.forEach(app => { - configs = configs.concat(get_app_config(app)); - }); - return configs; -} - -function get_build_json(app) { - try { - return require(get_build_json_path(app)); - } catch (e) { - // build.json does not exist - return null; - } -} - -function delete_file(path) { - if (fs.existsSync(path)) { - fs.unlinkSync(path); - } -} - -module.exports = get_all_apps_config(); \ No newline at end of file diff --git a/rollup/build.js b/rollup/build.js new file mode 100644 index 0000000000..0a564a55b9 --- /dev/null +++ b/rollup/build.js @@ -0,0 +1,105 @@ +const fs = require('fs'); +const path = require('path'); +const chalk = require('chalk'); +const rollup = require('rollup'); +const log = console.log; // eslint-disable-line + +const { + get_build_json, + get_app_path, + apps_list, + run_serially, + assets_path, + sites_path, + delete_file +} = require('./rollup.utils'); + +const { + get_rollup_options +} = require('./config'); + +show_production_message(); +ensure_js_css_dirs(); +build_libs(); +build_assets_for_all_apps(); + +function build_assets_for_all_apps() { + run_serially( + apps_list.map(app => () => build_assets(app)) + ); +} + +function build_assets(app) { + const build_json = get_build_json(app); + if (!build_json) return Promise.resolve(); + log(chalk.yellow(`\nBuilding ${app} assets...\n`)); + + const promises = Object.keys(build_json) + .map(output_file => { + const input_files = build_json[output_file] + .map(input_file => path.resolve(get_app_path(app), input_file)); + const { inputOptions, outputOptions } = get_rollup_options(output_file, input_files); + + return build(inputOptions, outputOptions) + .then(() => { + log(`${chalk.green('✔')} Built ${output_file}`); + }); + }); + + const start = Date.now(); + return Promise.all(promises) + .then(() => { + const time = Date.now() - start; + log(chalk.green(`✨ Done in ${time / 1000}s`)); + }); +} + +function build(inputOptions, outputOptions) { + return rollup.rollup(inputOptions) + .then(bundle => bundle.write(outputOptions)); +} + +function build_libs() { + // only concatenates lib files, not processed through rollup + + const touch = require('touch'); + const libs_path = 'js/libs.min.js'; + const input_files = get_build_json('frappe')[libs_path]; + + const libs_content = input_files.map(file_name => { + const full_path = path.resolve(get_app_path('frappe'), file_name); + return `/* ${file_name} */\n` + fs.readFileSync(full_path); + }).join('\n\n'); + + const target_path = path.resolve(assets_path, libs_path); + fs.writeFileSync(target_path, libs_content); + log(`${chalk.green('✔')} Built ${libs_path}`); + touch(path.join(sites_path, '.build'), { force: true }); +} + +function ensure_js_css_dirs() { + const paths = [ + path.resolve(assets_path, 'js'), + path.resolve(assets_path, 'css') + ]; + paths.forEach(path => { + if (!fs.existsSync(path)) { + fs.mkdirSync(path); + } + }); + + // clear files in css folder + const css_path = path.resolve(assets_path, 'css'); + const files = fs.readdirSync(css_path); + + files.forEach(file => { + delete_file(path.resolve(css_path, file)); + }); +} + +function show_production_message() { + const production = process.env.FRAPPE_ENV === 'production'; + if (production) { + log(chalk.green('Production mode')); + } +} \ No newline at end of file diff --git a/rollup/config.js b/rollup/config.js new file mode 100644 index 0000000000..a46ce130de --- /dev/null +++ b/rollup/config.js @@ -0,0 +1,136 @@ +const path = require('path'); +const chalk = require('chalk'); +const log = console.log; // eslint-disable-line + +const multi_entry = require('rollup-plugin-multi-entry'); +const commonjs = require('rollup-plugin-commonjs'); +const node_resolve = require('rollup-plugin-node-resolve'); +const less = require('rollup-plugin-less'); +const buble = require('rollup-plugin-buble'); +const uglify = require('rollup-plugin-uglify'); +const frappe_html = require('./frappe-html-plugin'); + +const production = process.env.FRAPPE_ENV === 'production'; + +const { + assets_path, + bench_path, + get_public_path, + get_app_path, + delete_file, +} = require('./rollup.utils'); + +function get_rollup_options(output_file, input_files) { + if (output_file.endsWith('.js')) { + return get_rollup_options_for_js(output_file, input_files); + } else if(output_file.endsWith('.css')) { + return get_rollup_options_for_css(output_file, input_files); + } +} + +function get_rollup_options_for_js(output_file, input_files) { + const css_output_file = path.resolve(assets_path, 'css', path.basename(output_file).split('.js')[0] + '.css'); + + const plugins = [ + // enables array of inputs + multi_entry(), + // .html -> .js + frappe_html(), + // less -> css + less({ + output: css_output_file, + option: { + // so that other .less files can import variables.less from frappe directly + paths: [path.resolve(get_public_path('frappe'), 'less'), path.resolve(get_app_path('frappe'), '..')], + compress: production + }, + include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')], + exclude: [] + }), + // ES6 -> ES5 + buble({ + objectAssign: 'Object.assign', + transforms: { + dangerousForOf: true + }, + exclude: [path.resolve(bench_path, '**/*.css'), path.resolve(bench_path, '**/*.less')] + }), + commonjs(), + node_resolve(), + production && uglify() + ]; + + return { + inputOptions: { + input: input_files, + plugins: plugins, + context: 'window', + external: ['jquery'], + onwarn({ code, message, loc, frame }) { + // skip warnings + if (['EVAL', 'SOURCEMAP_BROKEN', 'NAMESPACE_CONFLICT'].includes(code)) return; + + if (loc) { + log(`${loc.file} (${loc.line}:${loc.column}) ${message}`); + if (frame) log(frame); + } else { + log(chalk.yellow.underline(code), ':', message); + } + } + }, + outputOptions: { + file: path.resolve(assets_path, output_file), + format: 'iife', + name: 'Rollup', + globals: { + 'jquery': 'window.jQuery' + }, + sourcemap: true + } + }; +} + +function get_rollup_options_for_css(output_file, input_files) { + const output_path = path.resolve(assets_path, output_file); + + // clear css file to avoid appending problem + delete_file(output_path); + + const plugins = [ + // enables array of inputs + multi_entry(), + // less -> css + less({ + output: output_path, + option: { + // so that other .less files can import variables.less from frappe directly + paths: [path.resolve(get_public_path('frappe'), 'less')], + compress: production + }, + include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')] + }) + ]; + + return { + inputOptions: { + input: input_files, + plugins: plugins, + onwarn(warning) { + // skip warnings + if (['EMPTY_BUNDLE'].includes(warning.code)) return; + + // console.warn everything else + log(chalk.yellow.underline(warning.code), ':', warning.message); + } + }, + outputOptions: { + // this file is always empty, remove it later? + file: path.resolve(assets_path, `css/rollup.manifest.css`), + format: 'cjs' + } + }; +} + +module.exports = { + get_rollup_options +}; diff --git a/frappe-html-plugin.js b/rollup/frappe-html-plugin.js similarity index 100% rename from frappe-html-plugin.js rename to rollup/frappe-html-plugin.js diff --git a/rollup.utils.js b/rollup/rollup.utils.js similarity index 76% rename from rollup.utils.js rename to rollup/rollup.utils.js index e634693199..608d6a5e4d 100644 --- a/rollup.utils.js +++ b/rollup/rollup.utils.js @@ -42,6 +42,31 @@ const get_public_path = app => public_paths[app]; const get_build_json_path = app => path.resolve(get_public_path(app), 'build.json'); +function get_build_json(app) { + try { + return require(get_build_json_path(app)); + } catch (e) { + // build.json does not exist + return null; + } +} + +function delete_file(path) { + if (fs.existsSync(path)) { + fs.unlinkSync(path); + } +} + +function run_serially(tasks) { + let result = Promise.resolve(); + tasks.forEach(task => { + if(task) { + result = result.then ? result.then(task) : Promise.resolve(); + } + }); + return result; +} + const get_app_path = app => app_paths[app]; module.exports = { @@ -49,8 +74,11 @@ module.exports = { bundle_map, get_public_path, get_build_json_path, + get_build_json, get_app_path, apps_list, assets_path, - bench_path + bench_path, + delete_file, + run_serially }; diff --git a/rollup/watch.js b/rollup/watch.js new file mode 100644 index 0000000000..6bdfed7f64 --- /dev/null +++ b/rollup/watch.js @@ -0,0 +1,57 @@ +const path = require('path'); +const chalk = require('chalk'); +const rollup = require('rollup'); +const log = console.log; // eslint-disable-line +const { + apps_list, + get_app_path, + get_build_json +} = require('./rollup.utils'); + +const { + get_rollup_options +} = require('./config'); + +watch_assets(); + +function watch_assets() { + let watchOptions = []; + apps_list.map(app => { + watchOptions.push(...get_watch_options(app)); + }); + log(chalk.green(`\nRollup Watcher Started`)); + let watcher = rollup.watch(watchOptions); + + watcher.on('event', event => { + switch(event.code) { + case 'START': + log(chalk.yellow(`\nWatching...`)); + break; + + case 'BUNDLE_START': + log('Rebuilding', path.basename(event.output[0])); + break; + + default: + break; + } + }); +} + +function get_watch_options(app) { + const build_json = get_build_json(app); + if (!build_json) return []; + + const watchOptions = Object.keys(build_json) + .map(output_file => { + const input_files = build_json[output_file] + .map(input_file => path.resolve(get_app_path(app), input_file)); + const { inputOptions, outputOptions } = get_rollup_options(output_file, input_files); + + return Object.assign({}, inputOptions, { + output: outputOptions + }); + }).filter(Boolean); + + return watchOptions; +} diff --git a/yarn.lock b/yarn.lock index cf73ac5dd6..e3bab09d37 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,6 +54,12 @@ ansi-styles@^3.2.0: dependencies: color-convert "^1.9.0" +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -232,6 +238,14 @@ chalk@^2.3.1: escape-string-regexp "^1.0.5" supports-color "^5.2.0" +chalk@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + cliui@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" @@ -617,6 +631,10 @@ frappe-datatable@frappe/datatable: clusterize.js "^0.18.0" sortablejs "^1.7.0" +frappe-gantt@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/frappe-gantt/-/frappe-gantt-0.1.0.tgz#0532d7f10bc4c905ad7dd1ef8e65c7457d13355f" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -986,10 +1004,6 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash@^4.17.5: - version "4.17.5" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" - lru-cache@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -1700,6 +1714,12 @@ supports-color@^5.2.0: dependencies: has-flag "^3.0.0" +supports-color@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" + dependencies: + has-flag "^3.0.0" + to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"