UNPKG

@tuax/plugin-react

Version:

support react 18

94 lines (86 loc) 3.21 kB
/** * 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); }); };