如何使用Gulp构建TypeScript

转载地址

如何使用Gulp构建TypeScript

1、创建目录
选择一个你认为适合开发项目的目录,然后参考下面创建项目目录

mkdir typescript_demo && ce typescript_demo

2、npm初始化项目
进入的项目目录后,执行

npm init -y

3、安装依赖库

npm install gulp-cli gulp typescript gulp-typescript --save-dev

gulp-typescript是TypeScript的一个Gulp插件。

4、配置项目

4.1、在项目目录下面创建目录src和dist
src目录用来存储原始的文件也即是这里的.ts文件,dist用来存放编辑后的文件。
在src目录下添加main.ts文件,内容如下

function hello(compiler: string) {
    console.log(`Hello from ${compiler}`);
}
hello("TypeScript");

4.2、在项目目录下新建一个tsconfig.json文件,配置内容如下

{
    "files": [
        "src/main.ts"
    ],
    "compilerOptions": {
        "noImplicitAny": true,
        "target": "es5"
    }
}

4.3、在项目目录下新建一个gulpfile.js文件,配置内容如下

const gulp = require("gulp");
const ts = require("gulp-typescript");
const tsProject = ts.createProject("tsconfig.json");

gulp.task("default", function () {
  return tsProject.src()
    .pipe(tsProject())
    .js.pipe(gulp.dest("dist"));
});

4.4、试试gulp是否起作用,执行如下

npx gulp

得到类似如下的输出

[13:29:14] Using gulpfile ~/nodejs/typescript_demo/gulpfile.js
[13:29:14] Starting 'default'...
[13:29:15] Finished 'default' after 1.52 s

查看下dist目录下是否生成了一个main.js文件
执行如下命令 确保代码运行正常

node dist/main.js

执行后输出类似如下结果

Hello from TypeScript

4.5、配置package.json
修改package.json中main对一个的值,如下

"main": "./dist/mian.js",

如果有其他想要的修改的话,可以继续修改其他符合自己需求的项

5、模块添加
创建文件src/greet.ts文件,内容如下

export function sayHello(name: string) {
    return `Hello from ${name}`;
}

然后在src/main.ts代码中调用,修改后结果如下

import { sayHello } from './greet';

console.log(sayHello("TypeScript"));

最后,将src/greet.ts添加到tsconfig.json,结果如下

{
    "files": [
        "src/main.ts",
        "src/greet.ts"
    ],
    "compilerOptions": {
        "noImplicitAny": true,
        "target": "es5"
    }
}

通过gulp编译代码

npx gulp

得到类似如下的输出

[13:38:59] Using gulpfile ~/nodejs/typescript_demo/gulpfile.js
[13:38:59] Starting 'default'...
[13:39:01] Finished 'default' after 1.6 s

执行如下命令 确保代码运行正常

node dist/main.js

执行后输出类似如下结果

Hello from TypeScript

6、Browserify

注意,即使我们使用了ES2015的模块语法,TypeScript还是会生成Node.js使用的CommonJS模块。 我们在这个教程里会一直使用CommonJS模块,但是你可以通过修改 module选项来改变这个行为。

现在,让我们把这个工程由Node.js环境移到浏览器环境里。 因此,我们将把所有模块捆绑成一个JavaScript文件。 所幸,这正是Browserify要做的事情。 更方便的是,它支持Node.js的CommonJS模块,这也正是TypeScript默认生成的类型。 也就是说TypeScript和Node.js的设置不需要改变就可以移植到浏览器里。

首先,安装Browserify,tsify和vinyl-source-stream。 tsify是Browserify的一个插件,就像gulp-typescript一样,它能够访问TypeScript编译器。 vinyl-source-stream会将Browserify的输出文件适配成gulp能够解析的格式,它叫做 vinyl。
安装命令如下

npm install browserify tsify vinyl-source-stream --save-dev

6.1、在src目录下新建一个index.html文件,内容如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Hello World!</title>
    </head>
    <body>
        <p id="greeting">Loading ...</p>
        <script src="bundle.js"></script>
    </body>
</html>

6.2、修改main.ts文件,修改后内容如下

import { sayHello } from "./greet";

function showHello(idName: string, name: string) {
    const elt = document.getElementById(idName);
    elt.innerText = sayHello(name);
}

showHello("greeting", "TypeScript");

调用sayHello函数更改页面上段落的文字
6.3、配置gulpfile.js,修改后内容如下

const gulp = require("gulp");
const browserify = require("browserify");
const source = require('vinyl-source-stream');
const tsify = require("tsify");
const paths = {
  pages: ['src/*.html']
};

gulp.task("copy-html", function () {
  return gulp.src(paths.pages)
    .pipe(gulp.dest("dist"));
})

gulp.task("browserify", function() {
  return browserify({
      basedir: '.',
      debug: true,
      entries: ['src/main.ts'],
      cache: {},
      packageCache: {}
    })
    .plugin(tsify)
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest("dist"));
})

gulp.task("default", gulp.series('copy-html', 'browserify'));

这里的gulp配置可能与以往的不同,需要稍加注意下,这里使用的是gulp@4.0.0这个版本
这里增加了copy-html任务并且把它加作default的依赖项。 这样,当 default执行时,copy-html会被首先执行。 我们还修改了 default任务,让它使用tsify插件调用Browserify,而不是gulp-typescript。 方便的是,两者传递相同的参数对象到TypeScript编译器。

调用bundle后,我们使用source(vinyl-source-stream的别名)输出文件命名为bundle.js。

测试此页面,运行npx gulp,然后在浏览器里打开dist/index.html。 你应该能在页面上看到“Hello from TypeScript”。

注意,我们为Broswerify指定了debug: true。 这会让 tsify在输出文件里生成source maps。 source maps允许我们在浏览器中直接调试TypeScript源码,而不是在合并后的JavaScript文件上调试。 你要打开调试器并在 main.ts里打一个断点,看看source maps是否能工作。 当你刷新页面时,代码会停在断点处,从而你就能够调试 greet.ts。

7、Watchify、Babel和Uglify
现在代码已经用Browserify和tsify捆绑在一起了,还可以使用Browserify插件为构建添加一些新的特性。

Watchify启动Gulp并保持运行状态,当你保存文件时自动编译。 帮你进入到编辑-保存-刷新浏览器的循环中。

Babel是个十分灵活的编译器,将ES2015及以上版本的代码转换成ES5和ES3。 你可以添加大量自定义的TypeScript目前不支持的转换器。

Uglify帮你压缩代码,将花费更少的时间去下载它们。

7.1、Watchify
启动Watchify,让它在后台帮我们编译:

npm install watchify gulp-util --save-dev

修改gulpfile.js文件,修改后内容如下:

const gulp = require("gulp");
const browserify = require("browserify");
const source = require('vinyl-source-stream');
const tsify = require("tsify");
const watchify = require("watchify");
const gutil = require("gulp-util");
const paths = {
  pages: ['src/*.html']
};

const watchedBrowserify = watchify(browserify({
  basedir: '.',
  debug: true,
  entries: ['src/main.ts'],
  cache: {},
  packageCache: {}
}).plugin(tsify));

gulp.task("copy-html", function () {
  return gulp.src(paths.pages)
    .pipe(gulp.dest("dist"));
})

function browserifyBundle() {
  return watchedBrowserify
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest("dist"));
}

gulp.task("browserify", function() {
  return browserifyBundle();
})

gulp.task("default", gulp.series('copy-html', 'browserify'));
watchedBrowserify.on("update", browserifyBundle);
watchedBrowserify.on("log", gutil.log);

共有三处改变,但是需要你略微重构一下代码。

  1. 将browserify实例包裹在watchify的调用里,控制生成的结果。
  2. 调用watchedBrowserify.on("update", bundle)每次TypeScript文件改变时Browserify会执行bundle函数。
  3. 调用watchedBrowserify.on("log", gutil.log);将日志打印到控制台。

(1)和(2)在一起意味着我们要将browserify调用移出default任务。 然后给函数起个名字,因为Watchify和Gulp都要调用它。 (3)是可选的,但是对于调试来讲很有用。

现在当你执行gulp,它会启动并保持运行状态。 试着改变 main.ts文件里showHello的代码并保存。 你会看到这样的输出:

7.2、Uglify
首先安装Uglify。 因为Uglify是用于混淆你的代码,所以我们还要安装vinyl-buffer和gulp-sourcemaps来支持sourcemaps。

npm install gulp-uglify vinyl-buffer gulp-sourcemaps --save-dev

修改gulpfile.js文件,修改后内容如下

const gulp = require("gulp");
const browserify = require("browserify");
const source = require('vinyl-source-stream');
const tsify = require("tsify");
const watchify = require("watchify");
const gutil = require("gulp-util");
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');
const buffer = require('vinyl-buffer');
const paths = {
  pages: ['src/*.html']
};

const watchedBrowserify = watchify(browserify({
  basedir: '.',
  debug: true,
  entries: ['src/main.ts'],
  cache: {},
  packageCache: {}
}).plugin(tsify));

gulp.task("copy-html", function () {
  return gulp.src(paths.pages)
    .pipe(gulp.dest("dist"));
})

function browserifyBundle() {
  return watchedBrowserify
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({
      loadMaps: true
    }))
    .pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest("dist"));
}

gulp.task("browserify", function() {
  return browserifyBundle();
})

gulp.task("default", gulp.series('copy-html', 'browserify'));
watchedBrowserify.on("update", browserifyBundle);
watchedBrowserify.on("log", gutil.log);

注意uglify只是调用了自己。buffer和sourcemaps的调用是用于确保sourcemaps可以工作。 这些调用让我们可以使用单独的sourcemap文件,而不是之前的内嵌的sourcemaps。 你现在可以执行 gulp来检查bundle.js是否被压缩了:

7.3、Babel
首先安装Babelify和ES2015的Babel预置程序。 和Uglify一样,Babelify也会混淆代码,因此我们也需要vinyl-buffer和gulp-sourcemaps。 默认情况下Babelify只会处理扩展名为 .js,.es,.es6和.jsx的文件,因此我们需要添加.ts扩展名到Babelify选项。

npm install babelify babel-core babel-preset-env vinyl-buffer gulp-sourcemaps --save-dev

修改gulpfile.js文件,修改后内容如下:

const gulp = require("gulp");
const browserify = require("browserify");
const source = require('vinyl-source-stream');
const tsify = require("tsify");
const watchify = require("watchify");
const gutil = require("gulp-util");
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');
const buffer = require('vinyl-buffer');
const paths = {
  pages: ['src/*.html']
};

const watchedBrowserify = watchify(browserify({
  basedir: '.',
  debug: true,
  entries: ['src/main.ts'],
  cache: {},
  packageCache: {}
}).plugin(tsify));

gulp.task("copy-html", function () {
  return gulp.src(paths.pages)
    .pipe(gulp.dest("dist"));
})

function browserifyBundle() {
  return watchedBrowserify
    .transform('babelify', {
      presets: ['env'],
      extensions: ['.ts']
    })
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({
      loadMaps: true
    }))
    .pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest("dist"));
}

gulp.task("browserify", function () {
  return browserifyBundle();
})

gulp.task("default", gulp.series('copy-html', 'browserify'));
watchedBrowserify.on("update", browserifyBundle);
watchedBrowserify.on("log", gutil.log);

我们需要设置TypeScript目标为ES2015。 Babel稍后会从TypeScript生成的ES2015代码中生成ES5。 修改 tsconfig.json:

{
    "files": [
        "src/*.ts"
    ],
    "compilerOptions": {
        "noImplicitAny": true,
        "target": "es2015"
    }
}

对于这样一段简单的代码来说,Babel的ES5输出应该和TypeScript的输出相似。

实践项目地址

https://github.com/durban89/typescript_demo.git
tag: 1.0.2
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学...
    依依玖玥阅读 3,118评论 7 55
  • 请务必理解如下章节后阅读此章节: 安装 Node 和 gulp 访问论坛获取帮助 压缩 js 代码可降低 js 文...
    无名小码农阅读 1,123评论 0 2
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,385评论 1 32
  • 1、gulp的安装 首先确保你已经正确安装了nodejs环境。然后以全局方式安装gulp: npm install...
    F_imok阅读 2,300评论 1 11
  • PHP性能问题具体分析 工具:XHProf-性能分析扩展工具ab-压力测试vld-opcode代码分析 PHP性能...
    snakeSkin阅读 148评论 0 0