用Vite创建TypeScript React应用程序

784 阅读9分钟

前端应用程序正变得越来越大,越来越复杂。一个React应用有数百甚至数千个组件的情况并不罕见。随着项目规模的增加,构建时间变得越来越重要。在大型项目中,你可能需要等待长达1分钟的时间来翻译代码并捆绑到浏览器中运行的生产包。对于这些项目,开发服务器的编译和加载时间也是一个大问题。代码的变化可能在几秒钟后才在浏览器中显示出来。这些等待时间已经成为减缓开发速度的瓶颈。

Vite通过提供一个开发服务器和一个快如闪电的构建命令来解决这个问题。Vite,发音为/vit/ ,是法语 "快速 "的意思,这个名字描述了这个工具的目标。构建命令在引擎盖下使用Rollup,它被预先配置为创建高度优化的代码。开发服务器利用了浏览器对ES模块的支持。热模块替换将立即把任何代码库的变化加载到浏览器中。

Vite最初是为Vue开发的,但你也可以开箱即用地创建React和Svelte项目。在本教程中,我将向你展示如何使用Vite创建一个基于TypeScript的React应用程序。该应用将是一个简单的数字转换工具,将十进制数字转换为十六进制和二进制。除了熟悉JavaScript之外,我不会假设任何先前的知识。

先决条件

目录

使用Vite创建TypeScript React应用程序

在你开始之前,你应该在你的系统上安装最新版本的Node和npm。第一步是使用Vite命令来创建一个新的应用程序。这可以使用npm init 命令来完成,不需要安装任何额外的软件。在你选择的文件夹中打开一个终端,运行以下命令。

npm init vite@latest vite-number-conversion -- --template react-ts

如果你使用的是旧版本的npm (低于第7版),你需要稍微修改该命令。

npm init vite@2.8.0 vite-number-conversion --template react-ts

该命令将生成一个新的文件夹vite-number-conversion ,并用react-ts 模板对其进行初始化。如果你被要求同意安装create-vite 包,只需回答是。这个模板使用TypeScript创建一个React项目,以及开发和构建项目所需的所有工具配置。接下来,导航到新的项目文件夹,运行下面的命令来安装所有的依赖项。

npm install

你将使用React Router来管理单页应用程序的导航。运行下面的命令来安装额外的依赖项。

npm install -E react-router-dom@5.3.0 @types/react-router-dom@5.3.3

现在在项目文件夹中打开你喜欢的IDE。随意浏览一下,熟悉一下Vite生成的代码。如果你熟悉create-react-app ,你会发现表面上的差异并不大。有一个Vite专用的配置文件,vite.config.ts ,可以调整Vite的行为。现在,让它保持原样,但我们以后会回到这个文件。

你的React组件被保存为.tsx 文件,在src/ 文件夹中。为了使事情有条理,创建一个新的文件夹src/components ,并添加一个新的文件src/components/Home.tsx 。这将是显示应用程序主页的组件。将以下内容粘贴到该文件中。

function Home() {
    return <div>
        <h1>Number Converter</h1>
    </div>
}

export default Home;

接下来,创建包含数字转换工具的组件。创建另一个文件src/components/Converter.tsx ,内容如下。

import { useState } from 'react';

function Converter() {
    const [value, setValue] = useState<number>();
    const [origin, setOrigin] = useState<string>();
    const isDisabled = (base: string) => (origin !== undefined && origin !== base);
    
    const updateValue = (baseName: string, base: number) => 
        (e: React.ChangeEvent<HTMLInputElement>) => {
            if (e.target.value === "") {
                setValue((oldValue) => undefined);
                setOrigin((oldOrigin) => undefined);
            } else {
                setValue((oldValue) => {
                    const newValue = parseInt(e.target.value, base);
                    return isNaN(newValue) ? oldValue : newValue;
                });
                setOrigin((oldOrigin) => baseName);
            }
        }

    return <div className="Converter">
        <label>
            Decimal:
            <input type="string" 
                value={value?.toString(10) || ""}
                name="decimal" 
                onChange={updateValue("decimal", 10)} 
                disabled={isDisabled("decimal")}/>
        </label>
        <label>
            Hexadecimal:
            <input type="string" 
                value={value?.toString(16) || ""}
                name="hex" 
                onChange={updateValue("hex", 16)} 
                disabled={isDisabled("hex")}/>
        </label>
        <label>
            Binary:
            <input type="string" 
                value={value?.toString(2) || ""}
                name="binary" 
                onChange={updateValue("binary", 2)} 
                disabled={isDisabled("binary")}/>
        </label>
    </div>
}

export default Converter;

Converter 组件包含三个输入字段,一个是十进制值,一个是十六进制值,还有一个是二进制值。它还使用了两个状态变量。value 包含应被转换为不同格式的数字,origin 包括用户已输入数字的输入字段的名称。我们的想法是禁用用转换后的数值自动填充的输入元素--isDisabled() 回调控制哪些元素被禁用。

updateValue() 这个函数有点儿棘手。它是一个返回回调的函数,配置有输入字段的名称和数字基数。回调接收ChangeEvent ,并根据输入字段的值更新组件的状态。在函数式编程风格中,像updateValue() 这样的高阶函数可以提供一种机制来实现可配置的代码,而不产生代码的重复性。

接下来,打开src/main.tsx ,将Router添加到应用程序中。在文件的顶部,添加以下导入。

import { BrowserRouter } from 'react-router-dom';

然后,修改渲染函数,使其看起来像下面的代码。

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
)

为了将路由添加到应用程序中,打开src/App.tsx ,用以下代码替换其内容。

import './App.css'
import { Link, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import Converter from './components/Converter';

function App() {
  return (
    <div className="App">
      <nav>
        <div className="menu">
          <Link to="/">Home</Link>
          <Link to="/converter">Converter</Link>
        </div>
      </nav>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/converter" component={Converter} />
      </Switch>
    </div>
  )
}

export default App

该应用程序已基本完成,但它需要一些样式。打开src/App.css ,并编辑它以符合下面的CSS。

.App {
  text-align: center;
}

.App nav {
  display: flex;
  justify-content: space-between;
  background-color: #333333;
  color: #ffffff;
  padding: 0.5rem 1rem;
}

.App nav a {
  color: #ffffff;
  text-decoration: none;
  margin-left: 1rem;
  margin-right: 1rem;
}

.Converter {
  text-align: left;
  margin: 1rem 4rem;
}

.Converter label {
  display: block;
  margin-bottom: 1rem;
}

.Converter input {
  display: block;
  margin-top: 0.5rem;
}

启动它并观察它的运行

现在,有趣的事情开始了!你已经准备好启动该应用程序了。在项目文件夹中打开终端,运行以下命令。

npm run dev

如果你习惯于用create-react-app 构建的React应用程序,你可能期望在开发服务器启动之前等待几秒钟。使用Vite,我在不到一秒钟的时间内就看到了下面的信息。

  vite v2.8.4 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 461ms.

现在你可以在http://localhost:3000/ ,打开你的浏览器,测试应用程序。当我点击导航栏中的转换器链接时,我看到了这样的内容。

The number conversion utility

我在Chrome浏览器中打开了开发者工具,以了解Vite如何实现这些快速启动时间。当你打开网络标签并按JS请求过滤时,你会看到许多对单个JavaScript源的请求。你甚至会看到你刚刚编辑的.tsx 源。

Vite development server under the hood.

然后我仔细观察了App.tsx, ,看到了上图所示的情况。当开发服务器被要求提供一个.tsx 文件时,它将在运行中把它编译成与浏览器兼容的代码。但它会保留所有的import 语句,并使用较新的浏览器中对ES模块的支持。这样一来,捆绑阶段就被取消了,加载时间也大大减少。

用Okta向应用程序添加认证

一个安全的应用程序需要用户认证,以防止未经授权的用户进入限制区域。有了Okta,只需几个步骤就可以轻松地将认证添加到您的Vite应用程序。

在你开始之前,你需要一个免费的Okta开发者账户。安装Okta CLI并运行okta register ,注册一个新账户。如果你已经有一个账户,运行okta login 。然后,运行okta apps create 。选择默认的应用程序名称,或根据你的需要进行更改。 选择单页应用程序,然后按回车键

在重定向URI中使用http://localhost:3000/callback ,并将注销重定向URI设置为http://localhost:3000

Okta CLI是做什么的?

Okta CLI将在您的Okta机构中创建一个OIDC单页应用。它将添加您指定的重定向URI并授予Everyone组的访问权限。它还会为http://localhost:3000 添加一个受信任的来源。当它完成时,你会看到如下的输出。

Okta application configuration:
Issuer:    https://dev-133337.okta.com/oauth2/default
Client ID: 0oab8eb55Kb9jdMIr5d6

注意:你也可以使用Okta管理控制台来创建你的应用程序。更多信息请参见创建一个React应用程序

现在你已经准备好将Okta的React库添加到你的项目中。在项目文件夹中打开终端,运行以下命令。

npm install -E @okta/okta-react@6.4.2 @okta/okta-auth-js@6.1.0

Vite需要一些帮助来解决Okta库使用的导入别名。为了使事情顺利进行,打开vite.config.ts ,在配置对象中添加以下条目。

resolve: {
  alias: [
    {
      find: "@okta/okta-auth-js",
      replacement: require.resolve("@okta/okta-auth-js/dist/okta-auth-js.umd.js"),
    },
  ],
}

如果你的IDE或构建不能解决require ,你可能需要为require 方法添加@types/node 库。在终端中,通过运行以下命令添加该库。

npm i –save-dev @types/node

现在,打开src/main.tsx ,紧接着在import 语句后添加以下代码。

import { Security } from '@okta/okta-react';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';

const oktaAuth = new OktaAuth({
  issuer: `/oauth2/default`,
  clientId: '{yourClientID}',
  redirectUri: `${window.location.origin}/callback`,
});

function restoreOriginalUri(oktaAuth: OktaAuth, originalUri: string) {
  window.location.replace(
    toRelativeUrl(originalUri || "/", window.location.origin)
  );
}

这里{yourClientID} 是你之前获得的客户ID,{yourOktaDomain} 是你的Okta域。接下来,用Security 组件包围BrowserRouter ,传入oktaAuthrestoreOriginalUri 作为参数。对渲染函数的调用应该看起来像这样。

ReactDOM.render(
  <React.StrictMode>
    <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Security>
  </React.StrictMode>,
  document.getElementById('root')
)

现在你已经使OktaAuth 对象对你的应用程序可用,你已经准备好创建一个安全路由并配置登录过程。打开src/App.tsx ,添加以下导入。

import { LoginCallback, SecureRoute } from '@okta/okta-react';

最后,将服务于Converter 组件的路由转换为安全路由,并添加另一个路由来处理Okta的登录回调。Switch 组件内的代码应该类似于下面的代码。

<Switch>
  <Route exact path="/" component={Home} />
  <SecureRoute path="/converter" component={Converter} />
  <Route path="/callback" component={LoginCallback} />
</Switch>

恭喜你,你已经准备好再次启动应用程序了。如果它仍然没有运行,在终端运行下面的命令。

npm run dev

现在,每当你导航到转换器路线时,应用程序就会检查你是否经过认证。如果没有,它将把你重定向到Okta登录页面,你可以在那里输入你的用户凭证。成功登录后,你就可以访问你所要求的应用程序页面。

了解更多关于React、TypeScript和Okta的信息

在本教程中,我指导你使用Vite创建一个TypeScript React应用程序。Vite是一个快如闪电的开发服务器和软件包捆绑器,利用现代ES模块浏览器支持和热模块替换--在代码库发生变化后加快刷新时间,可以显著提高开发效率。

作为一个例子,我向你展示了如何实现一个数字转换工具,在十进制、十六进制和二进制格式之间进行转换。该应用程序使用Okta认证来保证安全,你已经看到了这是如何在短短几行代码中实现的。