使用browserify后保留原始打字稿源地图

时间:2014-05-04 06:02:23

标签: javascript typescript browserify source-maps

背景:我正在将2个依赖的TypeScript文件编译为js,它使用tsc 1.0生成源地图(每个文件一个源地图)

我正在使用-m commonjs,然后使用browserify生成一个bundle.js

但是我注意到我在包中得到了两次原始的源地图引用,这似乎不起作用。

传递--debug似乎也无法解决问题。

我有一种感觉这个问题:https://github.com/substack/node-browserify/issues/325有点相关,但我无法弄清楚问题是如何解决的。

同时提出了https://github.com/substack/browser-pack,但我还是不完全明白如何使用它,它是否取代了浏览器?

底线,我想合并2个js文件,但是使用browserify将js“合并”到ts源地图。这可能吗?

6 个答案:

答案 0 :(得分:17)

tsify是一个更好的browserify插件,可替换为例如typescriptifier。

npm install tsify browserify watchify

你像这样使用tsify:

browserify src/index.ts -p tsify --debug -o build/index.js

请注意,这支持browserify --debug切换,不需要额外的技巧。所以你也可以像以下那样使用它:

watchify src/index.ts -p tsify --debug -o build/index.js

答案 1 :(得分:7)

使用minifyify browserify插件我相信您可以将TypeScript与Browserify一起使用并保留源地图。编译TypeScript文件后,您应该能够传递"条目"使用minifyify插件通过browserify通过commonjs语法导入另一个文件。

var browserify = require('browserify'),
    bundler = new browserify();

bundler.add('entry.js');
bundler.plugin('minifyify', {map: 'bundle.js.map'});
bundler.bundle({debug: true}, function (err, src, map) {
  if (err) console.log(err);
  fs.writeFileSync('bundle.js', src);
  fs.writeFileSync('bundle.js.map', map);
});

答案 2 :(得分:1)

这是我的工作解决方案:

var settings = {
  projectName : "test"
};    

gulp.task("bundle", function() {

  var mainTsFilePath = "src/main.ts";
  var outputFolder   = "bundle/src/";
  var outputFileName = settings.projectName + ".min.js";
  var pkg            = require("./package.json");

  var banner = [
    "/**",
    " * <%= pkg.name %> v.<%= pkg.version %> - <%= pkg.description %>",
    " * Copyright (c) 2015 <%= pkg.author %>",
    " * <%= pkg.license %>",
    " */", ""
  ].join("\n");

  var bundler = browserify({
    debug: true,
    standalone : settings.projectName
  });

  // TS compiler options are in tsconfig.json file
  return bundler.add(mainTsFilePath)
                .plugin(tsify)
                .bundle()
                .pipe(source(outputFileName))
                .pipe(buffer())
                .pipe(sourcemaps.init({ loadMaps: true }))
                .pipe(uglify())
                .pipe(header(banner, { pkg : pkg } ))
                .pipe(sourcemaps.write('./'))
                .pipe(gulp.dest(outputFolder));
});

答案 3 :(得分:1)

我创建了一个很好的模板来使用typescript开发或只是开发web项目!

也许你可以把我的项目的某些部分作为例子。

它包括一个带Scss&amp;的Gulp。 js minify,livereload,watch files,font&amp;图像缩小。如果你想使用它我也包括哈巴狗。如果你愿意,你可以使用html。

我还包括基金会(框架)。

为什么打字稿很好? 您可以使用它在main.js中“导入”.js,就像main.scss那样@import你的所有style.scss。

https://github.com/t1gu1/front-end-typescript-template

关注我并在我的github上发表评论! ^^

答案 4 :(得分:0)

我创建了example project

您可以使用$(npm bin)/gulp build --env=dev为开发环境运行它,并生成源地图。

gulpfile.js

'use strict';

var path = require('path'),
    gulp = require('gulp'),
    del = require('del'),
    typescript = require('gulp-typescript'),
    sourcemaps = require('gulp-sourcemaps'),
    browserify = require('browserify'),
    source = require('vinyl-source-stream'),
    buffer = require('vinyl-buffer'),
    uglify = require('gulp-uglify'),
    gutil = require('gulp-util'),
    inject = require('gulp-inject'),
    babel = require('gulp-babel'),
    argv = require('yargs').argv;

var devEnvironment = 'dev',
    prodEnvironment = 'prod',
    environment = argv.env || prodEnvironment,
    isDevelopment = environment === devEnvironment;

var projectPath = __dirname,
    srcDir = 'src',
    srcPath = path.join(projectPath, srcDir),
    buildDir = path.join('build', environment),
    buildPath = path.join(projectPath, buildDir),
    distDir = 'dist',
    distRelativePath = path.join(buildDir, distDir),
    distPath = path.join(buildPath, distDir);

var tsSrcPath = path.join(srcPath, 'typescript'),
    tsGlob = path.join(tsSrcPath, '**', '*.ts'),
    tsBuildPath = path.join(buildPath, 'tsc');

var indexHtmlName = 'index.html',
    indexJsName = 'index.js';

var distIndexJsPath = path.join(distPath, 'index.js'),
    distIndexHtmlPath = path.join(distPath, indexHtmlName);

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

console.log('Environment: ' + environment);

gulp.task('clean', function () {
    return del([buildPath]);
});

gulp.task('tsc', ['clean'], function () {
    var stream = gulp.src([tsGlob]);
    if (isDevelopment) {
        stream = stream
            .pipe(sourcemaps.init());
    }
    stream = stream
        .pipe(typescript(tsProject))
        .pipe(babel({
            presets: ['es2015']
        }));
    if (isDevelopment) {
        stream = stream.pipe(sourcemaps.write({sourceRoot: tsSrcPath}));
    }
    return stream.pipe(gulp.dest(tsBuildPath));
});

gulp.task('bundle', ['tsc'], function () {
    var b = browserify({
        entries: path.join(tsBuildPath, indexJsName),
        debug: isDevelopment
    });

    var stream = b.bundle()
        .pipe(source(indexJsName))
        .pipe(buffer());
    if (!isDevelopment) {
        stream = stream.pipe(uglify());
    }
    return stream
        .on('error', gutil.log)
        .pipe(gulp.dest(distPath));
});

gulp.task('build', ['bundle'], function() {
    return gulp.src(path.join(srcPath, indexHtmlName))
        .pipe(inject(gulp.src([distIndexJsPath], {read: false}), {ignorePath: distRelativePath, addRootSlash: true}))
        .pipe(gulp.dest(distPath));
});

你应该注意线条:

  1. stream = stream.pipe(sourcemaps.write('', {sourceRoot: tsSrcPath})); - 编写内联源地图,sourceRoot指向您的打字稿来源路径。内嵌地图直接写入.js生成的tsc build/dev/tsc文件。
  2. debug: isDevelopment - 在开发环境中,浏览器为生成的包build/dev/dist/index.js文件生成自己的源地图,因此它的源地图将引用来自.js的{​​{1}}文件源地图引用build/dev/tsc中的.ts个文件。
  3. 使用此设置,您将能够在浏览器中查看和调试src/typescript个文件:

    Screenshot

答案 5 :(得分:0)

我尝试调试在Visual Studio Code中使用Chrome运行的Angular2应用程序时遇到类似问题(使用Debugger for Chrome扩展程序)

我使用gulp作为我的任务运行器,我的设置如下: 打字稿文件 - &gt; tsc - &gt;中间es5 js - &gt; browserify(在生产版本中加上uglify) - &gt;编译捆绑

我的目录结构如下:

|- src
    |- my .ts files here
    |- main.ts - my entry file
|- dist
    |- intermediate files go here
|- web
    |- app.js - final bundle
    |- app.js.map - final bundle map
|- gulpfile.js

gulpfile.js

var gulp = require('gulp'),
    tsc = require('gulp-typescript'),
    browserify = require('browserify'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    source = require('vinyl-source-stream'),
    buffer = require('vinyl-buffer');

gulp.task('tsc', [], () => {
            return gulp.src(['src/**/*.ts'])
                    .pipe(sourcemaps.init())
                    .pipe(tsc({
                            "target": "es5",
                            "module": "commonjs",
                            "moduleResolution": "node",
                            "sourceMap": true,
                            "emitDecoratorMetadata": true,
                            "experimentalDecorators": true,
                            "lib": [ "es2015", "dom" ],
                            "noImplicitAny": true,
                            "suppressImplicitAnyIndexErrors": true
                    }))
                    .pipe(sourcemaps.write(null, {
                            "sourceRoot": function(file) { 
                                    let parts = file.relative.split('\\');
                                    let root = Array(parts.length + 1).join('../') + 'src';
                                    return root;
                            }
                    }))
                    .pipe(gulp.dest('dist/'));
    }); 
gulp.task('bundle', ['tsc'], () => {
    let b = browserify({
        entries: 'dist/main.js',
        debug: true,
    });

    return b.bundle()
        .pipe(source('app.js'))
        .pipe(buffer())
        .pipe(sourcemaps.init({loadMaps: true}))
        .pipe(sourcemaps.write('./', {
            "sourceRoot": "../",
        }))
        .pipe(gulp.dest('web/'));
})

gulp.task('default', ['bundle']);

说明/推理:

由于某种原因browserify没有读取和解析.js文件中链接的.js.map文件(最后通过特殊注释),但是当源地图嵌入在js文件中时会这样做。因此,通过将null而非路径传递给sourcemaps,它会将其嵌入到生成的.js文件的末尾。

我注意到的下一个问题是sourcemaps没有自动遵循目录结构(当它转到下一个目录级别时添加&#39; ../&# 39;到sourceRoot),所以我做了一个快速的功能来补充这一点。请记住,它仅适用于Windows - 在Linux上,您必须更改分割字符。

function(file) { 
    let parts = file.relative.split('\\'); // put '/' here on Linux
    let root = Array(parts.length + 1).join('../') + 'src';
    return root;
}

当然有一种方法可以检测正确的路径分隔符,我只在Windows上进行调试,因此对我的目的来说并不重要。

我希望它对某人有所帮助,因为我整个星期天早上都在追踪这个问题。