UNPKG

3 kBJavaScriptView Raw
1const codeFrame = require('babel-code-frame');
2const cache = require('./cache');
3const tmpFile = require('./tmp-file');
4const BOGUS_SOURCEMAP_STRING = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
5// This has to be broken apart or ava/nyc will try to use it when creating coverage reports.
6const URL_PREFIX = '//# sourceMappingURL=';
7const BOGUS_SOURCEMAP_URL = `\n${URL_PREFIX}${BOGUS_SOURCEMAP_STRING}`;
8
9function minify(source, map, uglifyOptions, uglifier) {
10 // inSourceMap doesn't work without outSourceMap, and uglify adds this as a url to the resulting
11 // code. We'd rather have the plugin respect our devtool setting, so we're going to provide a
12 // bogus filename, then strip it out after.
13 const opts = Object.assign({}, uglifyOptions);
14 if (map) {
15 Object.assign(opts, {
16 sourceMap: {
17 content: map,
18 includeSources: true,
19 url: BOGUS_SOURCEMAP_STRING,
20 },
21 });
22 }
23
24 const result = uglifier.minify(source, opts);
25 if (result.error) {
26 if (result.error.name === 'SyntaxError') {
27 const frame = codeFrame(source, result.error.line, result.error.col);
28 const errorMessage = `${result.error.name}: ${result.error.message}\n${frame}`;
29 throw new SyntaxError(errorMessage);
30 }
31
32 throw result.error;
33 }
34
35 result.code = result.code.replace(new RegExp(BOGUS_SOURCEMAP_URL), '');
36
37 return result;
38}
39
40/**
41 * Note: We're passing messages via tmpFiles as this is faster than passing through ipc.
42 * In this function msgLocation is the tmp file's name, so that we know where to look
43 * for our message.
44 *
45 * We expect the messages to have the following format:
46 * {
47 * assetName: 'someFileName.js',
48 * source: 'function() {}',
49 * map: 'a source map string if enabled',
50 * cacheDir: 'location to cache results',
51 * options: {
52 * pluginOptions,
53 * },
54 * }
55 */
56
57function processMessage(msgLocation, callback) {
58 try {
59 const messageContents = tmpFile.read(msgLocation);
60 const message = JSON.parse(messageContents);
61 const source = message.source;
62 const map = message.map;
63
64 const cacheKey = cache.createCacheKey(source + !!map, message.options);
65 // We do not check the cache here because we already determined that this asset yields a cache
66 // miss in the parent process.
67 const uglifyES = message.options.uglifyES;
68 const uglifyJS = message.options.uglifyJS;
69 const uglifier = uglifyES ? require('uglify-es') : require('uglify-js'); // eslint-disable-line global-require, max-len
70 const minifiedContent = minify(source, map, uglifyES || uglifyJS, uglifier);
71 cache.saveToCache(cacheKey, JSON.stringify({
72 source: minifiedContent.code,
73 map: minifiedContent.map,
74 }), message.cacheDir);
75
76 tmpFile.update(msgLocation, JSON.stringify({
77 source: minifiedContent.code,
78 map: minifiedContent.map,
79 cacheKey,
80 }));
81 callback(null, msgLocation);
82 } catch (e) {
83 callback(e.message, msgLocation);
84 }
85}
86
87module.exports = {
88 minify,
89 processMessage,
90};