node?gyp安裝canvas原生模塊編譯node?pregyp詳解
關(guān)于node-gyp
node-gyp是一個用 Node.js 編寫的跨平臺命令行工具,用于為 Node.js 編譯本機(jī)插件模塊。它包含之前由 Chromium 團(tuán)隊(duì)使用的 gyp-next項(xiàng)目的供應(yīng)副本,擴(kuò)展以支持 Node.js 原生插件的開發(fā)。
node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. It contains a vendored copy of the gyp-next project that was previously used by the Chromium team, extended to support the development of Node.js native addons.
node是跨平臺的,那么對于任何的node模塊理論也是應(yīng)該是跨平臺的。然而,有些node模塊直接或間接使用原生C/C++代碼,這些東西要跨平臺,就需要使用源碼根據(jù)實(shí)際的操作平臺環(huán)境進(jìn)行原生模塊編譯。通常我們開發(fā)環(huán)境為macOS或Windows,而生產(chǎn)環(huán)境為Linux的各種發(fā)行版,這將導(dǎo)致我們的開發(fā)工作變得沉重不堪。那我們是否可以跳過node-gyp的編譯過程?
node-pre-gyp
node-gyp的編譯是讓人難受的過程,所以社區(qū)出現(xiàn)了node-pre-gyp和prebuild-install,它們都會優(yōu)先下載插件作者預(yù)編譯的二進(jìn)制文件,當(dāng)二進(jìn)制文件下載出現(xiàn)問題時,再使用node-gyp進(jìn)行編譯兜底。
但因?yàn)槲覀兙W(wǎng)絡(luò)環(huán)境的特殊性,這些二進(jìn)制文件我們大概率是不會下載成功的,接下來一起來看看在canvas的安裝過程中node-pre-gyp干了什么事。
關(guān)于prebuild-install參考姊妹文【Nodejs】關(guān)于原生模塊編譯node-gyp + prebuild-install (以安裝 better-sqlite3為例)
canvas安裝過程追蹤
canvas就使用了node-pre-gyp來優(yōu)化構(gòu)建過程
1. 安裝canvas
關(guān)于install我們需要了解一點(diǎn)東西, 通?;诒硐笪覀兌紩J(rèn)為npm下載解壓并釋放到node_modules后就完成了安裝過程,但實(shí)際上npm還會檢查package中是否配置了install命令,存在就會立即執(zhí)行,這也是原生模塊在下載完成后會自動構(gòu)建的基礎(chǔ)。
npm install canvas
2. canvas的package的命令腳本
可以看到canvas配置了install命令,所以npm下載canvas后立即執(zhí)行了
node-pre-gyp install --fallback-to-build --update-binary
{
...,
"scripts": {
"prebenchmark": "node-gyp build",
"benchmark": "node benchmarks/run.js",
"lint": "standard examples/*.js test/server.js test/public/*.js benchmarks/run.js lib/context2d.js util/has_lib.js browser.js index.js",
"test": "mocha test/*.test.js",
"pretest-server": "node-gyp build",
"test-server": "node test/server.js",
"generate-wpt": "node ./test/wpt/generate.js",
"test-wpt": "mocha test/wpt/generated/*.js",
"install": "node-pre-gyp install --fallback-to-build --update-binary",
"dtslint": "dtslint types"
}
}
3. node-pre-gyp install命令
node-pre-gyp命令最終鏈接到了@mapbox/node-pre-gyp/lib/main.js,根據(jù)參數(shù)install最終進(jìn)入@mapbox/node-pre-gyp/lib/install.js執(zhí)行
4. 下載預(yù)構(gòu)建的二進(jìn)制文件
可以看到node-pre-gyp先檢查項(xiàng)目本地是否已經(jīng)存在二進(jìn)制構(gòu)建文件,當(dāng)不存在時進(jìn)入用戶本地查找,當(dāng)用戶本地也不存在時會執(zhí)行http下載任何,接下來我們在看看http鏈接如何生成
existsAsync(binary_module, (found) => {
if (!update_binary) {
if (found) {
console.log('[' + package_json.name + '] Success: "' + binary_module + '" already installed');
console.log('Pass --update-binary to reinstall or --build-from-source to recompile');
return callback();
}
log.info('check', 'checked for "' + binary_module + '" (not found)');
}
makeDir(to).then(() => {
const fileName = from.startsWith('file://') && from.slice('file://'.length);
if (fileName) {
extract_from_local(fileName, to, after_place);
} else {
place_binary(from, to, opts, after_place);
}
}).catch((err) => {
after_place(err);
});
function after_place(err) {
if (err && should_do_fallback_build) {
print_fallback_error(err, opts, package_json);
return do_build(gyp, argv, callback);
} else if (err) {
return callback(err);
} else {
console.log('[' + package_json.name + '] Success: "' + binary_module + '" is installed via remote');
return callback();
}
}
});
其中from變量即預(yù)構(gòu)件二進(jìn)制文件地址,指向opts.hosted_tarball,源碼只保留了核心部分,完整源碼請查閱@mapbox/node-pre-gyp/lib/util/versioning.js
const host = process.env['npm_config_' + validModuleName + '_binary_host_mirror'] || package_json.binary.host; opts.host = fix_slashes(eval_template(host, opts)); ... opts.remote_path = package_json.binary.remote_path ? drop_double_slashes(fix_slashes(eval_template(package_json.binary.remote_path, opts))) : default_remote_path; ... opts.hosted_path = url.resolve(opts.host, opts.remote_path); opts.hosted_tarball = url.resolve(opts.hosted_path, opts.package_name);
可以看到node-pre-gyp會讀取配置文件中是否配置了{(lán)包名}_binary_host_mirror,否則讀取待構(gòu)建的插件package.json中的binary.host配置項(xiàng),所以在prebuild-install中可以生效的{p包名}_binary_host在node-pre-gyp中是無效的,所以針對原生插件我們需要查看插件使用的node-pre-gyp還是prebuild-install來靈活調(diào)整.npmrc中的預(yù)構(gòu)件二進(jìn)制文件下載鏡像源
讓node-pre-gyp通過淘寶源下載預(yù)構(gòu)建文件
npm提供了.npmrc配置文件并注入到進(jìn)程的env環(huán)境變量中,從上面的源碼可知,node-pre-gyp會優(yōu)先讀取npm_config_{包名}_binary_host_mirror(.npmrc中的變量均會被npm添加npm_config_前綴, 所以我們配置時無需添加npm_config_前綴),另外需要值得注意的是npm會將.npmrc中的鍵以下劃線的方式組織且任何非數(shù)字和字母的字符將會被替換為_。所以以canvas舉例來說,配置如下
canvas_binary_host_mirror=https://registry.npmmirror.com/-/binary/canvas
鑒于prebuild-install兼容性更好,針對原生模塊我們在.npmrc中以{包名}_binary_host_mirror={mirror}的格式配置預(yù)構(gòu)建文件下載鏡像
以上就是node gyp安裝canvas原生模塊編譯node pregyp詳解的詳細(xì)內(nèi)容,更多關(guān)于node gyp安裝canvas的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
nodejs安裝與配置過程+初學(xué)實(shí)例解讀
這篇文章主要介紹了nodejs安裝與配置過程+初學(xué)實(shí)例解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
詳解node-ccap模塊生成captcha驗(yàn)證碼
本篇文章主要介紹了node-ccap模塊生成captcha驗(yàn)證碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
通過實(shí)例了解Nodejs模塊系統(tǒng)及require機(jī)制
這篇文章主要介紹了通過實(shí)例了解Nodejs模塊系統(tǒng)及require機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
基于Express+multer實(shí)現(xiàn)文件上傳功能
Multer是Node.js中的一個第三方包,或者說是第三方中間件,主要用于是實(shí)現(xiàn)文件上傳的功能,本文小編講給大家詳細(xì)介紹一下基于Express+multer來實(shí)現(xiàn)文件上傳功能,文章通過代碼示例和圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
windows如何把已安裝的nodejs高版本降級為低版本(圖文教程)
這篇文章主要介紹了windows如何把已安裝的nodejs高版本降級為低版本,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
node封裝一個控制臺進(jìn)度條插件???????詳情
這篇文章主要介紹了node封裝一個控制臺進(jìn)度條插件???????詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08

