Quantcast
Channel: ReScript Forum - Latest posts
Viewing all articles
Browse latest Browse all 2592

How to Resolve Export Format Conflicts Between ReScript and React Router v7 for Hot Module Replacement?

$
0
0

I tried writing a vite transformation plugin to enable code written in ReScript to run properly in SSR mode with React Router v7 in Vite. However, I still haven’t found the reason why it doesn’t support the error caused by export { someVariable as default } .
But it seems to be working properly now.

// vite-plugin-fix-dollar-default-export.js
export default function fixDollarDefaultExport() {
  return {
    name: 'fix-dollar-default-export',
    
    transform(code, id) {
      if (!/\.(js|jsx|ts|tsx|mjs|cjs)$/.test(id)) return null;
      
      let transformedCode = code;
      let hasChanged = false;
      
      const exportBlockPattern = /export\s*\{([^}]+)\}/g;
      const exportBlocks = [...transformedCode.matchAll(exportBlockPattern)];
      
      for (const block of exportBlocks) {
        const fullMatch = block[0];
        const exportContent = block[1].trim();
        
        if (exportContent.includes('as default')) {
          const exportItems = exportContent.split(',')
            .map(item => item.trim())
            .filter(item => item.length > 0);
          
          const defaultExports = [];
          const normalExports = [];
          
          for (const item of exportItems) {
            const asDefaultMatch = item.match(/^(.+?)\s+as\s+default$/);
            
            if (asDefaultMatch) {
              const varName = asDefaultMatch[1].trim();
              
              if (/^[\w$]+$/.test(varName)) {
                defaultExports.push(varName);
              } else {
                normalExports.push(item);
              }
            } else {
              normalExports.push(item);
            }
          }
          
          if (defaultExports.length > 0) {
            let newExports = '';
            
            if (normalExports.length > 0) {
              newExports += `export { ${normalExports.join(', ')} };\n`;
            }
            
            defaultExports.forEach(varName => {
              newExports += `export default ${varName};\n`;
            });
            console.log('origin: ', transformedCode)
            transformedCode = transformedCode.replace(fullMatch, () => newExports.trim());
            console.log(fullMatch + ' ---> ' +  newExports.trim())
            console.log("result: ", transformedCode)
            hasChanged = true;
          }
        }
      }
      
      if (hasChanged) {
        return {
          code: transformedCode,
          map: null
        };
      }
      
      return null;
    }
  };
}
// vite.config.js
import { reactRouter } from "@react-router/dev/vite";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
import rewrite from './vite-plugin-fix-export-default'

export default defineConfig({
  plugins: [tailwindcss(), rewrite(), reactRouter(), ]  
});

input

origin:  // Generated by ReScript, PLEASE EDIT WITH CARE

import * as JsxRuntime from "react/jsx-runtime";

function loader() {
  return Promise.resolve({
    text: "about 1"
  });
}

function About$default(props) {
  return JsxRuntime.jsx("strong", {
    children: props.loaderData.text
  });
}

let $$default = About$default;

export {
  loader,
  $$default as default,
}
/* react/jsx-runtime Not a pure module */

output:

result:  // Generated by ReScript, PLEASE EDIT WITH CARE

import * as JsxRuntime from "react/jsx-runtime";

function loader() {
  return Promise.resolve({
    text: "about 1"
  });
}

function About$default(props) {
  return JsxRuntime.jsx("strong", {
    children: props.loaderData.text
  });
}

let $$default = About$default;

export { loader };
export default $$default;
/* react/jsx-runtime Not a pure module */

Translation target:


export {
  loader,
  $$default as default,
} ---> export { loader };
export default $$default;

Viewing all articles
Browse latest Browse all 2592

Trending Articles