如何基于 Typescript 开发快应用

TypeScript是一种由微软开发的开源、跨平台的编程语言。它是 JavaScript 的超集,最终会被编译为 JavaScript 代码。用 TypeScript (以下简称 ts)做前端开发,时下正是火热。本篇文章即在于,探讨如何基于 TypeScript 来开发快应用

基于 ts-loader

众所周知,ts 是需要编译,才能运行到 js 引擎上,所以需要有工具来对其进行转换。webpack 已经有对其进行 loader 整合。而 hap-toolkit 是基于 webpack 上的封装,所以我们可以直接用起来。

安装依赖:

npm i -D typescript ts-loader
// OR
yarn add --dev typescript ts-loader

然后项目 src 里找一个位置,新建一份 ts 文件,写上点代码,在 ux 文件的 script 里引入这份 ts 文件

function greeter(person: string) {
  return "Hello, " + person;
}
let user = "Jane User";
console.log(greeter(user));

配置 tsconfig.json

接下来项目根路径新建一份 tsconfig.json 文件,写上:

{
  "include": [
    "src"
  ]
}

配置快应用

最后,在项目根路径新建一份 quickapp.config.js 文件,内容为如下:

module.exports = {
  webpack: {
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: [
            {
              loader: "ts-loader",
            },
          ],
        },
      ],
    },
  },
};

这样就可以引入 ts 语法(即告知打包工具,使用 ts-loader 对 .tsx 后缀文件进行解析)。编译的时候也会显示语法检测结果。

存在问题

  • 但这种做法有个问题,由于快应用调用系统底层能力,约定 @system@service 开头的模块,为系统接口。也就是意味着这部分依赖不会存在于前端代码。这里是 hap-toolkit 做了处理,自定义了 loader 来防止 webpack 对这种模块的搜索。因为该模块实际上不存在,所以必定会报错。即 ts-loader 处理不了这里模块,也会报告说找不到该模块的错。所以这里的 ts 文件无法使用系统 feature。

  • 可能大家也注意到了,这是外引用的 ts 文件。那么对于 ux 文件里的 script 代码,是不支持的。就算针对 script 代码,在 hap-toolkit 里增加 ts-loader 去处理,但由于问题一和 ts-loader 本身对于入口文件配置的特殊性,这部分也会报错。

基于 babel-loader

那么怎么更好地融入快应用呢?好在,Babel 与 Typescript “联姻”了。早在 2018 年,Babel 团队就宣布 Babel7 支持 Typescript。

可能早就有开发者注意到 @babel/preset-typescript ,它正是 Babel 里用来将 ts 语法转换成 js 的重要工具。其实两者是有共同点,都是把不同的代码编译成引擎可以解析的语法。那其中涉及的 AST 三步骤:解析、转译、生成,也是一样的。只是各自的规则不同而已。具体使用步骤如下:

安装依赖:

npm i -D @babel/preset-typescript
// OR
yarn add --dev @babel/preset-typescript

这个会顺带装上 @babel/plugin-transform-typescript 这个依赖。

配置 babel

接着配置 babel.config.js(项目根路径下,无则新建):

module.exports = {
  webpack: {
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: [
            {
              loader: "babel-loader",
              options: {
                cwd: __dirname,
              },
            },
          ],
        },
      ],
    },
  },
};

配置快应用

在项目根目录下新建 quickapp.config.js,做如下配置,告知 Webpack 使用哪些插件:

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["@babel/preset-typescript"],
    plugins: [
      "@babel/plugin-transform-modules-commonjs",
      "@babel/plugin-transform-typescript",
    ],
    babelrcRoots: [".", "node_modules"],
  };
};

这样就使得 script 内代码,和引用外部 ts 文件都可用 ts 语法,同时也可以使用 feature API。上面一系列操作是:首先快应用 ux 文件已经用上 Babel 去处理了。这里我们指定 Babel 转换规则,使其支持 ux 内的 script 代码用 ts 语法。然后在 quickapp.config.js 加上 webpack 的文件处理规则,指定引用的外部 ts 文件由 babel-loader 去处理。

这里有一个重要点就是,如此配置就可以使得使用 feature 接口不报错。原因在于:Babel 是个语法编译工具,只负责当前文件内容的编译。并不会像 webpack 那样会去遍历模块引用。我们先用 babel-loader 把代码给转译了,然后拦截里面对 feature 模块的请求。使得 Webpack 不会当它是个模块引用,就不会去对该模块进行搜索。这样就不会因为没有这个模块而报错。而 ts-loader 还会去校验模块存在与否,这就势必会报错了。

有在 Github 建立开源项目:Quickapp TypeScript Template,基于 babel-loader 方式,使得可以用 TypeScript 开发快应用;同时,为了做到开箱即用,有对模版做了加工优化处理;如果您有这方面诉求,可参考之。当然,也欢迎提出您宝贵的建议或意见。

但这种做法,也会存在问题。

存在问题

  1. @babel/plugin-transform-typescript明确表示,只转不检测。也就是 ts 类型错误,编译时候也不会报错打断。当然,快应用 IDE 已经支持 ts 语法检测。您使用它来开发,编译、打包报错,都可以看到。

这种编译校验分离还有个好处,就是如果用 ts-loader 来做这个事,编译前还要检测一番,自然会拖慢编译流程。既然是静态语法检测,那么应该在 coding 的时候就检测并给予提示修复。

This plugin adds support for the syntax used by the TypeScript programming language. However, this plugin does not add the ability to type-check the JavaScript passed to it. For that, you will need to install and set up TypeScript.

  1. 还有四个小问题,Babel 团队也给出相应的解决方案
    1、Namespace
    2、使用 <newtype>x 语法转换类型
    3、const 枚举
    4、历史遗留风格的 import/export 语法

写在结尾

总结来看,方法都不十全十美,但也不是完全无法使用。ts-loader 做法可能使用的人更多。但是由于快应用的特殊性,在这里表现比较欠缺。babel-loader 做法就没有这个问题。而目前存在的问题,也可以通过其他工具和代码书写上的注意,来弥补和规避。

所以还是建议使用 Babel 的支持,来引入 ts 开发。当然如果可以抽离出单独的方法,又实在想看到编译时的提示,用 ts-loader 也没问题!您可以视自身需要而定。

参考链接