如何基于 Typescript 开发快应用

快应用 Jul 29, 2020

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 也没问题!您可以视自身需要而定。

参考链接

vivo developer

快应用引擎、工具开发者、快应用生态拓展达人(vivo)。

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.