/
index.js
89 lines (75 loc) · 2.98 KB
/
index.js
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
'use strict';
const fs = require('fs');
const path = require('path');
const {SourceNode, SourceMapConsumer} = require('source-map');
const loaderUtils = require('loader-utils');
const makeIdentitySourceMap = require('./makeIdentitySourceMap');
const patch = require('./patch');
let tagCommonJSExportsSource = null;
function transform(source, map) {
const callback = this.async();
const resourcePath = this.resourcePath;
if (process.env.NODE_ENV === 'production') {
return callback(null, source, map);
}
if (source && source.types && source.types.IfStatement) {
throw new Error(
'React Hot Loader: You are erroneously trying to use a Webpack loader ' +
'as a Babel plugin. Replace "react-hot-loader/webpack" with ' +
'"react-hot-loader/babel" in the "plugins" section of your .babelrc file. ' +
'While we recommend the above, if you prefer not to use Babel, ' +
'you may remove "react-hot-loader/webpack" from the "plugins" section of ' +
'your .babelrc file altogether, and instead add "react-hot-loader/webpack" ' +
'to the "loaders" section of your Webpack configuration.',
);
}
if (this.cacheable) {
this.cacheable();
}
const options = Object.assign({withPatch: true}, loaderUtils.getOptions(this));
if (options.withPatch) {
source = patch(source);
}
if (source.indexOf('reactHotLoader.register') > 0) {
return callback(null, source, map);
}
// This is a Webpack loader, but the user put it in the Babel config.
// Read the helper once.
if (!tagCommonJSExportsSource) {
tagCommonJSExportsSource = fs
.readFileSync(path.join(__dirname, 'webpackTagCommonJSExports.js'), 'utf8')
// Babel inserts these.
// Ideally we'd opt out for one file but this is simpler.
.replace(/['"]use strict['"];/, '')
// eslint comments don't need to end up in the output
.replace(/\/\/ eslint-disable-line .*\n/g, '\n')
.replace(/\/\* global.*\*\//, '')
.split(/\n\s*/)
.join(' ');
}
// Parameterize the helper with the current filename.
const separator = '\n\n;';
const appendText = tagCommonJSExportsSource.replace(/__FILENAME__/g, JSON.stringify(resourcePath));
if (this.sourceMap === false) {
return callback(null, [source, appendText].join(separator));
}
if (!map) {
map = makeIdentitySourceMap(source, resourcePath); // eslint-disable-line no-param-reassign
}
const sourceMapConsumer = new SourceMapConsumer(map);
const onSourceMapReady = consumedMap => {
const node = new SourceNode(null, null, null, [
SourceNode.fromStringWithSourceMap(source, consumedMap),
new SourceNode(null, null, resourcePath, appendText),
]).join(separator);
const result = node.toStringWithSourceMap();
callback(null, result.code, result.map.toJSON() || undefined);
};
if (sourceMapConsumer.then) {
sourceMapConsumer.then(onSourceMapReady);
} else {
onSourceMapReady(sourceMapConsumer);
}
}
transform.patch = patch;
module.exports = transform;