@tuax/plugin-react
Version:
support react 18
94 lines (86 loc) • 3.21 kB
JavaScript
/**
* react fast refresh loader
* @see https://github.com/facebook/react/issues/16604
* @see https://github.com/pekala/react-refresh-test
*
* 注入热更新方法代码
*/
/**
* 调整sourcemap的行数
* @param sourcemap
* @param lineOffset
* @returns {Promise<{mappings: *, names: *, sources: *, version: *}>}
*/
async function adjustSourcemapLines (sourcemap, lineOffset) {
const { SourceMapConsumer, SourceMapGenerator } = require('source-map');
const consumer = await new SourceMapConsumer(sourcemap);
const generator = new SourceMapGenerator({
file: sourcemap.file,
sourceRoot: sourcemap.sourceRoot,
});
consumer.eachMapping(mapping => {
if (mapping.source) {
generator.addMapping({
source: mapping.source,
original: { line: mapping.originalLine, column: mapping.originalColumn },
generated: { line: mapping.generatedLine + lineOffset, column: mapping.generatedColumn },
name: mapping.name,
});
}
// 如果存在 sourcesContent,将其复制到新的 SourceMap
if (consumer.sourcesContent) {
consumer.sources.forEach((source, index) => {
generator.setSourceContent(source, consumer.sourcesContent[index]);
});
}
});
consumer.destroy();
return generator.toJSON();
}
module.exports = function (source, map, meta) {
let injectedSource = source;
const callback = this.async();
if (source.includes('$refresh-loader_should_handle_this$')) {
injectedSource = `
// 防止和react-native项目中的react-refresh产生冲突,需要固定react-refresh的位置,从启动项目的 node_modules中查找包
// require的URL需使用 / 做目录分割符。在linux或者Mac OS上, 分隔符为 /,而在windows上,路径中的分隔符为 \\,所以需转换为统一的分隔符 /。
let refreshRuntime = require('${process.cwd().replace(/\\/g, '/')}/node_modules/react-refresh/runtime')
const debounce = function (fn, delay) {
var timer
return function () {
var context = this
var args = arguments
clearTimeout(timer)
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
let enqueueUpdate = debounce(refreshRuntime.performReactRefresh, 30);
let wglobal = typeof global === 'undefined'? window : global
let prevRefreshReg = wglobal.$RefreshReg$;
let prevRefreshSig = wglobal.$RefreshSig$;
wglobal.$RefreshReg$ = (type, id) => {
// Note module.id is webpack-specific, this may vary in other bundlers
const fullId = module.id + ' ' + id;
refreshRuntime.register(type, fullId);
}
wglobal.$RefreshSig$ = refreshRuntime.createSignatureFunctionForTransform;
try {
${source}
if(module.hot){
module.hot.accept()
enqueueUpdate()
}
} finally {
wglobal.$RefreshReg$ = prevRefreshReg;
wglobal.$RefreshSig$ = prevRefreshSig;
}`;
}
// 假设 `originalSourcemap` 是你的原始 sourcemap 对象
// 调用 adjustSourcemapLines 函数,假设要向下偏移 29 行
adjustSourcemapLines(map, 29).then(adjustedSourcemap => {
// 使用 `adjustedSourcemap` 做进一步处理
callback(null, injectedSource, adjustedSourcemap, meta);
});
};