如何基于 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 开发快应用;同时,为了做到开箱即用,有对模版做了加工优化处理;如果您有这方面诉求,可参考之。当然,也欢迎提出您宝贵的建议或意见。
但这种做法,也会存在问题。
存在问题
- @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.
- 还有四个小问题,Babel 团队也给出相应的解决方案:
1、Namespace
2、使用<newtype>x
语法转换类型
3、const 枚举
4、历史遗留风格的 import/export 语法
写在结尾
总结来看,方法都不十全十美,但也不是完全无法使用。ts-loader
做法可能使用的人更多。但是由于快应用的特殊性,在这里表现比较欠缺。babel-loader
做法就没有这个问题。而目前存在的问题,也可以通过其他工具和代码书写上的注意,来弥补和规避。
所以还是建议使用 Babel 的支持,来引入 ts 开发。当然如果可以抽离出单独的方法,又实在想看到编译时的提示,用 ts-loader 也没问题!您可以视自身需要而定。