UNPKG

2.58 kBJavaScriptView Raw
1/* global Buffer */
2
3import path from 'path';
4import url from 'url';
5import RequestShortener from 'webpack/lib/RequestShortener';
6
7export default class AssetMapPlugin {
8 /**
9 * AssetMapPlugin
10 *
11 * @param {string} outputFile - Where to write the asset map file
12 * @param {string} [relativeTo] - Key assets relative to this path, otherwise defaults to be relative to the directory where the outputFile is written
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}