UNPKG

builder-isv

Version:

ISV 模块本地预览与云构建器

302 lines (254 loc) 9.43 kB
var co = require('co'); var fs = require('fs'); var path = require('path'); var gulp = require('gulp'); var gutil = require('gulp-util'); var clean = require('gulp-clean'); var cakeCssTask = require('isv-gulp-cake-css'); var abcOptions = require('./lib/getabc.js'); var webpack = require('webpack'); var Base = require('./models/base'); var uglify = require('gulp-uglify'); var through = require('through2'); var rename = require('gulp-rename'); var copy2 = require('gulp-contrib-copy'); var uglify_parallel = require('isv-uglify-parallel'); var _ = require('lodash'); // var babel = require('gulp-babel'); var util = require('./lib/util'); var rimraf = require('rimraf'); var Debug = require('debug'); var debug = Debug('mod'); var debugMini = Debug('mod:mini'); var debugError = Debug('mod:error'); // 在 shell 中执行一个命令 var exec = require('child_process').exec; var SRC_BASE = abcOptions.SRC_BASE; var BUILD_BASE = abcOptions.BUILD_BASE; var CACHE_DIR = '.cachefile'; var config = require('./config'); var utils = require('./lib/utils'); var rendererFactory = new (require('./models/rendererFactory'))(Base.INVOKE_TYPE_BUILD); config.defOptions = { base: SRC_BASE, verbose: process.env.DEF_LOG_LEVEL === 'verbose' }; process.utils = utils; try { abcOptions.packageJSON = JSON.parse(fs.readFileSync(SRC_BASE + '/package.json')); } catch (e) { utils.log.info("\n**注意:本目录不存在package.json文件,不能使用 builder-mod 进行打包,故略过**\n"); gulp.task('default', function() {}); return; } // 创建缓存文件夹 try { var cacheDir = path.join(SRC_BASE, CACHE_DIR); fs.mkdirSync(cacheDir); debugMini('=====> 创建文件夹成功:' + cacheDir); } catch (e) { if (e.code == 'EEXIST') { debugMini('=====> 文件夹已存在不需要创建'); } else { // 如果不是文件已存在的案例,则直接抛出错误 debugError('=====> 创建文件夹失败:', e); console.log('文件夹:', cacheDir, '创建失败'); return; } } // 是否是新模块打包方式,根据guideName进行判断 var guideName = abcOptions.packageJSON && abcOptions.packageJSON.upx && abcOptions.packageJSON.upx.guideName; var isBaseUpx = !!guideName; abcOptions.isNewModule = isBaseUpx; abcOptions.options.entry = {}; var isWeex = abcOptions.info && abcOptions.info.extraLib === 'weex'; var isVue2 = abcOptions.info && abcOptions.info.extraLib === 'vue2'; var isRax = abcOptions.info && abcOptions.info.extraLib === 'rax'; var customeName = isBaseUpx ? ['upx', abcOptions.group, abcOptions.name].join(';') : abcOptions.name; // 自定义模块名 var suffix = isWeex ? '.we?customeName=' + customeName : '.js'; if (isVue2) { suffix = '.vue?customeName=' + customeName; } abcOptions.options.entry['index'] = SRC_BASE + '/index' + suffix; abcOptions.modBuild = true; //补充配置信息,支持rx、kimi 调试 var info = abcOptions.info; if (!info.project) { abcOptions.info.project = 'mod'; } // 强制删除define 声明中的 deps 的标志位 // info.extraLib 还有可能是 'null',此时一般是pc或者kimi模块 var shouldRemoveDeps = false; if (info.extraLib === 'reactjs') { abcOptions.info.extraLib = 'rx'; shouldRemoveDeps = true; } abcOptions.options.ignore = _.merge({ "@ali/rx": "kg/rx/index", "@ali/rx-components": "kg/rx-components/index", "@ali/pi/mod-base": "kg/pi/mod-base", "@ali/rx-mounter": "kg/rx-mounter/index" }, abcOptions.options.ignore || {}); // 为了解决 weex 模块找不到 babel-runtime 的问题,需要手动指定 alias var WEEX_LOADER_PATH = path.join(__dirname, './node_modules/@ali/cake-webpack-config/node_modules/@ali/weex-mod-loader'); abcOptions.options.resolve = { alias: { 'babel-runtime': path.join(WEEX_LOADER_PATH, './node_modules/babel-runtime') } }; // 打包的时候,需要强制删除缓存文件 // 这样就能强制生成deps.json文件了 function emptyCacheDeps(base) { // 要清理的文件,包含缓存文件、原始的 deps.json 文件 var fileRule = isRax ? [] : [path.join(base, CACHE_DIR, '*.json')]; fileRule.push(path.join(base, 'deps.json')); // 删除缓存文件夹中 版本 文件 return gulp.src(fileRule, {read: false}).pipe(clean()); } /* ---------------------------------------------------- 从 upx 查询有注册过的组件,供动态 external 使用 ----------------------------------------------------- */ gulp.task('get-external', function() { return util.getVersionFromUpx(abcOptions.packageJSON.dependencies).then(function(result) { // 过滤结果,给出提示 _.forOwn(result, function(v, k) { if (typeof v === 'undefined' || v === null) { console.log(' ****** 组件 ' + k + ' 未在 upx 中注册,若引用该组件将打包进最终bundle,请斟酌使用 *****\n'); } }); // console.log('44444', result); abcOptions.componentsInUpx = result; }).catch(function(err) { console.log('尝试从 upx 获取 组件信息失败', err); }); }); gulp.task('clean-cache', function() { return emptyCacheDeps(SRC_BASE); }); gulp.task('clean', ['clean-cache'], function() { return gulp .src(BUILD_BASE, { read: false }) .pipe(clean()); }); gulp.task("webpack", ['clean', 'get-external'], function(callback) { co(function*() { let renderer = yield rendererFactory.getRenderer(null, 'index', path.isAbsolute(SRC_BASE) ? SRC_BASE : path.join(process.cwd(), SRC_BASE), BUILD_BASE); renderer.addListener('compileSucceed', () => { callback(); }); //var compiler = webpack(webpackConfig, function(err, stats) { // if (err) { // throw new gutil.PluginError("webpack", err); // } // //如果编译出错,直接退出进程 // if (stats.hasErrors()) { // gutil.log("[webpack]", stats.toString({ // chunks: false, // colors: true, // children: false // })); // //打印报错信息 // console.log(stats.toJson('errors-only')); // process.exit(1); // } // // gutil.log("[webpack]", stats.toString({ // chunks: false, // colors: true, // children: false // })); // callback(); //}); // //if (compiler.compilers) { // compiler.compilers.forEach(function(compiler) { // // 注入变量 // compiler.plugin('should-emit', function(compilation) { // compiler.shouldRemoveDeps = shouldRemoveDeps; // }); // }); // // compiler.plugin("done", function(stats) { // // vue2.0 deps 尝试读取三端的缓存deps进行合并 // if ( // Options && abcOptions.info && abcOptions.info.extraLib === 'vue2') { // var nativeDeps = util.parseOrFalse(util.readFileOrEmpty(path.join(SRC_BASE, '.cachefile', 'deps.native.json'))); // var webDeps = util.parseOrFalse(util.readFileOrEmpty(path.join(SRC_BASE, '.cachefile', 'deps.web.json'))); // var originDeps = util.parseOrFalse(util.readFileOrEmpty(path.join(SRC_BASE, '.cachefile', 'deps.origin.json'))); // // var finalDeps = _.assign(nativeDeps, webDeps, originDeps); // util.writeFileOrNone(path.join(modPath, 'deps.json'), JSON.stringify(finalDeps)); // } // }); //} else { // // 注入变量 // compiler.plugin('should-emit', function(compilation) { // compiler.shouldRemoveDeps = shouldRemoveDeps; // }); //} }).catch(function(err) { utils.log.error(err.stack); }); var webpackConfigOptions = { entryDir: SRC_BASE, outputDir: BUILD_BASE, abcOptions: abcOptions, callback: function(err, webpackConfig) { } }; }); gulp.task('uglify-parallel', ['webpack'], function() { return new Promise(function(resolve) { uglify_parallel({ pattern: '**/*.js', src: BUILD_BASE, dest: BUILD_BASE, // https://github.com/mishoo/UglifyJS2/issues/490 params: ['--compress', 'pure_getters=true,unused=false', '--beautify', 'beautify=false,ascii-only=true'] }, function() { resolve(); }) }); }); gulp.task('minify-js', ['webpack'], function() { var isSouce = false; // if(abcOptions.options.build){ // isSouce = abcOptions.options.build.minifyJS === false; // } console.log('=== minify-js阶段 ==='); if (process.env.BUILD_DEBUG === 'debug') { // 用户添加 --debug 参数,则不代码压缩等处理 console.log('=== 源代码不进行压缩处理 ==='); isSouce = true; } //todo pure_getters 参数防止 xtpl 生成的代码在 IE8下无法运行 return gulp.src('**/*.js', { cwd: BUILD_BASE, base: BUILD_BASE }).pipe(isSouce && gutil.noop() || uglify({output: {"ascii_only": true}, "pure_getters": true})) .pipe(gulp.dest(BUILD_BASE)); }); gulp.task('copy-js', ['minify-js'], function() { return gulp.src('**/*.js', { cwd: BUILD_BASE, base: BUILD_BASE }) .pipe(copy2()) .pipe(rename({ extname: '-min.js' })) .pipe(gulp.dest(BUILD_BASE)); }); gulp.task('copy-json', ['copy-js'], function() { return gulp .src([SRC_BASE + '/deps.json']) .pipe(copy2()) .pipe(gulp.dest(BUILD_BASE)); }); gulp.task('build-js', ['copy-json']); //css编译任务 cakeCssTask(gulp, abcOptions); gulp.task('default', ['build-js', 'build-css'], function() { return emptyCacheDeps(SRC_BASE); // 清空缓存 });