【问题标题】:Maintaining native module dependencies for node.js and electron at the same time同时维护 node.js 和 electron 的原生模块依赖
【发布时间】:2019-10-23 16:20:19
【问题描述】:

我正在尝试构建一个需要 nodegit 的 Electron 应用程序,这是一个原生模块。据我所知,本机模块的本机库必须以与运行时引擎(我的意思是 Node.js 或 Electron)相同的 NODE_MODULE_VERSION 为目标。

例如,如果我的 Electron 使用 NODE_MODULE_VERSION 64 运行,那么我的 nodegit 应该安装一个以 NODE_MODULE_VERSION 64 为目标的本机库。

当前我的项目中有一些测试,我想在 Electron 和 Node.js 上运行它们。因为(1)Electron 更接近最终产品的环境,(2)Node.js 更容易调试。

要实现这个目标,原生模块必须同时兼容 Electron 和 Node.js。然而,这几乎是不可能的。

有趣的是,从列出NODE_MODULE_VERSIONElectron versions(在此图表中称为Chrome 版本)和Node.js versions 的图表中,他们的NODE_MODULE_VERSION 很少匹配强>。很难找到使用同样NODE_MODULE_VERSION 的 Node.js 的 Electron 版本。因此,我不得不使用不同的NODE_MODULE_VERSION 来使用 Electron 和 Node.js。换句话说,本机模块只能与 Electron 或 Node.js 中的一个兼容,而不是两者都兼容。

我很好奇是否可以在不重新构建模块的情况下将 Node.js 和 Electron 使用的原生模块分开,或者是否有版本切换功能可以让我快速切换原生模块的版本?

如果有人能分享一种方法让 Electron 和 Node.js 使用相同的 NODE_MODULE_VERSION,那就更好了。

【问题讨论】:

    标签: node.js npm electron


    【解决方案1】:

    不知道有没有更好的解决方案,我想出了一个非常简单的脚本,可以复制和粘贴带有环境选择的模块文件(附在下面)。 仍然非常感谢任何关于如何解决这个问题的好主意。

    'use strict';
    
    const fs = require('fs-extra');
    const path = require('path');
    
    let args = process.argv.slice(2);
    let cachePath = path.resolve(__dirname, '../.module_cache');
    let configPath = path.join(cachePath, '.config');
    let modulePath = path.resolve(__dirname, '../node_modules');
    
    wrapper(args)
    .catch(err => {
        console.error(err);
    })
    
    function wrapper(args) {
        switch (args[0]) {
            case 'save':
                return saveModule(args[1], args[2]);
    
            case 'load':
                return loadModule(args[1], args[2]);
    
            case 'drop':
                if (args.length === 3) {
                    return dropModuleEnvironment(args[1]);
                }
                else {
                    return dropModule(args[1]);
                }
    
            case 'ls':
                return listModules();
    
            case 'which':
                return printWhichModule(args[1]);
    
            case 'versions':
                return listModuleVersions(args[1]);
    
            case 'help':
                printUsage();
                return Promise.resolve();
    
            default:
                printUsage();
                return Promise.reject(new Error("Unexcepted arguments: " + args.join(', ')));
        }
    }
    
    function printUsage() {
        console.log(`
      Usage:
        save <module> <environment>: cache a module environment for later use
        load <module> <environment>: load a previously saved module environment, and set it to be active
        drop <module> [environment]: remove all cached module environments, 
                                     or when [environment] is provided, remove the specified environment
        ls: list all cached modules and their current environment
        which <module>: show the active environment for the module
        versions <module>: list all available environments for the module. Active environment is marked by "*"
        help: show this help info`);
    }
    
    function saveModule(moduleName, envName) {
        let storePath = path.join(cachePath, moduleName, envName);
        let sourcePath = path.join(modulePath, moduleName);
        return fs.emptyDir(storePath)
        .then(() => {
            return fs.copy(sourcePath, storePath);
        })
        .then(() => {
            return updateConfig(moduleName, ".system.");
        });
    }
    
    function loadModule(moduleName, envName) {
        let storePath = path.join(cachePath, moduleName, envName);
        let targetPath = path.join(modulePath, moduleName);
        return whichModuleVersion(moduleName)
        .then(currentVersion => {
            if (currentVersion === envName) {
                console.log(`Not loading ${envName} for ${moduleName} because it is current version`);
                return Promise.resolve();
            }
            else {
                return fs.emptyDir(targetPath)
                .then(() => {
                    return fs.copy(storePath, targetPath);
                })
                .then(() => {
                    return updateConfig(moduleName, envName);
                })
            }
        })
    }
    
    function dropModuleEnvironment(moduleName, envName) {
        let storePath = path.join(cachePath, moduleName, envName);
        return fs.remove(storePath)
        .then(() => {
            return fs.readFile(configPath)
            .then(configRaw => {
                let config = JSON.parse(configRaw);
                let currentEnv = config[moduleName];
                if (currentEnv && currentEnv === envName) {
                    config[currentEnv] = '.system.';
                }
    
                return JSON.stringify(config);
            })
            .then(configRaw => {
                return fs.writeFile(configPath, configRaw);
            });
        });
    }
    
    function dropModule(moduleName) {
        return fs.remove(path.join(cachePath, moduleName))
        .then(() => {
            return fs.readFile(configPath)
            .then(configRaw => {
                let config = JSON.parse(configRaw);
                if (config[moduleName]) {
                    delete config[moduleName];
                }
    
                return JSON.stringify(config);
            })
            .then(configRaw => {
                return fs.writeFile(configPath, configRaw);
            });
        })
    }
    
    function listModules() {
        return fs.readFile(configPath)
        .then(configRaw => {
            let config = JSON.parse(configRaw);
            Object.keys(config).forEach(moduleName => {
                printModuleVersion(moduleName, config[moduleName]);
            })
        })
    }
    
    function printWhichModule(moduleName) {
        return whichModuleVersion(moduleName)
        .then(version => {
            printModuleVersion(moduleName, version);
        });
    }
    
    function listModuleVersions(moduleName) {
        let modulePath = path.join(cachePath, moduleName);
        return fs.exists(modulePath)
        .then(exists => {
            if (exists) {
                let currentVersion;
                return whichModuleVersion(moduleName)
                .then(version => currentVersion = version)
                .then(() => fs.readdir(modulePath))
                .then(envNames => {
                    envNames.forEach(envName => {
                        if (currentVersion === envName) {
                            console.log('* ' + envName);
                        }
                        else {
                            console.log('  ' + envName);
                        }
                    });
                });
            }
            else {
                console.log('not installed');
            }
        })
    
    }
    
    function whichModuleVersion(moduleName) {
        return fs.readFile(configPath)
        .then(configRaw => {
            let config = JSON.parse(configRaw);
            return config[moduleName];
        });
    }
    
    function printModuleVersion(moduleName, moduleVersion) {
        console.log(`${moduleName}: ${moduleVersion || 'not installed'}`);
    }
    
    function updateConfig(moduleName, envName) {
        return fs.readFile(configPath)
        .then(configRaw => {
            let config = JSON.parse(configRaw);
            config[moduleName] = envName;
            return JSON.stringify(config);
        })
        .then(configRaw => {
            fs.writeFile(configPath, configRaw);
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-20
      • 1970-01-01
      • 1970-01-01
      • 2023-02-10
      • 2017-08-07
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      相关资源
      最近更新 更多