~7 分鐘閱讀 · 教學


我看過許多 MUI 管理後台模板。material-kit-react 來自 minimals 團隊,是我經常回頭使用的模板。它乾淨、具型別,且資料夾結構合理。儲存庫:minimal-ui-kit/material-kit-react

但每次我只想看看它,或是改一個顏色來確認效果,總是重複同樣的流程。git clonenpm install、等待、npm run dev,再等待,切換到 localhost。幾分鐘就過去了,磁碟上還多出幾百 MB 的 node_modules。這一切只是為了看一眼儀表板。

所以這次我跳過建置。直接在 CrossUI Studio 中開啟資料夾,並直接渲染 src/main.tsx。不需要安裝、不需要 Vite、不需要 localhost。以下是我所做的過程,以及讓我停下來思考的細節。

先說實話。這無法取代你的開發伺服器。你仍然需要真正的開發伺服器來進行測試、正式建置,以及實際的功能開發。它適合「快速查看與微調」的循環:評估模板、重新配色、展示給客戶等,這些情況下啟動整套工具鏈的成本高於任務本身。


小提醒:本機資料夾支援需要 Pro 帳號。若要測試,可使用原文部落格中的代碼免費升級。無需信用卡,名額有限,額滿為止。

你的瀏覽器不支援影片。請至 YouTube 觀看。

1. 複製到本機磁碟(不要直接從 GitHub 開啟)

Studio 可以直接掛載 GitHub 儲存庫。對於小型儲存庫來說,這是最佳途徑。針對這個專案,我先複製到磁碟:

git clone https://github.com/minimal-ui-kit/material-kit-react

進入全螢幕模式 離開全螢幕模式

原因很單純。src/ 約有 130 個檔案,整個專案約 245 個檔案,分散在 sections/components/layouts/theme/routes/ 等目錄。開啟專案時,工具必須抓取它所碰觸的檔案。透過 GitHub API 按需抓取會產生大量小型請求。雖然可行,但速度不快,若頻繁操作還可能達到速率限制。本機資料夾只透過檔案系統,因此速度更快。對於這種規模的模板,本機複製較佳。

這裡沒有執行 npm install。我只複製了原始碼。重點就是不進行建置。

2. 開啟資料夾 — 並讓它產生專案設定

在 Studio 中:開啟本機資料夾,選擇已複製的 material-kit-react 目錄。它會讀取目錄結構。不會安裝任何東西、不會執行任何程式,檔案仍留在我的磁碟上。最後這點很重要,因為你可能不希望為了查看而將客戶的程式碼上傳到某處。

CrossUI Studio — React 與 MUI 的視覺化 IDE

第一次進入時,Studio 偵測到沒有專案設定檔,會跳出提示:

此專案沒有 CrossUI Studio 設定檔。我們建議先自動掃描專案以產生設定檔,之後再手動編輯。

CrossUI Studio — React 與 MUI 的視覺化 IDE

點擊掃描並產生。它會讀取專案自身的設定檔,並在根目錄寫入設定檔。之後,模板所使用的 import 就能正確解析,而不需要 Vite。我完全不需要手動設定任何內容。

CrossUI Studio — React 與 MUI 的視覺化 IDE

之後你可以手動編輯。專案設定對話框會直接開啟已產生的檔案。但自動產生的設定檔已足以完成以下所有操作。花費幾秒鐘,仍然完全不需要 npm install

3. 開啟 src/main.tsx 並點擊預覽

關閉專案設定對話框後,Studio 會直接開啟入口檔案。你不需要在檔案樹中搜尋。

以下是你通常無法「直接渲染」的檔案:

// src/main.tsx
const router = createBrowserRouter([
  {
    Component: () => (
      <App>
        <Outlet />
      </App>
    ),
    errorElement: <ErrorBoundary />,
    children: routesSection,
  },
]);

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>
);

進入全螢幕模式 離開全螢幕模式

這是 Vite 的入口檔案。createBrowserRouter + RouterProvider,而整個應用程式都包含在 <App>(主題提供者)與 routesSection(路由)之中。若以隔離方式直接渲染此檔案,會發生錯誤。沒有路由器上下文、沒有主題,也沒有應用程式所需的 #root

但它仍然成功渲染了。我沒有進行任何設定。開啟 main.tsx、點擊預覽,儀表板就出現在畫布上,並帶有 MUI 主題。

CrossUI Studio — React 與 MUI 的視覺化 IDE

現在回到設計模式。據我所知,它會從入口檔案中自動抓取提供者,因此若模板在啟動時有特殊處理,可能需要手動指定正確的提供者。對於 material-kit 來說,它直接就能運作,我猜這是因為 app.tsx 相當簡潔:

// src/app.tsx
export default function App({ children }: AppProps) {
  return (
    <ThemeProvider>
      {children}
      {/* github fab */}
    </ThemeProvider>
  );
}

進入全螢幕模式 離開全螢幕模式

乾淨的入口檔案在這裡非常重要。更多細節請見文末。

4. 深入探索 — 提供者會自動跟隨(這才是真正的重點)

/ 路徑的儀表板不是單一元件。它是由延遲載入的堆疊組成:

main.tsx  (RouterProvider 在此定義 + 偵測到的 ThemeProvider)
  └─ routesSection              (src/routes/sections.tsx)
       └─ DashboardPage          (src/pages/dashboard.tsx, lazy)
            └─ OverviewAnalyticsView   (src/sections/overview/view)
                 └─ AnalyticsWidgetSummary ×4   (src/sections/overview, 統計卡片)

進入全螢幕模式 離開全螢幕模式

CrossUI Studio — React 與 MUI 的視覺化 IDE

在畫布上按 Ctrl+點擊,可逐層向下瀏覽檔案樹。令人驚喜的是:包裝用的提供者會自動跟隨。在任何層級開啟「渲染裝飾」面板,都能看到兩個包裝器:RouterProviderThemeProvider

  • main.tsx 上,兩者皆會列出,但 自動跳過 RouterProvider。這很合理,因為該提供者就在此檔案中,若再包裝一次會造成重複。它只會套用主題。
  • sections.tsxdashboard.tsx 以及更下層,兩個提供者都會存在(面板顯示「2」)。因此路由器與主題上下文會一路跟隨。我完全不需要手動修復「缺少提供者」的問題。

這通常是在隔離渲染深層檔案時最痛苦的部分,而這裡是自動處理的。在前往目標檔案的過程中,只遇到兩次小型導覽中斷。兩者都不是錯誤,只是真實程式碼的常見情況。

中斷 1 — sections.tsx 開啟在錯誤的 JSX 區塊(renderFallback)。

按 Ctrl+點擊進入路由器檔案時,會停在 renderFallback,也就是 Suspense 的 spinner:

// src/routes/sections.tsx
const renderFallback = () => (
  <Box sx={{ display: 'flex', flex: '1 1 auto', alignItems: 'center', justifyContent: 'center' }}>
    ...
  </Box>
);

進入全螢幕模式 離開全螢幕模式

因此畫布幾乎空白。一個檔案可能包含多個 JSX 區塊,而這個 spinner 只是第一個。頂端有區塊導覽器(麵包屑下拉選單),會列出所有區塊。我切換到 routesSection 及其子項目:

export const routesSection: RouteObject[] = [
  {
    element: ( /* <DashboardLayout><Suspense><Outlet/></Suspense></DashboardLayout> */ ),
    children: [
      { index: true, element: <DashboardPage /> },
      { path: 'user',     element: <UserPage /> },
      { path: 'products', element: <ProductsPage /> },
      { path: 'blog',     element: <BlogPage /> },
    ],
  },
  // sign-in, 404 ...
];

進入全螢幕模式 離開全螢幕模式

CrossUI Studio — React 與 MUI 的視覺化 IDE

選擇 { index: true, element: <DashboardPage /> }(也就是 / 路由),整個儀表板就渲染出來了。主題已經從自動包裝器一路跟隨。找到 DashboardPageUserPage / ProductsPage 並排的位置只需一眼。路由看起來就像 URL 對照表。

CrossUI Studio — React 與 MUI 的視覺化 IDE

教訓:當一個檔案包含多個 JSX 區塊時,不要相信它顯示的第一個東西。請使用區塊導覽器來切換到你需要的區塊。

中斷 2 — index.ts 是 barrel 檔案,不是元件。

DashboardPage 繼續向下,我遇到這個:

// src/sections/overview/view/index.ts
export * from "./overview-analytics-view.tsx";

進入全螢幕模式 離開全螢幕模式

CrossUI Studio — React 與 MUI 的視覺化 IDE

NO-TARGET-JSX: 檔案中找不到目標 JSX 區塊。這是正確的。它是一個 re-export,沒有 JSX 可以渲染。sections/ 到處使用這種簡短的 barrel,讓 import 保持簡潔(使用 from 'src/sections/overview/view' 而非完整路徑)。在檔案清單中點擊 overview-analytics-view.tsx 即可開啟原始檔案。overview-analytics-view.tsx 會在開啟時渲染,主題已套用,而這正是我實際要編輯的檔案(下一節)。

因此讓我停下來的兩件事都不是錯誤。提供者會自動跟隨。其中一個是包含多個 JSX 區塊的檔案(使用導覽器),另一個是 barrel re-export(直接點擊)。這兩次半秒鐘的中斷,其實透露了更多關於模板結構的資訊,而不是工具的問題。

CrossUI Studio — React 與 MUI 的視覺化 IDE

(編輯器上方的區塊導覽器也可以直接跳到任何層級,若你覺得點擊穿梭很麻煩。)

5. 進行修改

overview-analytics-view.tsx 是四個統計卡片取得 props 的地方,而且讀起來很簡單:

<AnalyticsWidgetSummary
  title="Weekly sales"
  percent={2.6}
  total={714000}
  // color 預設為 primary
/>

進入全螢幕模式 離開全螢幕模式

兩處小修改,都是從畫布與檢查器完成的。我將「Weekly sales」卡片的 color 改為 warning,並將 total 提高。接著將「New users」卡片的 colorsecondary 改為 success。產生的 diff 正是這些修改,沒有其他變更:

   <AnalyticsWidgetSummary
     title="Weekly sales"
     percent={2.6}
-    total={714000}
+    total={928000}
+    color="warning"
     ...
   />
   <AnalyticsWidgetSummary
     title="New users"
     percent={-0.1}
     total={1352831}
-    color="secondary"
+    color="success"
     ...
   />

進入全螢幕模式 離開全螢幕模式

CrossUI Studio — React 與 MUI 的視覺化 IDE

沒有重新格式化、沒有碰觸 import,其他卡片完全相同。這是我最在意的部分。我希望它能以我原本會手動輸入的方式寫入修改,而不是從內部模型重新輸出整個檔案。這裡只進行了精準的 prop 修改。

如果你想進行更大的修改,可以從主題著手。src/theme/ 是調色盤建立的地方,在那裡修改 primary 顏色會改變按鈕、導覽列、啟用狀態等所有地方。同樣的流程,但影響範圍更廣。

6. 回到整個應用程式 — 只需按下瀏覽器返回鍵

有件小事我沒想到會這麼喜歡。我不需要從檔案樹重新開啟 main.tsx 來返回。每一次向下鑽取都是真正的導覽,每次進入時 URL 都會改變,因此瀏覽器返回鍵可以直接回到上層。檢視 → 頁面 → 路由 → main.tsx。前進與返回的行為就像一般網頁應用程式。按幾次返回,我就會看到完整的儀表板,並帶有我所做的修改。「Weekly sales」卡片現在在真實佈局中呈現琥珀色,而不只是在我修改它的隔離檢視中。

CrossUI Studio — React 與 MUI 的視覺化 IDE

這種「在檢視深處進行編輯,然後一路返回到整個應用程式查看」的流程,通常需要重新載入並進行心理上的上下文切換。在這裡,它是同一個畫布,而且只要按返回鍵即可。

git clone 到「在執行中的儀表板中看到琥珀色卡片」的總時間:只要幾分鐘,大部分時間花在複製上。完全不需要 npm install


為什麼摩擦點出現在這些地方(給模板作者的建議)

其實並非完全零摩擦。向下鑽取的過程中遇到兩次小型導覽中斷。但兩者都出現在可預測的位置:多區塊的路由器檔案,以及 barrel re-export,而且每次都只需一點擊即可解決。之所以這麼可預測,很大一部分來自模板本身,而不是工具。material-kit-react 的組織方式與工具相當配合:

  • 入口檔案(main.tsx / app.tsx)相當直觀。提供者就在這裡,不會隱藏在三層間接參照之後。這可能就是為什麼 RouterProviderThemeProvider 能被抓取,並在每一層級都持續套用的原因。主題上下文會自動跟隨,完全不需要手動修復提供者。
  • 路由使用 lazy() 並分組在 routesSection 中,因此區塊導覽器看起來就像 URL 結構。找到 DashboardPageUserPage / ProductsPage 並排的位置只需一眼。
  • sections/ 會依功能拆分,並放在簡短的 barrel index.ts 檔案後面。這讓真實應用程式中的 import 保持簡潔,而在向下鑽取時,你只需點擊 export * 那一行。可預測的模式勝過聰明的模式。
  • 卡片接受純粹的 propsAnalyticsWidgetSummary 只需要 title/total/percent/color/chart,由 view 提供。因此從 view 編輯就是資料變更,而不是後端呼叫,而 diff 只會是一行。

如果模板結構混亂,預覽就會變得困難,無論有沒有工具。若提供者是動態組裝、單一頁面有 2000 行程式碼、section 必須接收真實的 fetched 資料才能運作,那麼好的模板結構就是讓「不建置就能開啟」成為現實的重要因素。為此要向 material-kit-react 致敬,它的結構確實發揮了作用。

實際上,如果你製作或銷售模板。有人評估你的模板時,一大部分的摩擦來自「clone-install-run」的成本。讓模板可以直接從原始碼預覽與微調,能大幅降低這項成本。這值得思考。

我不會用它來做什麼

  • 執行測試套件或真正的 Vite 建置。這是預覽 + 編輯,不是 CI。
  • 任何需要即時後端資料才能渲染的內容。你可以為向下鑽取模擬資料,但那是不同的工作流程。
  • 對執行時期行為的最終判斷。它會從原始碼渲染結構,但不會監視你的應用程式真正從頭到尾執行。

對於「開啟這個模板、修改幾處、在上下文中查看」這種我使用管理後台模板前最常做的事,跳過建置就是少了一道繁瑣的手續。


小提醒:本機資料夾支援需要 Pro 帳號。若要測試,可使用原文部落格中的代碼免費升級。無需信用卡,名額有限,額滿為止。