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

Existing source maps of concatenated scripts are ignored #1

Open
madtisa opened this issue Mar 1, 2022 · 2 comments
Open

Existing source maps of concatenated scripts are ignored #1

madtisa opened this issue Mar 1, 2022 · 2 comments
Assignees

Comments

@madtisa
Copy link

madtisa commented Mar 1, 2022

If input files has source maps besides them, then they should also be merged. For example when concatenating of two minified libraries.
To support source maps I overrode existing class (v4.1.4) that way:

import { readFile } from 'fs/promises';
import { relative } from 'upath';
import { ConcatSource, OriginalSource, SourceMapSource } from 'webpack-sources'
import { Compilation, Compiler } from 'webpack';
import type { RawSourceMap } from 'source-map';

import ConcatPlugin = require('@mcler/webpack-concat-plugin');

class FileWithMap {
    constructor(private readonly _content: string, private readonly _sourceMap: RawSourceMap) {
    }

    public get sourceMap() {
        return this._sourceMap;
    }

    public toString() {
        return this._content;
    }
}

const originalResolve = ConcatPlugin.prototype.resolveReadFiles;
ConcatPlugin.prototype.resolveReadFiles = function (compiler: Compiler): void {
    originalResolve.call(this, compiler);

    let readFilePromise: ReturnType<typeof createSourcesPromise>;

    this.getReadFilePromise = (createNew: boolean) => {
        if (!readFilePromise || createNew) {
            readFilePromise = createSourcesPromise.call(this);
        }

        return readFilePromise;
    };

    async function getSourceAndMap(filePath: string) {
        const path = `webpack:///${relative(compiler.options.context, filePath)}`;
        const source = await readFile(filePath);
        const sourceMap = await readSourceMap(filePath);

        return {
            [path]: new FileWithMap(source.toString(), sourceMap)
        };
    }

    async function readSourceMap(filePath: string) {
        try {
            const sourceMapText = await readFile(filePath + '.map');
            return JSON.parse(sourceMapText.toString()) as RawSourceMap;
        } catch (error) {
            console.debug(`Skip reading source map for '${filePath}'. Details: ${error.message}`);
            return undefined;
        }
    }

    async function createSourcesPromise() {
        this.needCreateNewFile = true;
        const filePathArray: string[] = await this.filesToConcatAbsolutePromise;

        return await Promise.all(filePathArray.map((path) => getSourceAndMap(path)));
    };
}

ConcatPlugin.prototype.resolveConcatAndUglify = function (compilation: Compilation, files: { [x: string]: FileWithMap }[]): void {
    const allFiles = files.reduce((file1, file2) => Object.assign(file1, file2), {});
    this.finalFileName = this.getFileName(allFiles);
    const concatSource = new ConcatSource();
    Object.entries(allFiles).forEach(([name, file]) => {
        const fileContent = file.toString();
        const source = file.sourceMap
            ? new SourceMapSource(fileContent, name, file.sourceMap)
            : new OriginalSource(fileContent, name);
        concatSource.add(source);
        concatSource.add('\n');
    });
    compilation.emitAsset(this.finalFileName, concatSource);
    this.needCreateNewFile = false;
}

export = ConcatPlugin;

If you interested in including this functionality in the library I can create PR (or your can merge it yourself).

P.S. It also fixes problem with missing newline between merged scripts.

@mcler
Copy link
Owner

mcler commented Mar 1, 2022

@madtisa PR would be great!

UPD: I'm working on suggested feature

@mcler
Copy link
Owner

mcler commented Mar 15, 2022

@mcler mcler self-assigned this Mar 26, 2022
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