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)東西, 通常基于表象我們都會認(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開發(fā)一個最簡單的web服務(wù)器實(shí)例講解
在本篇文章里小編給大家整理的是關(guān)于nodejs開發(fā)一個最簡單的web服務(wù)器實(shí)例內(nèi)容,有需要的朋友們可以參考下。2020-01-01Node.js 多線程實(shí)戰(zhàn)小結(jié)
在?Node.js?的世界中,多線程技術(shù)一直是一個受到廣泛關(guān)注的領(lǐng)域,本文主要介紹了Node.js 多線程實(shí)戰(zhàn)小結(jié),具有一定的參考價值,感興趣的可以了解一下2024-01-01Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片詳解
最近項(xiàng)目遇到了個需求,需要將存放圖片進(jìn)行預(yù)覽,所以這篇文章主要給大家介紹了關(guān)于Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01Nodejs中session的簡單使用及通過session實(shí)現(xiàn)身份驗(yàn)證的方法
session的本質(zhì)使用cookie來實(shí)現(xiàn)。本文給大家介紹Nodejs中session的簡單使用及通過session實(shí)現(xiàn)身份驗(yàn)證的方法,對node.js session相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2016-02-02nodejs安裝與配置過程+初學(xué)實(shí)例解讀
這篇文章主要介紹了nodejs安裝與配置過程+初學(xué)實(shí)例解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04