Blame view

node_modules/webpack-bundle-analyzer/src/BundleAnalyzerPlugin.js 3.46 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  const bfj = require('bfj-node4');
  const path = require('path');
  const mkdir = require('mkdirp');
  const { bold } = require('chalk');
  
  const Logger = require('./Logger');
  const viewer = require('./viewer');
  
  class BundleAnalyzerPlugin {
  
    constructor(opts) {
      this.opts = {
        analyzerMode: 'server',
        analyzerHost: '127.0.0.1',
        analyzerPort: 8888,
        reportFilename: 'report.html',
        defaultSizes: 'parsed',
        openAnalyzer: true,
        generateStatsFile: false,
        statsFilename: 'stats.json',
        statsOptions: null,
        excludeAssets: null,
        logLevel: 'info',
        // deprecated
        startAnalyzer: true,
        ...opts
      };
  
      this.server = null;
      this.logger = new Logger(this.opts.logLevel);
    }
  
    apply(compiler) {
      this.compiler = compiler;
  
      const done = stats => {
        stats = stats.toJson(this.opts.statsOptions);
  
        const actions = [];
  
        if (this.opts.generateStatsFile) {
          actions.push(() => this.generateStatsFile(stats));
        }
  
        // Handling deprecated `startAnalyzer` flag
        if (this.opts.analyzerMode === 'server' && !this.opts.startAnalyzer) {
          this.opts.analyzerMode = 'disabled';
        }
  
        if (this.opts.analyzerMode === 'server') {
          actions.push(() => this.startAnalyzerServer(stats));
        } else if (this.opts.analyzerMode === 'static') {
          actions.push(() => this.generateStaticReport(stats));
        }
  
        if (actions.length) {
          // Making analyzer logs to be after all webpack logs in the console
          setImmediate(() => {
            actions.forEach(action => action());
          });
        }
      };
  
      if (compiler.hooks) {
        compiler.hooks.done.tap('webpack-bundle-analyzer', done);
      } else {
        compiler.plugin('done', done);
      }
    }
  
    async generateStatsFile(stats) {
      const statsFilepath = path.resolve(this.compiler.outputPath, this.opts.statsFilename);
      mkdir.sync(path.dirname(statsFilepath));
  
      try {
        await bfj.write(statsFilepath, stats, {
          space: 2,
          promises: 'ignore',
          buffers: 'ignore',
          maps: 'ignore',
          iterables: 'ignore',
          circular: 'ignore'
        });
  
        this.logger.info(
          `${bold('Webpack Bundle Analyzer')} saved stats file to ${bold(statsFilepath)}`
        );
      } catch (error) {
        this.logger.error(
          `${bold('Webpack Bundle Analyzer')} error saving stats file to ${bold(statsFilepath)}: ${error}`
        );
      }
    }
  
    async startAnalyzerServer(stats) {
      if (this.server) {
        (await this.server).updateChartData(stats);
      } else {
        this.server = viewer.startServer(stats, {
          openBrowser: this.opts.openAnalyzer,
          host: this.opts.analyzerHost,
          port: this.opts.analyzerPort,
          bundleDir: this.getBundleDirFromCompiler(),
          logger: this.logger,
          defaultSizes: this.opts.defaultSizes,
          excludeAssets: this.opts.excludeAssets
        });
      }
    }
  
    generateStaticReport(stats) {
      viewer.generateReport(stats, {
        openBrowser: this.opts.openAnalyzer,
        reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename),
        bundleDir: this.getBundleDirFromCompiler(),
        logger: this.logger,
        defaultSizes: this.opts.defaultSizes,
        excludeAssets: this.opts.excludeAssets
      });
    }
  
    getBundleDirFromCompiler() {
      return (this.compiler.outputFileSystem.constructor.name === 'MemoryFileSystem') ? null : this.compiler.outputPath;
    }
  
  }
  
  module.exports = BundleAnalyzerPlugin;