用 TypeScript 写 gulp 构建
我在项目中经常使用前端构建技术来生成网页需要脚本和样式表。多数时候是采用 gulp + webpack (babel-loader | ts-loader) 的方案,在 Node7 下运行甚至可以使用 async 语法——当然大部分都是配置,只在 gulpfile.js 里会有少量的脚本代码。
注:node7 在 7.6 以前需要
--harmony_async_await
来支持 async function 语法,但从 7.6 开始不再需要这个参数。
不过最近遇到一点麻烦,因为我们需要使用 gulp 来构建一堆文档。文档是用 Markdown 写的,需要构建成静态 HTML 页面。考虑过 Jekyll,但是团队里没有人用过。所以最终决定用 marked 来转换 Markdown,自己写脚本定制——gulp 里引入逻辑模块是很容易的事件,跟写 node 程序一样。
但是构建文档这个需求与之前的构建有很大不同。之前的构建几乎只需要配置,而这次需要写大量的业务代码,这就意味着产生 BUG 的风险大大增加。按惯例,业务逻辑我们通常会用 TypeScript 来写,TypeScript 的静态类型特性会在我们编写代码的时候(配合合适的编辑器,比如 VSCode)就检查不少问题出来,能大大降低产生 BUG 的风险。
我们初步的方案是,像其它前端脚本类似,用 TypeScript 写完了使用 tsc 转译成 JavaScript,再用 gulp 来运行 JavaScript 生成文档。方案虽然可行,但却将构建过程的复杂度增加了一倍。要是 Node 能直接运行 TypeScript 就好了……
用 Node 直接运行 TypeScript,有这种想法的人肯定不只我一个。而且之前也曾了解到 babel-register (或 "babel-core/register"
) 可以改变 Node 的 require
,在加载脚本的时候先对其进行转译。既然技术上是可行的,那就是找有没有现成的实现了。
通过 typescript node
关键字找到了 npm 上的 tyepscript-node 模块,而这个模块说明文档的第一句话就写着:
DEPRECATED: Use ts-node instead.
所以我们要找的实际上是 ts-node。它的文档中还专门提到创建 gulpfile.ts 文件,然后直接运行 gulp 就行。
为了试验 gulp 直接运行 TypeScript 脚本。先建了一个临时的 Node 项目目录,安装 gulp 模块。再建立一个 gulpfile.ts 测试文件,使用 TS 支持但 Node 不运行的 import 语法
import gulp = require("gulp");
gulp.task("default", () => {
console.log("hello, gulp with typescript");
});
然后运行(当前是Windows环境)。在没添加 ts-node 模块之前,运行结果会抛出一些错误
好吧,gulp 想得还是挺周到,居然尝试了 4 个 typescript node register 模块。其中 ts-node 是首先尝试的,且当它是 gulp 推荐的。typescript-node 已经申明用 ts-node 替代了。
现在我们安装 ts-node 模块,之后再运行一次
gulp 提示它使用了 ts-node 模块,不过因为没有安装 typescript 模块,所以运行失败。安装好 typescript 模块之后再试一次,
运行成功。
顺便提一下,如果不是构建应用,而是 Node Web 应用,需要注册 ts-node,它的文档中提供了两个方法
require("ts-node").register({ /* options */ });
上面这种方法可以加一些选项,这些选项并不是 tsconfig.js 中的选项,而是 ts-node 自己的一些选项,具体可以参考 ts-node 的文档。
而下面这种方法,似乎是一种快捷方式,但它只能使用默认选项(多数情况下默认选项足够)。
require('ts-node/register')
ts-node 会自己加载使用 tsconfig.json。
当然,直接运行 node 程序的时候,不像 gulp 内置了注册和启动过程,所以需要一个 JavaScript 的启动程序,假设是 start.js,它应该这样写
// start.js
require('ts-node/register');
require("app")
当然,还可以加一些其它逻辑在里面,比如在开发环境下注册 ts-node 运行 app.ts,而在生产环境下直接运行转译好的 app.js。
敬请 扫码 关注〔边城〕的公众号:边城客栈
更多建议: