Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong reference in source map for files in subfolders #666

Open
haoadoreorange opened this issue Nov 2, 2021 · 3 comments
Open

Wrong reference in source map for files in subfolders #666

haoadoreorange opened this issue Nov 2, 2021 · 3 comments

Comments

@haoadoreorange
Copy link
Collaborator

Expected behavior:
Go up mutiple level in sources path of .map file depending on the location in subfolder

Actual behavior:
Same level for all

Your gulpfile:

Include your gulpfile, or only the related task (with ts.createProject).

const sourcemaps = require(`gulp-sourcemaps`);
const tsProject = require(`gulp-typescript`).createProject(`tsconfig.build.json`);
const gulp = require(`gulp`);
exports.default = () => {
    const compiled_src = tsProject
        .src()
        .pipe(sourcemaps.init())
        .pipe(
            require(`gulp-strip-code`)({
                start_comment: `<DEV-ONLY>`,
                end_comment: `</DEV-ONLY>`,
            }),
        )
        .pipe(tsProject());
    return require(`merge-stream`)(
        compiled_src.js
            .pipe(require(`gulp-uglify`)({ keep_fnames: true }))
            .pipe(sourcemaps.write(`.`, { includeContent: false }))
            .pipe(gulp.dest(`dist`)),
        compiled_src.dts.pipe(sourcemaps.write(`.`, { includeContent: false })).pipe(gulp.dest(`dist`)),
    );
};

tsconfig.json

Include your tsconfig, if related to this issue.

// tsconfig.build.json
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "rootDir": "src/",
        "declaration": true
    },
    "exclude": ["test/", "dist/"]
}

// tsconfig.json
{
    "extends": "@tsconfig/node14/tsconfig.json",
    "compilerOptions": {
        "outDir": "dist/" /* Redirect output structure to the directory. */,
        "lib": ["ES2020", "ES2021.String"],
        "baseUrl": "src/" /* Base directory to resolve non-absolute module names. */,
        "plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
    }
}

// @tsconfig/node14/tsconfig.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node 14",

  "compilerOptions": {
    "lib": ["es2020"],
    "module": "commonjs",
    "target": "es2020",

    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Code

Include your TypeScript code, if necessary.

// src/index.ts
export {}

// dist/index.js.map
{"version":3,"sources":["../src/index.ts"], ... // correct

// src/lib/polyfill.ts
export {}

// dist/lib/polyfill.js.map
{"version":3,"sources":["../src/lib/polyfill.ts"], ... // wrong, should be ../../src/lib....

This might be related to #644, although I'm not sure

@ivogabe
Copy link
Owner

ivogabe commented Nov 3, 2021

gulp-sourcemaps expects the paths to be relative to the base path of gulp:

Important: Make sure the paths in the generated source map (file and sources) are relative to file.base (e.g. use file.relative).

I think the base path of dist/lib/polyfill.js is dist/lib and that the sources should thus be ["../src/lib/polyfill.ts"] (before sourcemaps.write does its work). Can you verify that by adding some logging in gulp-typescript?

I'm not sure what gulp-sourcemaps does with those paths in sourcemaps.write. Maybe you need to set sourceRoot?

Anyway, this is another example why gulp is so difficult, with all those relative paths, relative to different paths.

@haoadoreorange
Copy link
Collaborator Author

haoadoreorange commented Nov 30, 2021

So I dig into it today and found the answer. Here's for those who will run into the same problem later on.

TL;DR: I didn't set the sourceRoot. You MUST set the sourceRoot for gulp-sourcemaps when not inlining the source map, as the relative path from gulp.dest to outDir. If you're not sure, just follow gulp-typescript doc instructions closely.

Explanation:

gulp.dest uses the vinyl package file.relative as the final destination, which is computed as path.relative(file.base, file.path). So in order to re-construct the structure of source folder in gulp.dest, gulp-typescript set file.base of every output files to whatever the common destination folder is. The common destination folder is NOT gulp.dest, gulp-typescript has no idea what gulp.dest is, this is computed as the highest common of path.dirname(file.path), here file.path is the output file path given by the typescript compiler, no matter whether it exists or not, as it is only used to compute the relative path from gulp.dest for output files.

Because gulp-sourcemaps requires that the sources field of .map files is relative to file.base (which I'm not sure is the optimal choice, opened an issue here). The sources field set by gulp-typescript is not relative to the .map file itself.

Hence, to overcome it you need to pass sourceRoot a relative path from gulp.dest to the file.base (which is the outDir), which will be replaced with the correct relative path to file.base in each .map file.

This is why if gulp.dest === outDir, sourceRoot = ./. Because ./ is the relative path to gulp.dest and outDir. When you don't set outDir in tsconfig, it is set as the source folder by tsc, hence sourceRoot need to be the relative path from gulp.dest to the source folder.

If gulp.dest !== outDir, you need to figure out the relative path from gulp.dest to outDir and pass it to sourceRoot. (@ivogabe can be an added to the doc here)

@ivogabe
Copy link
Owner

ivogabe commented Nov 30, 2021

Great! So our behaviour is correct? Are all examples in the readme correct? We could indeed add some more explanation there to clarify this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants