UNPKG

@edenjs/cli

Version:

Web Application Framework built on Express.js and Redis

200 lines (175 loc) 5.64 kB
// resolve path import path from 'path'; /** * Create Javascript Task class * * @task javascript * @priority 10 * @parallel */ export default class JavascriptTask { /** * Construct Javascript Task class * * @param {Loader} runner */ constructor(cli) { // Set private variables this.cli = cli; // Bind public methods this.run = this.run.bind(this); this.watch = this.watch.bind(this); } /** * Run javascript task * * @return {Promise} */ async run(files) { // create imports const imports = Array.from(this.cli.get('bundles', []).map((b) => b.path).reduce((accum, item) => { // add to set accum.add(item.includes('bundles/') ? `${item.split('bundles/')[0]}bundles` : item); // return accum return accum; }, new Set())).map((item) => path.resolve(item)); // set opts const opts = { files, js : Array.from(new Set(this.cli.get('config.frontend.javascript.include') || [])), dest : `${global.appRoot}/www/public/js`, cache : `${global.appRoot}/.edenjs/.cache/browserify.json`, imports : [...imports, ...(this.cli.get('config.import.modules', []).map((mod) => { return `${mod}/node_modules`; })), global.appRoot, `${global.appRoot}/node_modules`, `${global.edenRoot}/node_modules`], browsers : this.cli.get('config.frontend.javascript.browserlist'), sourceMaps : this.cli.get('config.environment') === 'dev', entry : path.resolve(path.dirname(__dirname) + '/public/js/entry'), appRoot : global.appRoot, edenRoot : global.edenRoot, }; // run in thread await this.cli.thread(this.thread, opts); // return loaded return `${files.length.toLocaleString()} javascript entries compiled!`; } /** * threadded run */ async thread(data) { // require const fs = require('fs-extra'); const os = require('os'); const gulp = require('gulp'); const path = require('path'); const glob = require('@edenjs/glob'); const xtend = require('xtend'); const babelify = require('babelify'); const browserify = require('browserify'); const gulpTerser = require('gulp-terser'); const gulpHeader = require('gulp-header'); const vinylSource = require('vinyl-source-stream'); const vinylBuffer = require('vinyl-buffer'); const browserifyinc = require('browserify-incremental'); const gulpSourcemaps = require('gulp-sourcemaps'); // Browserify javascript let b = browserify(xtend(browserifyinc.args, { paths : data.imports, debug : data.sourcemaps, ignore : [...((data.js || []).map((item) => { // check item if (item.indexOf('!') === 0) { // return item return item.substring(1); } }).filter(item => item))], entries : [data.entry, ...await glob(data.files)], commondir : false, extensions : ['.es6', '.es', '.jsx', '.js', '.mjs', '.ts'], insertGlobals : true, })); // browserifyinc browserifyinc(b, { cacheFile : data.cache, }); // check environment b = b.transform(babelify, { presets : [ ['@babel/preset-env', { targets : { browsers : '> 0.25%, not dead', }, }], ], plugins : [ ['@babel/plugin-transform-typescript', { strictMode : false, }], ], sourceMaps : data.sourcemaps, extensions : ['.es6', '.es', '.jsx', '.js', '.mjs', '.ts'], }); // Create browserify bundle const bundle = b.bundle(); // Create job from browserify bundle let job = bundle .pipe(vinylSource('app.min.js')) // Convert to gulp stream .pipe(vinylBuffer()); // Needed for terser, sourcemaps // Init gulpSourcemaps if (data.sourceMaps) { job = job.pipe(gulpSourcemaps.init({ loadMaps : true })); } // Build vendor prepend let head = ''; // run through files for (const file of (data.js || [])) { if (file.indexOf('!') === 0) continue; if (await fs.pathExists(path.join(data.edenRoot, file))) { head += (await fs.readFile(path.join(data.edenRoot, file), 'utf8')) + os.EOL; } else if (await fs.pathExists(path.join(data.appRoot, 'bundles', file))) { // Legacy format head += (await fs.readFile(path.join(data.appRoot, 'bundles', file), 'utf8')) + os.EOL; } else if (await fs.pathExists(path.join(data.appRoot, file))) { head += (await fs.readFile(path.join(data.appRoot, file), 'utf8')) + os.EOL; } else { throw new Error(`JS file missing: ${file}`); } } // Apply head to file job = job.pipe(gulpHeader(head, false)); // Only minify in live if (!data.sourceMaps) { // Pipe uglify job = job.pipe(gulpTerser({ ie8 : false, mangle : true, compress : true, output : { comments : false, }, })); } // Write gulpSourcemaps if (data.sourceMaps) { job = job.pipe(gulpSourcemaps.write('.')); } // Pipe job job = job.pipe(gulp.dest(data.dest)); // Wait for job to end await new Promise((resolve, reject) => { job.once('end', resolve); job.once('error', reject); bundle.once('error', reject); }); } /** * Watch task * * @return {String[]} */ watch () { // Return files return '/public/js/**/bootstrap.{js,jsx,ts,tsx}'; } }