推广 热搜: 京东  联通  iphone11  摄像头  企业存储  iPhone  XSKY  京东智能采购  网络安全  自动驾驶 

使用Yarn workspace,TypeScript,esbuild,React和Express构建 K8S 云原生应用(一)

   日期:2021-06-06     来源:51cto    作者:itcg    浏览:548    我要评论    

政府采购

本文将指导您使用 K8S ,Docker,Yarn workspace ,Typescript,esbuild,Express 和 React 来设置构建一个基本的云原生 Web 应用程序。在本教程的最后,您将拥有一个可完全构建和部署在 K8S 上的 Web 应用程序。

设置项目

该项目将被构造为 monorepo。 monorepo 的目标是提高模块之间共享的代码量,并更好地预测这些模块如何一起通信(例如在微服务架构中)。出于本练习的目的,我们将使结构保持简单:

app,它将代表我们的 React website。 server,它将使用 Express 服务我们的 app。 common,其中一些代码将在 app 和 server 之间共享。

设置项目之前的唯一要求是在机器上安装 yarn。 Yarn 与 npm 一样,是一个程序包管理器,但性能更好,功能也略多。您可以在官方文档中阅读有关如何安装它的更多信息。

Workspaces(工作区)

进入到要初始化项目的文件夹,然后通过您喜欢的终端执行以下步骤:

鸿蒙官方战略合作共建――HarmonyOS技术社区 使用 mkdir my-app 创建项目的文件夹(可以自由选择所需的名称)。 使用 cd my-app 进入文件夹。 使用 yarn init 初始化它。这将提示您创建初始 package.json 文件的相关问题(不用担心,一旦创建文件,您可以随时对其进行修改)。如果您不想使用 yarn init 命令,则始终可以手动创建文件,并将以下内容复制到其中: {   "name": "my-app",   "version": "1.0.0",   "license": "UNLICENSED",   "private": true // Required for yarn workspace to work } 

现在,已经创建了 package.json 文件,我们需要为我们的模块app,common 和 server 创建文件夹。为了方便 yarn workspace 发现模块并提高项目的可读性(readability),我们将模块嵌套在 packages 文件夹下:

my-app/ ├─ packages/ // 我们当前和将来的所有模块都将存在的地方 │  ├─ app/ │  ├─ common/ │  ├─ server/ ├─ package.json 

我们的每个模块都将充当一个小型且独立的项目,并且需要其自己的 package.json 来管理依赖项。要设置它们中的每一个,我们既可以使用 yarn init(在每个文件夹中),也可以手动创建文件(例如,通过 IDE)。

软件包名称使用的命名约定是在每个软件包之前都使用 @my-app     "target": "es2017",     "module": "CommonJS",     "lib": ["ESNext", "DOM"],           "moduleResolution": "node",     "esModuleInterop": true,           "baseUrl": "./",     "paths": {       "@flipcards     "jsx": "react",     "experimentalDecorators": true,     "resolveJsonModule": true   },   "exclude": ["node_modules", "**/node_modulespublic/script.js 

文件夹结构应如下所示:

my-app/ ├─ packages/ ├─ .gitignore ├─ package.json  添加代码

这部分将着重于将代码添加到我们的 common、app 和 server 包中。

Common

我们将从 common 开始,因为此包将由 app 和 server 使用。它的目标是提供共享的逻辑(shared logic)和变量(variables)。

文件

在本教程中,common 软件包将非常简单。首先,从添加新文件夹开始:

src/ 文件夹,包含包的代码。

创建此文件夹后,将以下文件添加到其中:

src/index.ts

export const APP_TITLE = 'my-app'; 

现在我们有一些要导出的代码,我们想告诉 Typescript 从其他包中导入它时在哪里寻找它。为此,我们将需要更新 package.json 文件:

package.json

{   "name": "@my-app/common",   "version": "0.1.0",   "license": "UNLICENSED",   "private": true,   "main": "./src/index.ts" // 添加这一行来为 TS 提供入口点 } 

我们现在已经完成了 common 包!

结构提醒:

common/ ├─ src/ │  ├─ index.ts ├─ package.json  App 依赖项

该 app 包将需要以下依赖项:

react react-dom

从项目的根目录运行:

yarn app add react react-dom yarn app add -D @types/react @types/react-dom (为 Typescript 添加类型typings)

package.json

{   "name": "@my-app/app",   "version": "0.1.0",   "license": "UNLICENSED",   "private": true,   "dependencies": {     "@my-app/common": "^0.1.0", // Notice that we've added this import manually     "react": "^17.0.1",     "react-dom": "^17.0.1"   },   "devDependencies": {     "@types/react": "^17.0.3",     "@types/react-dom": "^17.0.2"   } }  文件

要创建我们的 React 应用程序,我们将需要添加两个新文件夹:

一个 public/ 文件夹,它将保存基本 HTML 页面和我们的 assets。 一个 src/ 文件夹,其中包含我们应用程序的代码。

一旦创建了这两个文件夹,我们就可以开始添加 HTML 文件,该文件将成为我们应用程序的宿主。

public/index.html

         my-app                

cript>You need to enable Javascript to run this app.cript>

     

     

 

     

     

cript type="text/javascript" src="script.js">cript>

     

 现在我们有了要渲染的页面,我们可以通过添加下面的两个文件来实现非常基本但功能齐全的 React 应用程序。

src/index.tsx

import * as React from 'react'; import * as ReactDOM from 'react-dom';  import { App } from './App';  ReactDOM.render(, document.getElementById('root')); 

此代码从我们的 HTML 文件挂接到 root div 中,并将 React组件树 注入其中。

src/App.tsx

import { APP_TITLE } from '@flipcards/common'; import * as React from 'react';  export function App(): React.ReactElement {   const [count, setCount] = React.useState(0);    return (     

       

Welcome on {APP_TITLE}!

       

         This is the main page of our application where you can /confirm/i that it         is dynamic by clicking the button below.       

        

Current count: {count}

            

   ); } 

这个简单的 App 组件将呈现我们的应用标题和动态计数器。这将是我们的 React tree 的入口点。随意添加您想要的任何代码。

就是这样!我们已经完成了非常基本的 React 应用程序。目前它并没有太大的作用,但是我们总是可以稍后再使用它并添加更多功能。

结构提醒:

app/ ├─ public/ │  ├─ index.html ├─ src/ │  ├─ App.tsx │  ├─ index.tsx ├─ package.json  Server

依赖项

server 软件包将需要以下依赖项:

cors express

从项目的根目录运行:

yarn server add cors express yarn server add -D @types/cors @types/express(为 Typescript 添加类型typings)

package.json

{   "name": "@my-app/server",   "version": "0.1.0",   "license": "UNLICENSED",   "private": true,   "dependencies": {     "@my-app/common": "^0.1.0", // 请注意,我们已手动添加了此导入     "cors": "^2.8.5",     "express": "^4.17.1"   },   "devDependencies": {     "@types/cors": "^2.8.10",     "@types/express": "^4.17.11"   } }  文件

现在我们的 React 应用程序已经准备就绪,我们需要的最后一部分是服务器来为其提供服务。首先为其创建以下文件夹:

一个 src/ 文件夹,包含我们服务器的代码。

接下来,添加 server 的主文件:

src/index.ts

import { APP_TITLE } from '@flipcards/common'; import cors from 'cors'; import express from 'express'; import { join } from 'path';  const PORT = 3000;  const app = express(); app.use(cors());  // 服务来自 "public" 文件夹的静态资源(例如:当有图像要显示时) app.use(express.static(join(__dirname, '../../app/public')));  // 为 HTML 页面提供服务 app.get('*', (req: any, res: any) => {   res.sendFile(join(__dirname, '../../app/public', 'index.html')); });  app.listen(PORT, () => {   console.log(`${APP_TITLE}'s server listening at http://localhost:${PORT}`); }); 

这是一个非常基本的 Express 应用程序,但如果除了单页应用程序之外我们没有任何其他服务,那么这就足够了。

结构提醒:

server/ ├─ src/ │  ├─ index.ts ├─ package.json  构建应用

Bundlers(打包构建捆绑器)

为了将 Typescript 代码转换为可解释的 Javascript 代码,并将所有外部库打包到单个文件中,我们将使用打包工具。JS/TS 生态系统中有许多捆绑器,如 WebPack、Parcel 或 Rollup,但我们将选择 esbuild。与其他捆绑器相比,esbuild 自带了许多默认加载的特性(Typescript, React),并有巨大的性能提升(快了 100 倍)。如果你有兴趣了解更多,请花时间阅读作者的常见问题解答。

这些脚本将需要以下依赖项:

esbuild 是我们的捆绑器 ts-node 是 Typescript 的 REPL,我们将使用它来执行脚本

从项目的根目录运行:yarn add -D -W esbuild ts-node。

package.json

{   "name": "my-app",   "version": "1.0",   "license": "UNLICENSED",   "private": true,   "workspaces": ["packages interface BuildOptions {   env: 'production' | 'development'; }   export async function buildApp(options: BuildOptions) {   const { env } = options;    await build({     entryPoints: ['packages/app/src/index.tsx'], // 我们从这个入口点读 React 应用程序     outfile: 'packages/app/public/script.js', // 我们在 public/ 文件夹中输出一个文件(请记住,在 HTML 页面中使用了 "script.js")     define: {       'process.env.NODE_ENV': `"${env}"`, // 我们需要定义构建应用程序的 Node.js 环境     },     bundle: true,     minify: env === 'production',     sourcemap: env === 'development',   }); }   export async function buildServer(options: BuildOptions) {   const { env } = options;    await build({     entryPoints: ['packages/server/src/index.ts'],     outfile: 'packages/server/dist/index.js',     define: {       'process.env.NODE_ENV': `"${env}"`,     },     external: ['express'], // 有些库必须标记为外部库     platform: 'node', // 为 Node 构建时,我们需要为其设置环境     target: 'node14.15.5',     bundle: true,     minify: env === 'production',     sourcemap: env === 'development',   }); }   async function buildAll() {   await Promise.all([     buildApp({       env: 'production',     }),     buildServer({       env: 'production',     }),   ]); }  // 当我们从终端使用 ts-node 运行脚本时,将执行此方法 buildAll(); 

该代码很容易解释,但是如果您觉得遗漏了部分,可以查看 esbuild 的 API文档 以获取完整的关键字列表。

我们的构建脚本现已完成!我们需要做的最后一件事是在我们的 package.json 中添加一个新命令,以方便地运行构建操作。

{   "name": "my-app",   "version": "1.0",   "license": "UNLICENSED",   "private": true,   "workspaces": ["packages/*"],   "devDependencies": {     "esbuild": "^0.9.6",     "ts-node": "^9.1.1",     "typescript": "^4.2.3"   },   "scripts": {     "app": "yarn workspace @my-app/app",     "common": "yarn workspace @my-app/common",     "server": "yarn workspace @my-app/server",     "build": "ts-node ./scripts/build.ts" // Add this line here   } } 

现在,您可以在每次对项目进行更改时从项目的根文件夹运行 yarn build 来启动构建过程(如何添加hot-reloading,稍后讨论)。

结构提醒:

my-app/ ├─ packages/ ├─ scripts/ │  ├─ build.ts ├─ package.json ├─ tsconfig.json  Serve(提供服务)

我们的应用程序已经构建好并可以提供给全世界使用,我们只需要向 package.json 添加最后一个命令即可:

{   "name": "my-app",   "version": "1.0",   "license": "UNLICENSED",   "private": true,   "workspaces": ["packages/*"],   "devDependencies": {     "esbuild": "^0.9.6",     "ts-node": "^9.1.1",     "typescript": "^4.2.3"   },   "scripts": {     "app": "yarn workspace @my-app/app",     "common": "yarn workspace @my-app/common",     "server": "yarn workspace @my-app/server",     "build": "ts-node ./scripts/build.ts",     "serve": "node ./packages/server/dist/index.js" // Add this line here   } } 

由于我们现在正在处理纯 Javascript,因此可以使用 node 二进制文件启动服务器。因此,继续运行 yarn serve。

如果您查看控制台,您将看到服务器正在成功侦听。你也可以打开一个浏览器,导航到 http://localhost:3000 来显示你的 React 应用

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
0相关评论

头条阅读
推荐图文
相关资讯
网站首页  |  物流配送  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  RSS订阅  |  违规举报  |  京ICP备14047533号-2
Processed in 0.190 second(s), 11 queries, Memory 1.52 M