說明
支持我們

入門

不熟悉 Preact?不熟悉虛擬 DOM?請查看教學

本指南協助您快速上手,開始使用 3 個熱門選項開發 Preact 應用程式。如果您不熟悉 Preact,我們建議從Vite開始。



無建置工具路徑

Preact 的封裝可直接在瀏覽器中使用,不需要任何建置或工具

<script type="module">
  import { h, render } from 'https://esm.sh/preact';

  // Create your app
  const app = h('h1', null, 'Hello World!');

  render(app, document.body);
</script>

🔨 在 Glitch 上編輯

使用這種方式開發的主要缺點是缺乏 JSX,這需要建置步驟。下一個區段記載了 JSX 的人體工學且效能良好的替代方案。

JSX 的替代方案

撰寫原始的 hcreateElement 呼叫可能會很繁瑣。根據我們的經驗,JSX 的優點在於它看起來很像 HTML,這讓許多開發人員更容易理解。不過 JSX 需要建置步驟,因此我們強烈推薦使用稱為 HTM 的替代方案。

HTM 是一種類似 JSX 的語法,可在標準 JavaScript 中運作。它不需要建置步驟,而是使用 JavaScript 本身的 標記範本 語法,該語法於 2015 年新增,並受 所有現代瀏覽器 支援。這是一種越來越流行的撰寫 Preact 應用程式的方式,因為與傳統的前端建置工具設定相比,它需要理解的活動部分較少。

<script type="module">
  import { h, render } from 'https://esm.sh/preact';
  import htm from 'https://esm.sh/htm';

  // Initialize htm with Preact
  const html = htm.bind(h);

  function App (props) {
    return html`<h1>Hello ${props.name}!</h1>`;
  }

  render(html`<${App} name="World" />`, document.body);
</script>

🔨 在 Glitch 上編輯

提示:HTM 也提供方便的單一匯入 Preact 版本

import { html, render } from 'https://esm.sh/htm/preact/standalone'

如需更完整的範例,請參閱 使用 Preact 搭配 HTM 和 ImportMaps,如需 HTM 的更多資訊,請查看其 文件

建立一個 Vite 驅動的 Preact 應用程式

Vite 在過去幾年已成為一個非常受歡迎的工具,用於在許多架構中建立應用程式,而 Preact 也不例外。它建立在流行的工具之上,例如 ES 模組、Rollup 和 ESBuild。Vite,透過我們的初始化器或他們的 Preact 範本,不需要任何設定或先備知識即可開始,而這種簡潔性使其成為使用 Preact 的非常受歡迎的方式。

要快速使用 Vite 並執行,你可以使用我們的初始化器 create-preact。這是一個互動式命令列介面 (CLI) 應用程式,可以在你機器上的終端機中執行。使用它,你可以透過執行以下指令來建立一個新的應用程式

npm init preact

這將引導你建立一個新的 Preact 應用程式,並提供一些選項,例如 TypeScript、路由(透過 preact-iso)和 ESLint 支援。

提示:這些決定都不需要是最終的,如果你改變主意,你隨時可以將它們新增或從你的專案中移除。

準備好開發

現在我們準備好啟動我們的應用程式了。要啟動開發伺服器,請在你的新產生專案資料夾中執行以下指令

# Go into the generated project folder
cd my-preact-app

# Start a development server
npm run dev

伺服器啟動後,它會列印一個本機開發 URL,以便在你的瀏覽器中開啟。現在你準備好開始編寫你的應用程式了!

建立一個生產版本

總會遇到你需要在某處部署應用程式的時刻。Vite 附帶一個方便的 build 指令,它將產生一個高度最佳化的生產版本。

npm run build

完成後,您將有一個新的 dist/ 資料夾,可以直接部署到伺服器。

如需所有可用指令及其選項的完整清單,請查看 Vite CLI 文件

整合到現有管線

如果您已經設定現有的工具管線,很可能會包含一個打包器。最受歡迎的選擇有 webpackrollupparcel。Preact 可與所有這些工具順利搭配使用,無需進行重大變更!

設定 JSX

若要轉譯 JSX,您需要一個 Babel 外掛程式,將其轉換為有效的 JavaScript 程式碼。我們所有人都在使用 @babel/plugin-transform-react-jsx。安裝後,您需要指定應使用的 JSX 函式

{
  "plugins": [
    ["@babel/plugin-transform-react-jsx", {
      "pragma": "h",
      "pragmaFrag": "Fragment",
    }]
  ]
}

Babel 擁有目前最好的文件。我們強烈建議您查看有關 Babel 及其設定方式的問題。

將 React 別名設為 Preact

在某個時間點,您可能會想要利用廣大的 React 生態系統。最初為 React 編寫的函式庫和元件可與我們的相容性層無縫搭配使用。若要使用它,我們需要將所有 reactreact-dom 匯入指向 Preact。此步驟稱為別名設定

注意:如果您使用 Vite、Preact CLI 或 WMR,這些別名會在預設情況下自動為您處理。

在 Webpack 中設定別名

要在 Webpack 中設定任何套件別名,你需要在設定檔中新增 resolve.alias 區段。根據你使用的設定,這個區段可能已經存在,但缺少 Preact 的別名。

const config = {
   //...snip
  "resolve": {
    "alias": {
      "react": "preact/compat",
      "react-dom/test-utils": "preact/test-utils",
      "react-dom": "preact/compat",     // Must be below test-utils
      "react/jsx-runtime": "preact/jsx-runtime"
    },
  }
}

在 Node 中設定別名

在 Node 中執行時,套件管理工具別名(Webpack、Rollup 等)將無法運作,如 NextJS 所見。若要修正這個問題,我們可以在 package.json 中直接使用別名。

{
  "dependencies": {
    "react": "npm:@preact/compat",
    "react-dom": "npm:@preact/compat",
  }
}

在 Parcel 中設定別名

Parcel 使用標準的 package.json 檔案,在 alias 鍵下讀取設定選項。

{
  "alias": {
    "react": "preact/compat",
    "react-dom/test-utils": "preact/test-utils",
    "react-dom": "preact/compat",
    "react/jsx-runtime": "preact/jsx-runtime"
  },
}

在 Rollup 中設定別名

要在 Rollup 中設定別名,你需要安裝 @rollup/plugin-alias。這個外掛程式需要放在 @rollup/plugin-node-resolve 之前。

import alias from '@rollup/plugin-alias';

module.exports = {
  plugins: [
    alias({
      entries: [
        { find: 'react', replacement: 'preact/compat' },
        { find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
        { find: 'react-dom', replacement: 'preact/compat' },
        { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }
      ]
    })
  ]
};

在 Jest 中設定別名

Jest 允許重新寫入模組路徑,類似於套件管理工具。這些重新寫入會在你的 Jest 設定檔中使用正規表示法設定。

{
  "moduleNameMapper": {
    "^react$": "preact/compat",
    "^react-dom/test-utils$": "preact/test-utils",
    "^react-dom$": "preact/compat",
    "^react/jsx-runtime$": "preact/jsx-runtime"
  }
}

在 TypeScript 中設定別名

TypeScript 即使與套件管理工具一起使用,也有自己的類型解析程序。為了確保使用 Preact 的類型取代 React 的類型,你會希望在 tsconfig.json(或 jsconfig.json)中新增下列設定:

{
  "compilerOptions": {
    ...
    "skipLibCheck": true,
    "baseUrl": "./",
    "paths": {
      "react": ["./node_modules/preact/compat/"],
      "react-dom": ["./node_modules/preact/compat/"]
    }
  }
}

此外,您可能需要啟用 skipLibCheck,就像我們在上述範例中所做的一樣。某些 React 函式庫會使用 preact/compat 可能未提供的類型(儘管我們會盡力修正這些問題),因此,這些函式庫可能會導致 TypeScript 編譯錯誤。透過設定 skipLibCheck,您可以告訴 TS 它不需要對所有 .d.ts 檔案執行完整檢查(通常這些檔案僅限於 node_modules 中的函式庫),這將修正這些錯誤。

搭配 HTM 和 ImportMaps 使用 Preact

Import Map 是一項較新的功能,可讓您控制瀏覽器如何解析模組指定項,通常用於將 preact 等基本指定項轉換為 CDN URL,例如 https://esm.sh/preact。雖然許多人偏好 Import Maps 可提供的美學,但使用它們也有實際優點,例如更能控制模組解析(繼續閱讀以了解如何設定別名)以及解決從檔案複製 CDN URL 所帶來的負擔(以及可能的錯誤)。

以下為 Import Map 使用範例

<script type="importmap">
  {
    "imports": {
      "preact": "https://esm.sh/preact@10.19.2",
      "preact/": "https://esm.sh/preact@10.19.2/",
      "htm/preact": "https://esm.sh/htm@3.1.1/preact?external=preact"
    }
  }
</script>

<script type="module">
  import { render } from 'preact';
  import { useReducer } from 'preact/hooks';
  import { html } from 'htm/preact';

  export function App() {
    const [count, add] = useReducer((a, b) => a + b, 0);

    return html`
      <button onClick=${() => add(-1)}>Decrement</button>
      <input readonly size="4" value=${count} />
      <button onClick=${() => add(1)}>Increment</button>
    `;
  }

  render(html`<${App} />`, document.body);
</script>

注意:我們在上述範例中使用 ?external=preact,因為許多 CDN 會貼心地提供您要求的模組及其相依項。然而,這可能會讓 Preact 出錯,因為它(以及 React)預期會以單例方式載入(一次只有一個執行個體)。使用 ?external 會告訴 esm.sh 它不需要提供 preact 的副本,我們可以使用 Import Map 自行處理

您甚至可以使用 Import Maps 來支援別名

<script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/preact@10.19.2/compat",
      "react-dom": "https://esm.sh/preact@10.19.2/compat"
    }
  }
</script>