概要
sourcemap 文件会记录产物文件和源代码的映射关系,一个 *.map
文件的基本结构如下:
{
"version": 3,
"file": "bundle.js", // 产物文件
"sources": [ // 源代码文件
"../src/utils.js",
"../src/index.js"
],
"sourcesContent": [ // 数组, 每一项是 sources 中文件的源代码
"export function print(content) {\n console.log(content);\n}\n",
"import { print } from './utils';\n\nprint('Hello World');\n"
],
"names": [ // 用于优化的字段, 可不关注
"console",
"log"
],
"mappings": "yBACEA,QAAQC,ICCJ" // 位置的映射信息
}
*.map
文件中记录了所有模块的文件路径、源码内容以及映射关系。要生成 sourcemap 文件,就需要将所有模块的信息放入一个 swc_common::SourceMap
实例 cm
中。
而不是现阶段为每一个模块都生成一个 cm
,这样会导致每一个 cm
的 sources 只有一项,且最终无法拼接。
详细设计
新增全局共享的 swc_common::SourceMap
实例
Context
中添加共享数据 sourcemap
:
pub struct Context {
pub meta: Meta;
}
pub struct Meta {
pub js: JsMeta,
pub css: CssMeta,
}
pub struct JsMeta { // js sourcemap
pub cm: Arc<SourceMap>,
}
pub struct CssMeta { // css sourcemap
pub cm: Arc<SourceMap>,
}
向 cm
中添加源文件信息
parse
阶段使用 context.meta.js.cm.new_source_file()
添加文件,而非创建新 cm:
fn parse(path: &str, content: &str, context: &Arc<Context>) {
let fm = context
.meta
.js
.cm
.new_source_file(FileName::Custom(path.to_string()), content.to_string());
// ...
}
等构建出模块依赖图后,所有模块的信息都会被添加到 context.meta.js.cm
以及 context.meta.css.cm
中。
生成 sourcemap
需要对每一个 Chunk 都生成一个 .map
文件,追加 sourceMappingURL
到每个 Chunk js
文件末尾:
buf.append(&mut "\n//# sourceMappingURL=index.js.map".as_bytes().to_vec());
生成最终的 sourcemap 文件:
fs::write(format!("{}.map", output.display()), &file.sourcemap).unwrap()
预见的问题
.map
文件中 sources 文件路径
这是目前实验阶段生成出的一份 sourcemap 文件(基于 examples/normal
项目):
{
"version": 3,
"sources": [
"<index.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/scheduler/index.js>",
"</Users/jess/Code/Jess/mako/examples/normal/index.css.ts>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.production.min.js>",
"</Users/jess/Code/Jess/mako/examples/normal/assets/umi-logo.png>",
"</Users/jess/Code/Jess/mako/examples/normal/foo.ts>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/react/index.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.development.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/cjs/react-dom.development.js>",
"</Users/jess/Code/Jess/mako/examples/normal/assets/mailchimp-unsplash.jpg>",
"</Users/jess/Code/Jess/mako/examples/normal/index.tsx>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/react/cjs/react.production.min.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/index.js>",
"</Users/jess/Code/Jess/mako/examples/normal/foo.css.ts>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/@[email protected]/node_modules/@swc/helpers/esm/_interop_require_default.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.development.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected][email protected]/node_modules/react-dom/client.js>",
"</Users/jess/Code/Jess/mako/node_modules/.pnpm/[email protected]/node_modules/scheduler/cjs/scheduler.production.min.js>"
],
"names": [],
"mappings": "" // 这里被我隐藏了
}
sources 中的文件路径有些问题:
- 都被
< ... >
包裹住了
- 路径应该是相对路径而非绝对路径,这是因为在开发服务下
http://localhost:8080/Users/jess/Code/Jess/mako/examples/normal/index.js
会找不到。
css sourcemap
当前 mako 会将 css 转为 js,所以上述 sources 中出现了一些 *.css.ts
文件,这些文件不能被正常找到。
这一块建议先不做处理,后续支持生成单独的 css 文件后即可解决该问题。