執行使用Electron-forge打包的electron package時遇到在js檔案中執行的exec命令和在渲染程序中執行的node.js api出現奇怪問題的解決思路

lightmon發表於2024-10-10

js檔案中執行的exec命令出錯

很可能是專案中使用了一些非html, css, js的原始檔,比如用了Makefile來編譯了cpp程式碼,或者執行的exec命令為cp dir/something.cpp之類的檔案操作命令。

可以使用修改forge.config.js檔案配置的方式,使得npm run make的時候自動把Makefileexec命令中用到的檔案和目錄複製到打包後的根目錄中。

具體來說,可以給forge.config.js檔案的module.exports/packagerConfig下新增如下配置:

afterExtract: [
  (extractPath, electronVersion, platform, arch, done) => {
    // Copy the Makefile to the build directory
    var makefile = path.join(__dirname, 'Makefile');
    var backup = path.join(__dirname, 'backup');
    var dest = extractPath;
    fs.copyFileSync(makefile, path.join(dest, 'Makefile'));
    // 把backup目錄遞迴地複製到dest目錄下面
    copyDir(backup, path.join(dest, 'backup'));
    done();
  }
]

其中,copyDir函式的定義為:

function copyDir(src, dest) {
  fs.mkdirSync(dest, { recursive: true }); // 建立目標目錄

  // 遞迴遍歷源目錄
  fs.readdirSync(src).forEach(file => {
    const srcPath = path.join(src, file);
    const destPath = path.join(dest, file);

    // 判斷是檔案還是目錄
    const stat = fs.statSync(srcPath);
    if (stat.isDirectory()) {
      copyDir(srcPath, destPath); // 遞迴複製子目錄
    } else {
      fs.copyFileSync(srcPath, destPath); // 複製檔案
    }
  });
}

渲染程序中執行的node.js api出錯

可能是打包後的瀏覽器核心安全設定更高?

建議electron專案中還是儘量前後端分離比較好,在主程序中用node.js的庫,即各種require,在渲染程序(瀏覽器程序)中就用web頁面的庫,即各種importexport

我把renderer.js中的fs模組的操作都刪了,把呼叫的fs模組函式都轉移到了main.js裡面去執行,這個錯誤就消失了。

比如原本在renderer.js中是這樣:

document.getElementById('run-compare').addEventListener('click', () => {
  // 獲取code1和code2的內容
  var code1Content = editor1.state.doc.toString(); 
  var code2Content = editor2.state.doc.toString();

  // 獲取專案根目錄
  rootPath = __dirname;

  // 建立檔案路徑
  const filePath1 = path.join(rootPath, 'code1.cpp');
  const filePath2 = path.join(rootPath, 'code2.cpp');

  // 寫入檔案
  fs.writeFile(filePath1, code1Content, (err) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log('code1寫入成功');
  });

  fs.writeFile(filePath2, code2Content, (err) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log('code2寫入成功');
  });

  ipcRenderer.send('run-compare');
});

現在我就改成了這樣:

document.getElementById('run-compare').addEventListener('click', () => {
  // 獲取code1和code2的內容
  var code1Content = editor1.state.doc.toString(); 
  var code2Content = editor2.state.doc.toString();

  // 獲取專案根目錄
  rootPath = __dirname;

  // 建立檔案路徑
  const filePath1 = path.join(rootPath, 'code1.cpp');
  const filePath2 = path.join(rootPath, 'code2.cpp');

  // 傳送訊息給主程序
  ipcRenderer.send('compare-codes', { code1: code1Content, code2: code2Content });

  ipcRenderer.send('run-compare');
});

然後在main.js中新增對compare-codes事件的監聽:

ipcMain.on('compare-codes', (event, data) => {
  const { code1, code2 } = data;
  fs.writeFileSync('code1.cpp', code1);
  fs.writeFileSync('code2.cpp', code2);
});

總之,以後用node.js寫專案,最好還是要把前後端分離,不能在被某個html檔案引用的js指令碼中呼叫node.js中的庫。

相關文章