如何解决Browserify > Exorcist > Sorcery 和本地 NPM 依赖项的 Sourcemap 转换问题
我正在开发一个依赖于本地 npm 模块(节点目标)的 Chrome 扩展程序(打字稿、浏览器目标)。
问题:我的构建管道坏了,很可能是源映射转换(webpack > browserify > exorcist > sorcery)通过各种依赖项(我的应用程序 > 核心库 > 节点依赖)。
项目设置和构建管道
多模块项目设置
- chrome 扩展名“quickbrain.chrome”
- 这就是我想要构建的
- 浏览器目标
- 核心库“quickbrain.core”
- 被“quickbrain.chrome”和其他人使用
- node 目标/对 nodejs 模块的依赖(例如 https://github.com/NaturalNode/natural)
- 其他一些使用“quickbrain.core”模块(node express)的应用
为“quickbrain.chrome”构建管道
-
打字稿(输入)
-
网络包
-
浏览,https://github.com/browserify/browserify
(使 quickbrain.core(节点)在 quickbrain.chrome(浏览器)中运行)
-
驱魔人,https://github.com/thlorenz/exorcist
(externalize sourcemaps,因为 Chrome 不理解扩展的内联源映射,但 browserify 只生成内联)
-
魔法,https://github.com/Rich-Harris/sorcery(通过这个可怕的项目设置解析源映射 uri 链)
-
JS + 源映射(输出)
错误信息
在构建时,我在 Sorcery 阶段得到以下工件和错误。
- Webpack -> contentscript.js、contentscript.js.map
- Browserify -> Exorcist -> contentscript.exorcist.js,contentscript.exorcist.js.map
- 巫术 -> contentscript.final.js,concentscript.final.js.map
(node:30724) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory,open 'C:\QB\com.quickbrain\chrome\dist.development\core\node_modules\underscore\underscore-node-f.cjs.map'
Underscore / underscore-node 是来自节点模块“natural”的依赖项,在“quikbrain.core”中使用,我过去没有遇到过这个问题。
提示
-
我可以看到错误信息中的根路径完全错误:
- 错误消息:
com.quickbrain\____chrome\dist.development____\core\node_modules\underscore\underscore-node-f.cjs.map
(注意____突出显示的错误绝对路径) - 实际文件:
com.quickbrain\core\node_modules\underscore\underscore-node-f.cjs.map
- 错误消息:
-
查看源映射本身时,我也可以看到其他源映射的相同相对路径,例如
webpack:///../core/node_modules/axios/index.js
vswebpack:///../core/node_modules/underscore/underscore-node-f.cjs
,但只有后者会导致绝对路径错误的巫术错误信息。 -
过去的构建不包含
underscore-node
源映射。运行webpack后已经有区别了,但是我不明白为什么现在包含它。 -
请注意,
quickbrain.chrome
将quickbrain.core
安装为本地依赖项"quickbrain.core": "file:../core"
参考文件
> 浏览器化的 contentscript.js 和 contentscript.js.map 部分
const _ = __webpack_require__(/*! underscore */ "../core/node_modules/underscore/underscore-node.cjs")
"webpack:///../core/node_modules/underscore/underscore-node-f.cjs","webpack:///../core/node_modules/underscore/underscore-node.cjs",
> quickbrain.chrome > package.json(仅相关部分)
{
"name": "quickbrain.chrome","version": "0.3.0","description": "","main": "index.js","watch": {
"webpack-dev": {
"patterns": [
"src"
],"extensions": "ts,html"
}
},"scripts": {
"webpack-dev": "webpack --env NODE_ENV=development --config webpack.config.js && npm run browserify-contentscript-dev && npx node sorcery_finalize_sourcemaps.js","browserify-contentscript-dev": "browserify dist.development/contentscript.js --debug --ignore-missing | exorcist --error-on-missing --root ../ dist.development/contentscript.exorcist.js.map > dist.development/contentscript.exorcist.js",},"author": "","license": "ISC","devDependencies": {
"@types/chrome": "0.0.127","@types/node": "^14.14.28","awesome-typescript-loader": "^5.2.1","browserify": "^17.0.0","clean-webpack-plugin": "^3.0.0","convert-source-map": "^1.7.0","copy-webpack-plugin": "^7.0.0","exorcist": "^1.0.1","node-sass": "^5.0.0","npm": "^6.14.10","npm-run-all": "^4.1.5","npm-watch": "^0.7.0","sass-loader": "^10.1.0","sorcery": "^0.10.0","sourceify": "^1.0.0","ts-node": "^9.1.1","typescript": "^4.1.3","webpack": "^5.10.3","webpack-cli": "^4.2.0"
},"dependencies": {
"@types/ejs": "^3.0.5","@types/jquery": "^3.5.5","axios": "^0.21.0","quickbrain.core": "file:../core","ejs": "^3.1.5","html-loader": "^1.3.2","jquery": "^3.5.1","nodejs-base64-converter": "^1.0.5"
}
}
> quickbrain.chrome > tsconfig.json
{
"compileOnSave": false,"compilerOptions": {
"target": "es5","module": "commonjs","sourceMap": true,"inlineSourceMap": false,"inlineSources": false,"types": ["@types/chrome","node","jquery"],"typeRoots": ["node_modules/@types"],"moduleResolution": "node","esModuleInterop": true,"lib": ["es2017","dom"]
},"include": ["src/background","src/contentscript-chrome"]
}
> quickbrain.chrome > sorcery_finalize_sourcemaps.js(仅相关部分)
var sorcery = require("sorcery");
let i = 0;
function doMagic(src,dst) {
console.log(`loading ` + src);
sorcery.load(src).then(function(chain) {
// generate a flattened sourcemap
var map = chain.apply(); // { version: 3,file: 'code.min.js',... }
// get a JSON representation of the sourcemap
map.toString(); // '{"version":3,"file":"code.min.js",...}'
// get a data URI representation
map.toUrl(); // 'data:application/json;charset=utf-8;base64,eyJ2ZXJ...'
// write to a new file,but append the flattened sourcemap as a data URI
chain.write(dst,{ inline: true });
});
}
try {
doMagic(
"dist.development/contentscript.exorcist.js","dist.development/contentscript.final.js"
);
console.log("\n\n_,.~*`( sorcery done )`*~.,_\n");
} catch (e) {
console.error("Computer says no: " + e + " :(");
}
(当我只使用 npx sorcery --input dist.development/contentscript.exorcist.js --output dist.development/contentscript.sorcery.js
时,我收到相同的错误消息)
> quickbrain.core > package.json
{
"name": "quickbrain.core","version": "0.2.0","types": "index.d.ts","scripts": {
"test": "echo \"Error: no test specified\" && exit 1","build": "npx tsc"
},"dependencies": {
"@types/axios": "^0.14.0","@types/mongoose": "^5.10.3","@types/natural": "^2.1.1","@types/wink-tokenizer": "^4.0.2","atlassian-jwt": "^1.0.3","axios": "^0.21.1","compute-cosine-similarity": "^1.0.0","express": "^4.17.1","fuzzball": "^1.3.1","jwt-decode": "^3.1.2","moment": "^2.29.1","mongoose": "^5.11.17","natural": "^4.0.3","stopwords-iso": "^1.1.0","string-strip-html": "^8.2.2","ts-lib": "0.0.5","tslib": "^2.1.0","wink-tokenizer": "^5.2.3"
},"devDependencies": {
"mongodb-memory-server": "^6.9.6","typescript": "^4.2.3"
}
}
> quickbrain.core > tsconfig.json
{
"compilerOptions": {
"target": "es5",/* Specify ECMAScript target version: 'ES3' (default),'ES5','ES2015','ES2016','ES2017','ES2018','ES2019','ES2020',or 'ESNEXT'. */
"module": "commonjs",/* Specify module code generation: 'none','commonjs','amd','system','umd','es2015','es2020',or 'ESNext'. */
"declaration": true,/* Generates corresponding '.d.ts' file. */
"outDir": "./dist",/* Redirect output structure to the directory. */
"strict": true,/* Enable all strict type-checking options. */
"esModuleInterop": true,/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": true,/* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
解决方法
编辑:不幸的是没有解决。管道有效,但我缺少大部分源映射
我能够使用 https://stackoverflow.com/a/55356078/5244937(和 https://github.com/browserify/browserify/issues/772)解决这个问题,关于 Browserify 和带有预编译源映射的模块(例如导致问题的 underscore
)。
根据帖子,当 tsconfig.json 设置为 inline-sourcemaps 时,Browserify 将忽略 3rd 方源映射。
这意味着我已将 quickbrain.chrome
的 tsconfig.json 更改为
"sourceMap": false,"inlineSourceMap": true,"inlineSources": true,
.. 和 Browserify(管道的第 2 步)删除 natural
、underscore
等的源映射,从而完全避免管道末端的问题。
有趣的事实:"inlineSourceMap": true
甚至没有被我的管道使用,因为我使用带有外部源映射的 webpack 进行编译。唯一的影响是影响 Browserfify 删除其他源映射。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。