Skip to content

Instantly share code, notes, and snippets.

@maisano
Created September 10, 2019 00:47
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save maisano/441a4bc6b2954205803d68deac04a716 to your computer and use it in GitHub Desktop.
Save maisano/441a4bc6b2954205803d68deac04a716 to your computer and use it in GitHub Desktop.
const ReactRefreshHotModule = require.resolve('./ReactRefreshHotModule');
const ReactRefreshHotModuleInjection = `
const ReactRefreshHotModule = require('${ReactRefreshHotModule}');
if (ReactRefreshHotModule.isReactRefreshBoundary(module.exports || module.__proto__exports)) {
module.hot.accept(module.id, () => {
ReactRefreshHotModule.enqueueUpdate();
});
}
`;
function HotModuleLoader(source) {
return source + ReactRefreshHotModuleInjection;
}
module.exports = HotModuleLoader;
const ReactRefreshRuntimeInjection = `
if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined') {
const ReactRefreshRuntime = require('react-refresh/runtime');
ReactRefreshRuntime.injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => type => type;
window.__setupReactRefreshForModule = (moduleId) => {
const prevRefreshReg = window.$RefreshReg$;
const prevRefreshSig = window.$RefreshSig$;
window.$RefreshReg$ = (type, id) => {
const fullId = moduleId + ' ' + id;
ReactRefreshRuntime.register(type, fullId);
};
window.$RefreshSig$ = ReactRefreshRuntime.createSignatureFunctionForTransform;
return () => {
window.$RefreshReg$ = prevRefreshReg;
window.$RefreshSig$ = prevRefreshSig;
};
};
}
`;
function ReactDOMLoader(source) {
return ReactRefreshRuntimeInjection + source;
}
module.exports = ReactDOMLoader;
const ReactRefreshRuntime = require('react-refresh/runtime');
let timerId;
function enqueueUpdate() {
clearTimeout(timerId);
timerId = setTimeout(() => {
ReactRefreshRuntime.performReactRefresh();
}, 30);
}
function isReactRefreshBoundary(moduleExports) {
if (ReactRefreshRuntime.isLikelyComponentType(moduleExports)) {
return true;
}
if (moduleExports == null || typeof moduleExports !== 'object') {
// Exit if we can't iterate over exports.
return false;
}
let hasExports = false;
let areAllExportsComponents = true;
for (const key in moduleExports) {
hasExports = true;
if (key === '__esModule') {
continue;
}
const desc = Object.getOwnPropertyDescriptor(moduleExports, key);
if (desc && desc.get) {
// Don't invoke getters as they may have side effects.
return false;
}
const exportValue = moduleExports[key];
if (!ReactRefreshRuntime.isLikelyComponentType(exportValue)) {
areAllExportsComponents = false;
}
}
return hasExports && areAllExportsComponents;
}
module.exports = {
isReactRefreshBoundary,
enqueueUpdate,
};
class ReactRefreshPlugin {
apply(compiler) {
if (process.env.NODE_ENV !== 'development') {
return;
}
compiler.hooks.normalModuleFactory.tap('ReactRefreshPlugin', (nmf) => {
nmf.hooks.afterResolve.tap('ReactRefreshPlugin', (data) => {
if (data.rawRequest === 'react-dom') {
data.loaders.unshift({
loader: require.resolve('./ReactDOMLoader'),
});
} else if (/\.jsx?$/.test(data.resource) && !/node_modules/.test(data.resource)) {
data.loaders.unshift({
loader: require.resolve('./HotModuleLoader'),
});
}
return data;
});
});
compiler.hooks.compilation.tap('ReactRefreshPlugin', (compilation) => {
compilation.mainTemplate.hooks.require.tap('ReactRefreshPlugin', (source) => {
const lines = source.split('\n');
const moduleInitializationLineNumber = lines.findIndex((line) => {
return line.startsWith('modules[moduleId].call');
});
if (moduleInitializationLineNumber === -1) {
return source;
}
lines.splice(
moduleInitializationLineNumber,
1,
'var cleanup = window.__setupReactRefreshForModule',
' ? window.__setupReactRefreshForModule(module.i)',
' : function() {};',
'try {',
' ' + lines[moduleInitializationLineNumber],
'} finally {',
' cleanup();',
'}',
);
return lines.join('\n');
});
});
}
}
module.exports = ReactRefreshPlugin;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment