UNPKG

@gdjiami/cli

Version:

CLI for build front end project.

392 lines (391 loc) 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); /** * Start development server */ var webpack_dev_server_1 = tslib_1.__importDefault(require("webpack-dev-server")); var webpack_1 = tslib_1.__importDefault(require("webpack")); var express_1 = tslib_1.__importDefault(require("express")); var webpack_dev_middleware_1 = tslib_1.__importDefault(require("webpack-dev-middleware")); var webpack_format_messages_1 = tslib_1.__importDefault(require("webpack-format-messages")); var readline_1 = tslib_1.__importDefault(require("readline")); var child_process_1 = tslib_1.__importDefault(require("child_process")); var chalk_1 = tslib_1.__importDefault(require("chalk")); var https_1 = tslib_1.__importDefault(require("https")); var opener_1 = tslib_1.__importDefault(require("opener")); var tree_kill_1 = tslib_1.__importDefault(require("tree-kill")); var inquirer_1 = tslib_1.__importDefault(require("inquirer")); var utils_1 = require("../utils"); var proxy_1 = require("../proxy"); var info_1 = tslib_1.__importDefault(require("../services/info")); var checkElectron_1 = tslib_1.__importDefault(require("../services/checkElectron")); var options_1 = tslib_1.__importDefault(require("../options")); var config_1 = tslib_1.__importDefault(require("../config")); var cert_1 = require("../cert"); var electron_main_1 = tslib_1.__importDefault(require("../config/electron-main")); var paths_1 = tslib_1.__importDefault(require("../paths")); var Ora = require("ora"); var generateDll_1 = tslib_1.__importDefault(require("./dll/generateDll")); var mode = 'development'; process.env.NODE_ENV = mode; // initial enviroments variables require('../env'); var electronOrBrowserProcess; var lastElectronMainBuildTime; /** * get webpack-dev-server options * @param proxy */ function getDevServerConfig(proxy, webpackConfig, enviroments, options) { // https://github.com/chimurai/http-proxy-middleware // https://webpack.docschina.org/configuration/dev-server/#devserver-proxy // 解析proxy支持变量, 只会解析context和target if (proxy) { // @ts-ignore proxy = proxy_1.interpolateProxy(proxy, enviroments); } return { disableHostCheck: true, compress: true, clientLogLevel: 'none', contentBase: [paths_1.default.appPublic, paths_1.default.appDist, paths_1.default.appCache], watchContentBase: true, hot: !options.ie8, publicPath: webpackConfig.output.publicPath, quiet: true, watchOptions: { ignored: /node_modules/, }, https: process.env.HTTPS === 'true', proxy: proxy, // 使用原生的overlap // TODO: 使用更先进的react-error-overlay overlay: { errors: true, warnings: false, }, }; } /** * create webpack compiler and listen build events * @param config */ function createCompiler(config, electronMainConfig, onCompileSuccess) { var compiler; var started = false; try { // @ts-ignore compiler = webpack_1.default(electronMainConfig ? [electronMainConfig, config] : config); } catch (err) { // config error utils_1.message.error(chalk_1.default.red('Failed to compile.\n')); console.log(err.message || err); console.log(); process.exit(1); } var spinner = Ora(); var firstCompile = true; var startSpin = function () { spinner.text = 'Compiling...'; spinner.start(); }; compiler.hooks.invalid.tap('invalid', function () { if (!firstCompile) { utils_1.clearConsole(); } startSpin(); }); compiler.hooks.done.tap('done', function (stats) { started = true; spinner.stop(); firstCompile = false; var messages = webpack_format_messages_1.default(stats); if (messages.errors.length) { utils_1.message.error('Failed to compile.\n\n'); messages.errors.forEach(function (e) { return console.log(e); }); return; } if (onCompileSuccess) { onCompileSuccess(stats); } if (messages.warnings.length) { utils_1.message.warn('Compiled with warnings.\n\n'); messages.warnings.forEach(function (e) { return console.log(e); }); return; } utils_1.message.success(chalk_1.default.green('Compiled successfully.')); }); return [ compiler, function () { if (started) { return; } startSpin(); }, ]; } function log(str, color, title) { if (/[0-9A-z]+/.test(str)) { utils_1.message.custom(title, str, color); } } var restartingElectron = false; /** * 打开electron 实例 * @param prevProcess */ function openByElectron(argv, prevProcess, onRestart) { var _this = this; if (prevProcess && prevProcess.kill) { try { restartingElectron = true; tree_kill_1.default(prevProcess.pid, 'SIGKILL'); setTimeout(function () { restartingElectron = false; }, 5000); } catch (err) { utils_1.message.error("failed to kill electron process: " + err.message); } } var DefaultPort = 5858; var args = [ argv.electronInspectBrk != null ? "--inspect-brk=" + (argv.electronInspectBrk || DefaultPort) : argv.electronInspect != null ? "--inspect=" + (argv.electronInspect || DefaultPort) : '', '.', ].filter(Boolean); var p = child_process_1.default.spawn(utils_1.requireInCwd('electron'), args); if (prevProcess == null) { utils_1.message.info("calling: 'electron " + args.join(' ') + "'"); } var stdin = readline_1.default.createInterface({ input: p.stdout }); var stderr = readline_1.default.createInterface({ input: p.stderr }); stdin.on('line', function (data) { log(data, 'cyan', 'Electron Log'); }); stderr.on('line', function (data) { log(data, 'red', 'Electron Log'); }); // electron 主进程退出 p.on('close', function (evt) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var res; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!!restartingElectron) return [3 /*break*/, 2]; // 可能是意外退出, 考虑重启electron进程 utils_1.message.info("\u68C0\u6D4B\u5230Electron \u4E3B\u8FDB\u7A0B\u9000\u51FA, \u9000\u51FA\u7801\u4E3A: " + evt); return [4 /*yield*/, inquirer_1.default.prompt([ { type: 'confirm', name: 'restart', message: '是否重启Electron进程?', default: true, }, ])]; case 1: res = _a.sent(); if (res.restart) { if (onRestart) { onRestart(); } } else { process.exit(); } _a.label = 2; case 2: return [2 /*return*/]; } }); }); }); return p; } function startWebpackDevServer(port, host, compiler, devServerConfig, done) { var devServer = new webpack_dev_server_1.default(compiler, devServerConfig); devServer.listen(port, host, function (err) { done(err); }); ['SIGINT', 'SIGTERM'].forEach(function (sig) { process.on(sig, function () { if (electronOrBrowserProcess) { restartingElectron = true; process.kill(electronOrBrowserProcess.pid); } devServer.close(); process.exit(); }); }); } function startIE8DevServer(port, host, compiler, devServerConfig, done) { var app = express_1.default(); var listeningServer; if (devServerConfig.compress) { app.use(require('compression')()); } app.use(require('cors')()); var instance = webpack_dev_middleware_1.default(compiler, { logLevel: 'silent', publicPath: devServerConfig.publicPath || '/' }); app.use(instance); var contentBase = (devServerConfig.contentBase && (Array.isArray(devServerConfig.contentBase) ? devServerConfig.contentBase : typeof devServerConfig.contentBase === 'string' ? [devServerConfig.contentBase] : null)) || [paths_1.default.appDist, paths_1.default.appPublic]; contentBase.forEach(function (p) { app.use(express_1.default.static(p)); }); if (devServerConfig.proxy) { proxy_1.applyProxyToExpress(devServerConfig.proxy, app); } if (devServerConfig.https) { var _a = cert_1.getCerts(), key = _a.key, cert = _a.cert; listeningServer = https_1.default .createServer({ key: key, cert: cert, }, app) .listen(port, host, done); } else { listeningServer = app.listen(port, host, done); } ; ['SIGINT', 'SIGTERM'].forEach(function (sig) { process.on(sig, function () { listeningServer.close(); process.exit(); }); }); } function default_1(argv) { return tslib_1.__awaiter(this, void 0, void 0, function () { var port, protocol, host, urls, environment, pkg, jmOptions, isIE8Mode, isEelectron, _a, electronMainConfig, config, devServerConfig, spinner, contentBase, folders, proxyInfo, _b, compiler, startCompileSpin, serverSetuped; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: return [4 /*yield*/, utils_1.choosePort(parseInt(process.env.PORT, 10) || 8080)]; case 1: port = _c.sent(); protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; host = '0.0.0.0'; urls = utils_1.prepareUrls(protocol, host, port); process.env.PORT = port.toString(); process.env.ADDRESS = urls.lanUrlForConfig || 'localhost'; process.env.PROTOCOL = protocol; environment = require('../env').default(); pkg = require(paths_1.default.appPackageJson); jmOptions = options_1.default(pkg); if (jmOptions == null) { return [2 /*return*/]; } isIE8Mode = jmOptions.ie8; isEelectron = jmOptions.electron; if (isEelectron) { utils_1.message.info(chalk_1.default.cyan('Electron') + ' Mode'); checkElectron_1.default(); } if (!(environment.raw.DISABLE_DLL !== 'true' && !isIE8Mode)) return [3 /*break*/, 5]; utils_1.message.info('Checking DLL...'); _c.label = 2; case 2: _c.trys.push([2, 4, , 5]); return [4 /*yield*/, generateDll_1.default(environment, pkg, paths_1.default, { jmOptions: jmOptions })]; case 3: _c.sent(); return [3 /*break*/, 5]; case 4: _a = _c.sent(); utils_1.message.warn('Failed to compile DLL. skip'); return [3 /*break*/, 5]; case 5: electronMainConfig = isEelectron ? electron_main_1.default(environment, pkg, paths_1.default, { jmOptions: jmOptions }) : undefined; config = config_1.default(environment, pkg, paths_1.default, { entry: argv.entry, jmOptions: jmOptions }); devServerConfig = getDevServerConfig(jmOptions.proxy || {}, config, environment.raw, jmOptions); if (argv.inspect) { // TODO: 优化展示,使用fx,交互式 utils_1.inspect(jmOptions, 'CLI Options:'); utils_1.inspect(environment.raw, 'Environment:'); utils_1.inspect(devServerConfig, 'Development Server Config:'); utils_1.inspect(config, 'Webpack Configuration:'); return [2 /*return*/]; } spinner = Ora({ text: 'Starting the development server...\n' }).start(); contentBase = devServerConfig.contentBase; folders = typeof contentBase === 'string' ? contentBase : Array.isArray(contentBase) ? contentBase.join(', ') : ''; proxyInfo = devServerConfig.proxy && proxy_1.proxyInfomation(devServerConfig.proxy); _b = createCompiler(config, electronMainConfig, function (stats) { utils_1.message.info(info_1.default()); if (jmOptions.ie8) { utils_1.message.info('IE8 Mode'); } utils_1.message.info("Development server running at: \n Lan: " + chalk_1.default.cyan(urls.lanUrlForTerminal) + "\n Local: " + chalk_1.default.cyan(urls.localUrlForTerminal) + " "); utils_1.message.info("Webpack output is served from " + chalk_1.default.cyan('/')); if (folders) { utils_1.message.info("Static resources not from webpack is served from " + chalk_1.default.cyan(folders)); } if (proxyInfo) { utils_1.message.info("Other HTTP requests will proxy to Proxy-Server base on:\n " + chalk_1.default.cyan(proxyInfo)); } if (isEelectron) { utils_1.message.info("Call " + chalk_1.default.cyan('`electron .`') + " to setup development APP"); } try { if (isEelectron) { var compilerStat = stats.stats; // @ts-ignore var mainStat = compilerStat.find(function (i) { return i.compilation.name === 'main'; }); var buildTime = mainStat.startTime; // 失败重启 var restart_1 = function () { utils_1.message.info('restarting Electron'); electronOrBrowserProcess = openByElectron(argv, undefined, restart_1); }; if (electronOrBrowserProcess == null) { utils_1.message.info('open Electron'); electronOrBrowserProcess = openByElectron(argv, undefined, restart_1); } else if (argv.autoReload && lastElectronMainBuildTime !== buildTime) { // electron 主进程更新时重启 utils_1.message.info('restart Electron'); electronOrBrowserProcess = openByElectron(argv, electronOrBrowserProcess, restart_1); } lastElectronMainBuildTime = buildTime; } else if (electronOrBrowserProcess == null) { // 打开浏览器 var entries = Object.keys(config.entry); var entry = entries.some(function (i) { return i === 'index'; }) ? 'index' : entries[0]; electronOrBrowserProcess = opener_1.default(urls.localUrlForBrowser + "/" + entry + ".html"); } } catch (err) { utils_1.message.error(err); } }), compiler = _b[0], startCompileSpin = _b[1]; serverSetuped = function (err) { spinner.stop(); if (err) { utils_1.message.error('Fail to setup development server:'); return; } setTimeout(function () { startCompileSpin(); }, 1000); }; if (isIE8Mode) { startIE8DevServer(port, host, compiler, devServerConfig, serverSetuped); } else { startWebpackDevServer(port, host, compiler, devServerConfig, serverSetuped); } return [2 /*return*/]; } }); }); } exports.default = default_1;