Skip to content

Babel preset fails for Vite production build when functions are hoisted within components #170

Description

@devuxer

Hey @pzuraq,

I have several components with nested functions that are defined after the return statement, and therefore rely on JS hoisting.

Example:

import Stack from "@mui/material/Stack";
import { component } from "signalium/react";
import TableView from "@/features/dashboard/TableView";
import { dashboardFormat } from "@/features/dashboard/toolbar/toolbar-state";
import { unitStates } from "./dashboard-state";
import Toolbar from "./toolbar/Toolbar";
import UnitPanel from "./unit-summary/UnitPanel";

const Dashboard = component(() => {
    return (
        <Stack spacing={2} sx={{ maxWidth: "75em" }}>
            <Toolbar />
            {getBody()}
        </Stack>
    );

    function getBody() {
        switch (dashboardFormat.value) {
            case "Card":
                return unitStates().map(x => <UnitPanel key={x.code} state={x} />);
            case "Table":
                return <TableView />;
        }
    }
});

export default Dashboard;

This has been working fine in development, but I now realize it fails in production when the Babel preset is used.

This is what gets generated after running vite build:

const Dashboard = component(() => {
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Stack, { spacing: 2, sx: {
    maxWidth: "75em"
  }, children: [
    /* @__PURE__ */ jsxRuntimeExports.jsx(Toolbar, {}),
    getBody()
  ] });
  const getBody = callback(function getBody2() {
    switch (dashboardFormat.value) {
      case "Card":
        return unitStates().map(callback((x) => /* @__PURE__ */ jsxRuntimeExports.jsx(UnitPanel, { state: x }, x.code), 0));
      case "Table":
        return /* @__PURE__ */ jsxRuntimeExports.jsx(TableView, {});
    }
  }, 0);
});

This fails because getBody() is not defined at the time it is called.

Vite config:

import react from "@vitejs/plugin-react";
import { signaliumPreset } from "signalium/transform";
import { defineConfig } from "vite";
import viteTsconfigPaths from "vite-tsconfig-paths";

// https://vite.dev/config/
export default defineConfig({
    plugins: [react({ babel: { presets: [signaliumPreset()] } }), viteTsconfigPaths()],
    server: { open: true, port: 3000 },
    build: { minify: false },
});

This is what gets output w/o the Babel preset (and works as expected):

const Dashboard = component(() => {
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Stack, { spacing: 2, sx: { maxWidth: "75em" }, children: [
    /* @__PURE__ */ jsxRuntimeExports.jsx(Toolbar, {}),
    getBody()
  ] });
  function getBody() {
    switch (dashboardFormat.value) {
      case "Card":
        return unitStates().map((x) => /* @__PURE__ */ jsxRuntimeExports.jsx(UnitPanel, { state: x }, x.code));
      case "Table":
        return /* @__PURE__ */ jsxRuntimeExports.jsx(TableView, {});
    }
  }
});

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions