Skip to content

Instantly share code, notes, and snippets.

@mutoo
Created September 6, 2018 07:04
Show Gist options
  • Save mutoo/ad6dd6101535e82a44bcc2a051d7cb22 to your computer and use it in GitHub Desktop.
Save mutoo/ad6dd6101535e82a44bcc2a051d7cb22 to your computer and use it in GitHub Desktop.
/**
* Why we need the soucemap path fixer?
*
* 1) postcss-loader + css-loader suck!
* https://github.com/postcss/postcss-loader/issues/390#issuecomment-417584816
*
* 2) Don't insert absolute paths into the module code as they break hashing when the root for the project is moved.
* https://webpack.js.org/contribute/writing-a-loader/#absolute-paths
*/
import {getOptions} from 'loader-utils';
import validateOptions from 'schema-utils';
const schema = {
type: 'object',
properties: {
sourceMap: {
type: 'boolean',
},
},
};
const root = process.cwd().replace(/\\/g, '/');
/**
* Fix the source map path
*
* @param {object} source
* @return {string}
*/
export default function(source) {
// eslint-disable-next-line no-invalid-this
const options = getOptions(this);
validateOptions(schema, options, 'SourceMap fixer');
// check if source map enabled
if (options.sourceMap) {
source = fixer(source);
}
return source;
}
/**
* Source Paths Fixer
*
* Find and replace the source path in the source data.
* The sources could look like following strings:
*
* "sources":[]
* "sources":["/path/to/source-1"]
* "sources":["/path/to/source-1","/path/to/source-2"]
* "sources":["/path/to/source-1",...,"/path/to/source-n"]
*
* @param {string} source - the raw data of source
* @return {string}
*/
export function fixer(source) {
return source.replace(/"sources":\[((".+?",?)*)]/g, replacer);
}
/**
* Replace function
*
* To replace a path in the sources array to a webpack-internal path
*
* cwd = /path/to/project
* "sources":["/path/to/project/src/source-1"]
* => "sources":["webpack-internal:///./src/source-1"]
*
* cwd = C:/path/to/project
* "sources":["C:/path/to/project/src/source-2"]
* => "sources":["webpack-internal:///./src/source-2"]
*
* @param {string} $0 the capture 0 equals to whole capture
* @param {string} $1 the capture 1 equals the content in the sources array
* @return {string}
*/
export function replacer($0, $1) {
if ($1) {
let paths = $1.split(/,\s?/).map((originalPath) => {
let path = originalPath.slice(1,
originalPath.length - 1); // strip quotes
let foundRoot = path.lastIndexOf(root);
if (foundRoot > -1) {
path = path.slice(foundRoot + root.length);
return `"webpack-internal:///.${path}"`;
} else {
return originalPath;
}
}).join(',');
return `"sources":[${paths}]`;
}
return $0;
}
@mutoo
Copy link
Author

mutoo commented Sep 6, 2018

@michael-ciniawsky
Copy link

michael-ciniawsky commented Sep 6, 2018

Could you please provide a before and after example, so it's easier follow what this loader exactly does ? e.g

before/map.json

{
  sources: [
     'absolute/path/to/source.ext'
  ]
}

after/map.json

{
  sources: [
     // ?
  ]
}

Also a quick screenshot of e.g the DevTool's panel (like I did here for e.g), basically proofing your solution works and a small repoduction repo would be awesome to have

On UNIX platforms sourcemaps currently seem to work with absolute file paths, but that might be by coincidence since UNIX File Paths and URL's have some similarities in common

@mutoo
Copy link
Author

mutoo commented Sep 6, 2018

hi Michael, I've left before and after example in the jsdoc above the replacer function.

 * cwd = /path/to/project
 * "sources":["/path/to/project/src/source-1"]
 * => "sources":["webpack-internal:///./src/source-1"]
 *
 * cwd = C:/path/to/project
 * "sources":["C:/path/to/project/src/source-2"]
 * => "sources":["webpack-internal:///./src/source-2"]

On the windows it can even fixed the malformed path

 * cwd = C:/path/to/project
 * "sources":[" C:/path/to/project C:/path/to/projectC:/path/to/project/src/source-2"]
 * => "sources":["webpack-internal:///./src/source-2"]

macOS

before:
macos-sourcemap-path-fixer-before
after:
macos-sourcemap-path-fixer-after

Windows

before:
win-sourcemap-path-fixer-before
after:
win-sourcemap-path-fixer-after

Also, I created a branch to demonstrate this loader:
https://github.com/mutoo/web-project-boilerplate/tree/sourcemap-path-fixer
after running yarn run dev, the page will be available at http://localhost:9000/static

@romanlex
Copy link

romanlex commented Nov 22, 2020

hi....how I can use this?

@mutoo
Copy link
Author

mutoo commented Nov 22, 2020

hi....how I can use this? it's a plugin for postcss?

basically, add this loader to your project and then use it as a loader in your rules
ref: https://webpack.js.org/contribute/writing-a-loader/

But as discussed in that thread, I believe this issue had been fixed already:
webpack-contrib/postcss-loader#390 (comment)

P.S. I didn't verify this, yet.

@romanlex
Copy link

@mutoo thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment