从JSDOC JavaScript迁移Azure函数到打字稿
#javascript #typescript #jsdoc #azurefunctions

我以前写过有关如何实施dynamic redirect mechanism for Azure Static Web Apps using Azure Functions的文章。我使用JSDOC JavaScript实施了此功能。从那以后,我将其迁移到Typescript,我认为分享该过程很有趣。

title image reading "Azure Static Web Apps: dynamic redirects with Azure Functions" with the Static Web Apps and Azure Functions logo

为什么要从JSDOC JavaScript迁移到打字稿?

正如普通读者所知道的那样,我既是打字稿的忠实拥护者,又是JSDOC JavaScript的忠实拥护者。我认为两者都很棒。那么,为什么要从JSDOC JavaScript迁移到打字稿呢?对我来说,这主要是关于开发人员的体验; JSDOC的详细性更大,并且更广泛的生态系统比JSDOC JavaScript所做的打字率要多得多。因此,当您超越简单应用程序时,至少对我来说,Typescript是一个更好的选择。

My blog是一个具有Azure函数后端的Azure Static Web App。我一直在使用JSDOC JavaScript来完成我的Azure功能。这篇文章将带来后端并将其迁移到打字稿。我已经有各种各样的能力,我不想沿途失去:

  • 我可以在VS代码中调试
  • 我使用github操作部署
  • 我使用开玩笑进行了自动测试

所有这些负担能力都可以通过打字稿提供,我想保留它们。让我们开始迁移。顺便说一下,此迁移的代码lies in this PR

迁移tsconfig.json

我们的tsconfig.json管理打字稿编译器与我们的代码交互的方式。我们将从迁移开始:

```d diff title =“ tsconfig.json”
{
“ compileroptions”:{

  • “ noemit”:true,
  • “ noemit”:false,
  • “ oftdir”:“ dist”,
  • “ rootdir”:“。”,
  • “ sourcemap”:true,

  • “ allyjs”:false,

  • “ checkjs”:false,

  • “ moduleresolution”:“ node”,
    }
    }

    
    

让我们看一下我们所做的更改:

  • 由于noEmit设置为false,我们现在从编译中发出文件。我们将不再实际运行我们编写的代码,但是我们将运行我们发出的JavaScript。
  • 我们正在指定distoutDir-这是我们编译的JavaScript发出的地方。
  • 我们正在指定.rootDir-这是我们的打字稿源文件的根。
  • 我们正在为发射的JavaScript文件创建源地图 - 这将有助于我们调试原始源代码。 (即使我们没有运行它。)
  • 由于将allowJs设置为false,我们不再允许JavaScript文件成为我们程序的一部分。 (而且,由于将checkJs设置为false,我们也不会检查它们 - 我怀疑这是隐式设置为false to allowJsfalse-要清楚,我已经指定了它。)
  • 我们正在指定nodemoduleResolution-这是打字稿将如何从给定模块指定器查找文件。

迁移package.json

要迁移我们的package.json,我们需要添加一些依赖项并调整我们的脚本:

“脚本”:{
“构建”:“ TSC”,

  • “观看”:“ TSC -W”,
  • “ prestart”:“ npm run build”, “开始”:“ func start”, “测试”:“ IS” },, “ devDectiencies”:{ “@azure/functions”:“^3.5.0”,
  • “@type/is”:“^29.2.5”,
  • “@type/node”:“^18.x”, “是”:“^29.3.1”,
  • “ ts-is”:“^29.1.0”, “打字稿”:“^5.0.0” } } ````````

我们正在添加两个脚本:

  • watch-这将观看我们的打字稿文件并在更改时重新编译它们 - 我们真的不需要;但这取决于您喜欢的工作流程。
  • prestart-这将在start之前运行,并确保我们的打字稿文件已编译,并且我们有最新的JavaScript运行。

在我们的devDependencies中,我们正在为jest and node.js添加依赖项。我们还添加了ts-jest,这将使我们能够运行用打字稿编写的开玩笑测试。

迁移.vscode/settings.json.vscode/tasks.json

我较早提到了调试 - 要使该调试到位,我们需要在.vscode文件夹中的settings.jsontasks.json文件上工作。首先是settings.json

```d diff title =“ settings .json”

  • “ azurefunctions.projectlanguage”:“ javascript”,
  • “ azurefunctions.projectlanguage”:“ typescript”, ````````

以上是自我解释的。我们正在将Azure功能项目的语言从JavaScript更改为打字稿。现在tasks.json

```d diff title =“ tasks.json”
{
“版本”:“ 2.0.0”,
“任务”:[

  • {
  • “ type”:“ shell”,
  • “ label”:“ npm build(functions)”,
  • “命令”:“ npm run构建”,
  • “ deverson”:“ npm install(functions)”,
  • “ QuessionMatcher”:“ $ tsc”,
  • “选项”:{
  • “ cwd”:“ $ {workspacefolder}/blog-website/api”
  • }, 这是给出的 } ````````

我们在这里有一个新的任务,可以运行我们的npm run build脚本。这将把我们的打字稿文件编译到JavaScript。我们还将cwd设置为blog-website/api-这是我们的Azure函数使用的文件夹 - 您自己可能会有所不同。除了这个新脚本外,现有任务有一些调整,以使其取决于我们的新构建任务:

```d diff title =“ tasks.json”
{
“版本”:“ 2.0.0”,
“任务”:[
{
“ type”:“ func”,
“ label”:“ func:主机开始”,
“命令”:“主机开始”,
“ QuessionMatcher”:“ $ func-node-watch”,
“ isbackground”:true,

  • “依赖森”:“ npm build(functions)”,
  • “选项”:{
  • “ cwd”:“ $ {workspacefolder}/blog-website/api”
  • } },, // ... { “ type”:“ shell”, “ label”:“ npm Prune(函数)”, “命令”:“ NPM Prune-生产”,
  • “依赖森”:“ npm构建(functions)”, “ QuessionMatcher”:[], “选项”: { “ cwd”:“ $ {workspacefolder}/blog-website/api” } } 这是给出的 } ````````

迁移我们的Azure功能

这将不会成为从JSDOC JavaScript迁移到打字稿的详尽指南。我将专注于发现与Azure功能最相关的内容。让我们从fallback/function.json文件开始,该文件为我们的动态重定向供电,并生活在/api/fallback

{
“绑定”:[
{
“ authlevel”:“匿名”,
“ type”:“ httptrigger”,
“方向”:“在”,
“名称”:“ req”,
“方法”:[“ get”,“ post”]
},
{
“ type”:“ http”,
“方向”:“ out”,
“名称”:“ res”
}
],

  • “ scriptfile”:“ ../ dist/fallback/index.js” } ````````

这里有一个增加,将scriptFile重新分配到编译的JavaScript。

现在让我们看一下该功能的代码。最初是名为index.js的JavaScript文件;必须将其重命名为index.ts。原始代码看起来像这样:

```js title =“ flastback/index.js”
const redirect = require('./ redirect');
const savetodatabase = require('./ savetodatabase');

/**
*

  • @param {import(“@azure/functions”)。上下文}上下文
  • @param {import(“@azure/functions”)。httprequest} req */ 异步函数afflack(context,req){ // ... }

module.exports = hallback;




After renaming to `index.ts` and adding some TypeScript types, it looks like this:



```ts title="fallback/index.ts"
import type { AzureFunction, Context, HttpRequest } from '@azure/functions';

import { redirect } from './redirect';
import { saveToDatabase } from './saveToDatabase';

const httpTrigger: AzureFunction = async function (
  context: Context,
  req: HttpRequest
): Promise<void> {
  //...
};

export default httpTrigger;

我们可以看到,导入的类型变得更加简洁。我们还将该功能导出为default而不是module.exports。这是因为我们使用ES模块而不是CommonJS模块进行创作。我们还可以看到,我们使用import而不是require来导入我们的功能。虽然CONCORJS更为简单,但ES模块的语法感觉更加更好。至少对我来说。 (值得注意的是,我们不在编译的JavaScript中使用ES模块 - 我们仍在使用CommonJ;但是当我们编写代码时,我们不需要考虑一下。)

我不会浏览其他文件,但是该过程是相同的。将文件重命名为.ts,添加打字稿类型,然后使用import而不是require

迁移我们的测试

我们现在几乎在家中;我们只需要迁移测试即可。让我们从jest.config.js开始:

```d diff title =“ jest.config.js”

  • 预设:'ts-stest',
  • TESTPATHIGNOREPATTERNS:['/node_modules/','/dist/'], ````````

我们正在添加ts-jestpreset,这将使我们能够运行打字稿测试。如果您还记得,我们较早添加了ts-jest依赖性;就是这样。

我们还将dist添加到我们的testPathIgnorePatterns-这是因为我们不想对我们编译的JavaScript进行测试 - 我们最终将两次运行测试。

让我们将注意力直接转移到测试上。同样,我们从.js.ts进行了经典的重命名,我们的进口变成了简短的ES模块Y:

```d diff title =“ redirect.test.ts”
- /**

  • * @typedef {import(“@azure/functions”)。logger} logger
  • */ +来自'@azure/functions'的导入类型{logger}; -const {描述,期望,测试} = require('@jest/globals'); +导入{描述,期望,测试}来自'@jest/globals'; -const redirect = require('./ redirect'); +来自'./redirect'的导入{redirect}; ````````

美丽。最后,我们对测试本身的代码进行了一些调整。首先,声明我们的模拟变得容易得多:

```d diff title =“ redirect.test.ts”
- / ** @Type {is.mock}*/ const ockklogger = is.fn();
+const ocorlogger:is.mock = is.fn();




Secondly, casting our mock to the type we want is much more straightforward:



```diff title="redirect.test.ts"
-/** @type {any} */ (mockLogger)
+mockLogger as unknown as Logger

我没有真实的方式如何在JSDOC中两次铸造 - 现在我不需要。

结论

我们现在有一个打字稿Azure函数代码库,并提供我们之前拥有的所有调试 /测试 /部署。我们不必在部署方面做任何事情,因为它只是效果。我希望这篇文章对您有用!