javascript - Gulp Typescript + Browserify;捆绑的 sourcemap 指向转译的 JS 而不是源 TS

标签 javascript typescript gulp browserify source-maps

我正在开发一个 Typescript 项目,该项目被转译为 ES5 JS,然后通过 browserify 运行以创建单个 .js 包和源映射。捆绑的源映射指向转译后的 JS 而不是 源 TS,即使我生成的源映射在转译为 JS 时正确指向源 TS。

就好像 browserify 忽略了指向 TS 代码的现有源映射,并创建了自己的新映射到已转换的 JS 代码。

这是我的 gulp 任务供引用——代码被编译到一个临时文件夹,然后从那里浏览。这使用 browserify-incremental 来支持增量编译。

谢谢!

注意:通过其他 SO 问题,我已经尝试使用 tsify,据我所知,它不适用于我的项目,因为我们使用导入语法和 commonjs,它报告 tsc 和 gulp-typescript 没有的编译问题(无论是通过 gulp 还是通过 CLI 使用,都会出现相同的错误)。我也试过 minifyify 但它没有解决问题。

var gulp        = require('gulp'),
  ts          = require('gulp-typescript'),
  browserify = require('browserify'),
  browserifyInc = require('browserify-incremental'),
  source      = require('vinyl-source-stream'),
  del         = require('del'),
  sourcemaps  = require('gulp-sourcemaps'),
  buffer = require('vinyl-buffer'),
  xtend = require('xtend');

var tsProject = ts.createProject('tsconfig.json');

//COMPILE TS
gulp.task('compileTs', function () {
  var sourceTsFiles = [config.src.tsFiles, config.src.tsTypes];

  var tsResult = gulp.src(sourceTsFiles)
    .pipe(sourcemaps.init())
    .pipe(ts(tsProject));

  return tsResult.js
    .pipe(sourcemaps.write('.', {
      //includeContent: false,
      //sourceRoot: "../../src/js/"
    }))
    .pipe(gulp.dest(config.tempDir));
});

//BUNDLE BUILT TS->JS
gulp.task('bundleJs', [], function () {
  var b = browserify(xtend(browserifyInc.args, {
    entries: config.tempDir + '/main.js',
    extensions: ['.js', '.jsx'],
    debug: true
  }));

  browserifyInc(b,  {cacheFile: config.tempDir + '/browserify-cache.json'});

  return b.bundle()
  .pipe(source('main.js'))
  .pipe(buffer())
  .pipe(sourcemaps.init({ loadMaps: true }))
  .pipe(sourcemaps.write('.'))
  .pipe(gulp.dest(config.dest.jsDir));
});

最佳答案

简答

compileTs 任务中,您需要将源映射写入输出 .js 文件,而不是专用的 .map 文件。您还需要将 includeContent 设置为 true,并指定正确的 sourceRoot

然后在 bundleJs 任务中,让 browserify debug 为 true 就足以生成 sourcemaps。

更多详情

有些包没有向 bundle 任务中的 sourcemaps 实用程序提供必要的源数据。幸运的是 sourcemaps 可以重新读取 .ts 文件。要使恢复步骤生效,它需要正确的文件路径,这就是为什么 TypeScript 编译任务中正确的 sourceRoot 如此重要的原因。

这里似乎还有其他陷阱。例如,如果您在 TypeScript 编译任务中将 sourcemaps 写入专用的 .map 文件,则稍后 bundle 任务将生成指向已编译的 .js 文件的 sourcemaps。因此,编译任务将源映射嵌入到实际的 .js 文件中同样至关重要。

如果 browserify 的 debug 标志为真,它将生成 sourcemaps。此处额外的 gulp-sourcemaps 分层有一个错误的交互,应该被删除。

现实生活中的实例

目录结构

proj
    /ts
        /def
            my-declarations.d.ts
        /src
            my-sources.ts
        /tmp
            temp-files-get-created-here-by-gulp.js
        tsconfig.json
    /web
        /static
            /js
                final-result-goes-here.js
    gulpfile.js
    package.json

tsconfig.json

{
    "compilerOptions": {
        "noImplicitAny": true,
        "removeComments": true,
        "declaration": false,
        "jsx": "React",
        "target": "ES5",
        "module": "CommonJS"
    },
    "exclude": [
        "tmp"
    ]
}

package.json

{
  "name": "my-awesome-project",
  "version": "0.1.0",
  "devDependencies": {
    "browserify": "^13.0.1",
    "gulp": "^3.9.1",
    "gulp-sourcemaps": "^1.6.0",
    "gulp-typescript": "^2.13.6",
    "gulp-uglify": "^1.5.3",
    "gulp-util": "^3.0.7",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0"
  }
}

gulp文件.js

var path = require('path');
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var gutil = require('gulp-util');
var ts = require('gulp-typescript');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify');

var debug = false;

var paths = {
    tsConfig: 'ts/tsconfig.json',
    scriptsSrc: ['ts/def/**/*.ts', 'ts/src/**/*.ts', 'ts/src/**/*.tsx'],
    scriptsDst: 'web/static/js',
    outDev: 'bundle.dev.js',
    outFinal: 'bundle.js',
    tempDst: 'ts/tmp',
    entry: 'ts/tmp/entry.js'
};

var tsProject = ts.createProject(paths.tsConfig, { noExternalResolve: true });

gulp.task('ts', function () {
    var tsResult = tsProject.src().pipe(sourcemaps.init()).pipe(ts(tsProject));
    return tsResult.js.pipe(sourcemaps.write('', { debug: debug, includeContent: true, sourceRoot: './ts/src' })).pipe(gulp.dest(paths.tempDst));
});

gulp.task('dev', ['ts'], function() {
    var bsfy = browserify({ entries: paths.entry, debug: true }); // Debug true generates sourcemaps
    return bsfy.bundle()
        .on('error', gutil.log)
        .pipe(source(path.join(paths.scriptsDst, paths.outDev)))
        .pipe(buffer())
        .pipe(gulp.dest('./'));
});

gulp.task('final', ['ts'], function() {
    process.env.NODE_ENV = 'production';
    var bsfy = browserify({ entries: paths.entry, debug: false });
    return bsfy.bundle()
        .on('error', gutil.log)
        .pipe(source(path.join(paths.scriptsDst, paths.outFinal)))
        .pipe(buffer())
        .pipe(uglify())
        .pipe(gulp.dest('./'));
});

// Rerun the dev task when a file changes
gulp.task('watch', function() {
    gulp.watch(paths.scriptsSrc, ['dev']);
});

// By default run all the tasks
gulp.task('default', ['dev', 'final']);

关于javascript - Gulp Typescript + Browserify;捆绑的 sourcemap 指向转译的 JS 而不是源 TS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33903456/

相关文章:

javascript - 使用 ng-class 显示隐藏元素的 Angular 指令

angular - 更改月份后日期未更新

自更新到 MACOS Catalina 以来,Ruby 罗盘问题失败

javascript - 通过管道传递参数

javascript - 如何拆分 JavaScript 数组?

javascript - select2 和 select2 full 有什么区别?

javascript - 如何在另一个js文件中实例化一个javascript类?

javascript - Angular 2/ ionic 2 - ts 中的 for 循环

typescript - 如何通过 angular2 中的渲染器(或替代)获取类属性

javascript - 从 webdriver.io 获取数据后动态构建 Mocha 测试