开始使用
本指南帮助你开始运行,以使用 3 个流行选项开始开发 Preact 应用程序。如果你不熟悉 Preact,我们建议从 Vite 开始。
无构建工具路线
Preact 被打包后可直接在浏览器中使用,不需要任何构建或工具
以这种方式进行开发的主要缺点是缺少 JSX,这需要构建步骤。下一节中记录了 JSX 的一种符合人体工程学且性能良好的替代方案。
JSX 的替代方案
编写原始的
h
或
createElement
调用可能会很乏味。根据我们的经验,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>
提示: 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 支持。
提示: 这些决定都不必是最终决定,如果你改变主意,以后可以随时将它们添加到项目中或从中删除。
为开发做好准备
现在我们准备启动我们的应用程序。要启动开发服务器,请在新建的项目文件夹中运行以下命令
服务器启动后,它将打印一个本地开发 URL,以便在浏览器中打开。现在你可以开始编写你的应用程序代码了!
制作生产版本
总有一天你需要在某处部署你的应用程序。Vite 附带了一个方便的
build
命令,它将生成一个经过高度优化的生产版本。
完成后,你将拥有一个新的
dist/
文件夹,可以将其直接部署到服务器。
集成到现有管道
如果你已经设置了现有的工具管道,则很可能其中包括一个打包器。最流行的选择是 webpack 、 rollup 或 parcel 。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
在 Webpack 中别名化
要在 Webpack 中为任何包创建别名,你需要将
resolve.alias
部分添加到你的配置中。根据你使用的配置,此部分可能已经存在,但缺少 Preact 的别名。
在 Node 中别名化
在 Node 中运行时,捆绑器别名(Webpack、Rollup 等)将不起作用,如 NextJS 中所示。为了解决此问题,我们可以在
package.json
中直接使用别名
在 Parcel 中别名化
Parcel 使用标准
package.json
文件在
alias
键下读取配置选项。
在 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 中使用别名
将 Preact 与 HTM 和 ImportMaps 一起使用
Import Map
是一项较新的功能,允许你控制浏览器如何解析模块说明符,通常将裸说明符(如
preact
)转换为 CDN URL(如
https://esm.sh/preact
)。虽然许多人更喜欢导入映射可以提供的审美效果,但使用它们也有实际好处,例如对模块解析有更多控制(继续阅读以了解如何使用别名)以及解决从文件到文件复制 CDN URL 带来的负担(以及可能的错误)。
以下是在使用中导入映射的示例
<script type="importmap">
"imports": {
"preact": "https://esm.sh/[email protected]",
"preact/": "https://esm.sh/[email protected]/",
"htm/preact": "https://esm.sh/[email protected]/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)希望被加载为单例(一次仅激活 1 个实例)。使用?external
告诉esm.sh
它不需要提供preact
的副本,我们可以使用我们的导入映射自己处理它
你甚至可以使用导入映射来支持别名
<script type="importmap">