@jridgewell /重新映射
通过转换重新映射顺序源映射,以指向原始源代码
重新映射允许您获取通过转换代码和“重新映射”生成的源映射。 他们到原来的源位置。想想“我的迷你代码,用巴别塔转换和捆绑” 使用webpack",所有指向原始源代码中的正确位置。
通过重新映射,您的源代码转换都不需要知道输入的源映射, 它们只需要生成一个输出源映射。这极大地简化了构建自定义 转换(考虑查找和替换)。
安装
npm install @jridgewell/remapping
用法
function remapping(
map: SourceMap | SourceMap[],
loader: (file: string, ctx: LoaderContext) => (SourceMap | null | undefined),
options?: { excludeContent: boolean, decodedMappings: boolean }
): SourceMap;
// LoaderContext gives the loader the importing sourcemap, tree depth, the ability to override the
// "source" location (where child sources are resolved relative to, or the location of original
// source), and the ability to override the "content" of an original source for inclusion in the
// output sourcemap.
type LoaderContext = {
readonly importer: string;
readonly depth: number;
source: string;
content: string | null | undefined;
}
remapping 接受最终的输出源映射和 loader 函数。对于每个源文件指针
在源映射中, loader 将使用已解析的路径调用。如果路径本身表示
转换后的文件(它有一个与之关联的源映射),然后是 loader 应该返回
sourcemap。如果没有,路径将被视为原始的、未转换的源代码。
// Babel transformed "helloworld.js" into "transformed.js"
const transformedMap = JSON.stringify({
file: 'transformed.js',
// 1st column of 2nd line of output file translates into the 1st source
// file, line 3, column 2
mappings: ';CAEE',
sources: ['helloworld.js'],
version: 3,
});
// Uglify minified "transformed.js" into "transformed.min.js"
const minifiedTransformedMap = JSON.stringify({
file: 'transformed.min.js',
// 0th column of 1st line of output file translates into the 1st source
// file, line 2, column 1.
mappings: 'AACC',
names: [],
sources: ['transformed.js'],
version: 3,
});
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
// The "transformed.js" file is an transformed file.
if (file === 'transformed.js') {
// The root importer is empty.
console.assert(ctx.importer === '');
// The depth in the sourcemap tree we're currently loading.
// The root `minifiedTransformedMap` is depth 0, and its source children are depth 1, etc.
console.assert(ctx.depth === 1);
return transformedMap;
}
// Loader will be called to load transformedMap's source file pointers as well.
console.assert(file === 'helloworld.js');
// `transformed.js`'s sourcemap points into `helloworld.js`.
console.assert(ctx.importer === 'transformed.js');
// This is a source child of `transformed`, which is a source child of `minifiedTransformedMap`.
console.assert(ctx.depth === 2);
return null;
}
);
console.log(remapped);
// {
// file: 'transpiled.min.js',
// mappings: 'AAEE',
// sources: ['helloworld.js'],
// version: 3,
// };
在这个例子中, loader 将被调用两次:
"transformed.js"中的第一个源文件指针minifiedTransformedMap. 我们返回 它的关联源映射(毕竟它是一个转换后的文件),以便源映射位置可以 通过它跟踪到它所代表的源文件。"helloworld.js",我们原始的,未经修改的源代码。这个文件没有源映射,所以 我们返回null。
这个 remapped 源地图现在指向 transformed.min.js 进入各个位置 helloworld.js。如果
你要读 mappings,它表示“第一行的第0列输出行指向第1列。
文件第二行的列 helloworld.js".
一个文件的多个转换
为了方便起见,如果一个文件有多个单源转换,可以传递一个
源地图文件的数组,按照最近的转换源地图的顺序排列。请注意
改变了 importer 和 depth 对加载器的每个调用。所以上面的例子可以是
写为:
const remapped = remapping(
[minifiedTransformedMap, transformedMap],
() => null
);
console.log(remapped);
// {
// file: 'transpiled.min.js',
// mappings: 'AAEE',
// sources: ['helloworld.js'],
// version: 3,
// };
加载图形的高级控制
source
这个 source 属性可以重写为任何值,以更改当前加载的位置。例如,
对于原始源文件,它允许我们更改原始源文件的位置
sourcemap源条目所表示的内容。对于已转换的文件,它允许我们更改
加载源映射的子源的相对解析位置。
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
if (file === 'transformed.js') {
// We pretend the transformed.js file actually exists in the 'src/' directory. When the nested
// source files are loaded, they will now be relative to `src/`.
ctx.source = 'src/transformed.js';
return transformedMap;
}
console.assert(file === 'src/helloworld.js');
// We could futher change the source of this original file, eg, to be inside a nested directory
// itself. This will be reflected in the remapped sourcemap.
ctx.source = 'src/nested/transformed.js';
return null;
}
);
console.log(remapped);
// {
// …,
// sources: ['src/nested/helloworld.js'],
// };
content
这个 content 属性可以在遇到原始源文件时重写。例如,这允许
您必须手动提供原始文件的源内容,而不管是否
sourcesContent 字段存在于父源映射中。也可以设置为 null 删除
源内容。
const remapped = remapping(
minifiedTransformedMap,
(file, ctx) => {
if (file === 'transformed.js') {
// transformedMap does not include a `sourcesContent` field, so usually the remapped sourcemap
// would not include any `sourcesContent` values.
return transformedMap;
}
console.assert(file === 'helloworld.js');
// We can read the file to provide the source content.
ctx.content = fs.readFileSync(file, 'utf8');
return null;
}
);
console.log(remapped);
// {
// …,
// sourcesContent: [
// 'console.log("Hello world!")',
// ],
// };
选项
excludeContent
默认情况下, excludeContent 是 false. 通过 { excludeContent: true } 将排除
sourcesContent 字段从返回的源映射。这在你想减少的时候很有用
源地图的大小。
decodedMappings
默认情况下, decodedMappings 是 false. 通过 { decodedMappings: true } 将离开
mappings 字段中 解码状态 而不是
编码成VLQ字符串。