viewer.js 3.84 KB
'use strict';

var path = require('path');
var fs = require('fs');

var _ = require('lodash');
var express = require('express');
var ejs = require('ejs');
var opener = require('opener');
var mkdir = require('mkdirp');

var _require = require('chalk'),
    bold = _require.bold;

var Logger = require('./Logger');
var analyzer = require('./analyzer');

var projectRoot = path.resolve(__dirname, '..');

module.exports = {
  startServer: startServer,
  generateReport: generateReport,
  // deprecated
  start: startServer
};

function startServer(bundleStats, opts) {
  var _ref = opts || {},
      _ref$port = _ref.port,
      port = _ref$port === undefined ? 8888 : _ref$port,
      _ref$host = _ref.host,
      host = _ref$host === undefined ? '127.0.0.1' : _ref$host,
      _ref$openBrowser = _ref.openBrowser,
      openBrowser = _ref$openBrowser === undefined ? true : _ref$openBrowser,
      _ref$bundleDir = _ref.bundleDir,
      bundleDir = _ref$bundleDir === undefined ? null : _ref$bundleDir,
      _ref$logger = _ref.logger,
      logger = _ref$logger === undefined ? new Logger() : _ref$logger;

  var chartData = getChartData(logger, bundleStats, bundleDir);

  if (!chartData) return;

  var app = express();

  // Explicitly using our `ejs` dependency to render templates
  // Fixes #17
  app.engine('ejs', require('ejs').renderFile);
  app.set('view engine', 'ejs');
  app.set('views', projectRoot + '/views');
  app.use(express.static(projectRoot + '/public'));

  app.use('/', function (req, res) {
    res.render('viewer', {
      mode: 'server',
      chartData: JSON.stringify(chartData)
    });
  });

  return app.listen(port, host, function () {
    var url = 'http://' + host + ':' + port;

    logger.info(bold('Webpack Bundle Analyzer') + ' is started at ' + bold(url) + '\n' + ('Use ' + bold('Ctrl+C') + ' to close it'));

    if (openBrowser) {
      opener(url);
    }
  });
}

function generateReport(bundleStats, opts) {
  var _ref2 = opts || {},
      _ref2$openBrowser = _ref2.openBrowser,
      openBrowser = _ref2$openBrowser === undefined ? true : _ref2$openBrowser,
      _ref2$reportFilename = _ref2.reportFilename,
      reportFilename = _ref2$reportFilename === undefined ? 'report.html' : _ref2$reportFilename,
      _ref2$bundleDir = _ref2.bundleDir,
      bundleDir = _ref2$bundleDir === undefined ? null : _ref2$bundleDir,
      _ref2$logger = _ref2.logger,
      logger = _ref2$logger === undefined ? new Logger() : _ref2$logger;

  var chartData = getChartData(logger, bundleStats, bundleDir);

  if (!chartData) return;

  ejs.renderFile(projectRoot + '/views/viewer.ejs', {
    mode: 'static',
    chartData: JSON.stringify(chartData),
    assetContent: getAssetContent
  }, function (err, reportHtml) {
    if (err) return logger.error(err);

    var reportFilepath = reportFilename;

    if (!path.isAbsolute(reportFilepath)) {
      reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilepath);
    }

    mkdir.sync(path.dirname(reportFilepath));
    fs.writeFileSync(reportFilepath, reportHtml);

    logger.info(bold('Webpack Bundle Analyzer') + ' saved report to ' + bold(reportFilepath));

    if (openBrowser) {
      opener('file://' + reportFilepath);
    }
  });
}

function getAssetContent(filename) {
  return fs.readFileSync(projectRoot + '/public/' + filename, 'utf8');
}

function getChartData(logger) {
  var chartData = void 0;

  try {
    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    chartData = analyzer.getViewerData.apply(analyzer, args.concat([{ logger: logger }]));
  } catch (err) {
    logger.error('Could\'t analyze webpack bundle:\n' + err);
    chartData = null;
  }

  if (_.isEmpty(chartData)) {
    logger.error("Could't find any javascript bundles in provided stats file");
    chartData = null;
  }

  return chartData;
}