1 |
|
2 |
|
3 | import path from 'path';
|
4 | import url from 'url';
|
5 | import RequestShortener from 'webpack/lib/RequestShortener';
|
6 |
|
7 | export default class AssetMapPlugin {
|
8 | |
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | constructor(outputFile, relativeTo) {
|
15 | this.outputFile = outputFile;
|
16 | this.relativeTo = relativeTo;
|
17 | this.previousChunks = {};
|
18 | }
|
19 |
|
20 | _extractAssets(modules, requestShortener, publicPath) {
|
21 | let emitted = false;
|
22 | const mappedAssets = modules
|
23 | .map(m => {
|
24 | const assets = Object.keys(m.assets || {});
|
25 |
|
26 | if (assets.length === 0) {
|
27 | return undefined;
|
28 | }
|
29 |
|
30 | const asset = assets[0];
|
31 | emitted = emitted || m.assets[asset].emitted;
|
32 |
|
33 | return {
|
34 | name: m.readableIdentifier(requestShortener),
|
35 | asset: asset
|
36 | };
|
37 | }).filter(m => {
|
38 | return m !== undefined;
|
39 | }).reduce((acc, m) => {
|
40 | acc[m.name] = url.resolve(publicPath, m.asset);
|
41 | return acc;
|
42 | }, {});
|
43 |
|
44 | return [emitted, mappedAssets];
|
45 | }
|
46 |
|
47 | _extractChunks(chunks, publicPath) {
|
48 | const mappedChunks = chunks
|
49 | .map(c => {
|
50 | return {
|
51 | name: c.name,
|
52 | files: c.files
|
53 | .filter(f => path.extname(f) !== '.map')
|
54 | .map(f => url.resolve(publicPath, f))
|
55 | };
|
56 | })
|
57 | .reduce((acc, c) => {
|
58 | acc[c.name] = c.files;
|
59 | return acc;
|
60 | }, {});
|
61 |
|
62 | const emitted = JSON.stringify(this.previousChunks) !== JSON.stringify(mappedChunks);
|
63 | this.previousChunks = mappedChunks;
|
64 |
|
65 | return [emitted, mappedChunks];
|
66 | }
|
67 |
|
68 | apply(compiler) {
|
69 | compiler.plugin('emit', (compilation, done) => {
|
70 | const publicPath = compilation.outputOptions.publicPath;
|
71 | const requestShortener = new RequestShortener(this.relativeTo || compilation.outputOptions.path);
|
72 |
|
73 | const [assetsEmitted, assets] = this._extractAssets(compilation.modules, requestShortener, publicPath);
|
74 | const [chunksEmitted, chunks] = this._extractChunks(compilation.chunks, publicPath);
|
75 |
|
76 | if (assetsEmitted || chunksEmitted) {
|
77 | const out = JSON.stringify({ assets, chunks }, null, 2);
|
78 | compilation.assets[this.outputFile] = {
|
79 | source: () => {
|
80 | return out;
|
81 | },
|
82 | size: () => {
|
83 | return Buffer.byteLength(out, 'utf8');
|
84 | }
|
85 | };
|
86 | }
|
87 | done();
|
88 | });
|
89 | }
|
90 | }
|