ElectronForge v6.0.3打包原生模块leveldb-zlib报错求助
问题:Electron Forge + Webpack 打包原生模块 leveldb-zlib 报错且临时方案耗时过长
我有一个基于 ElectronForge v6.0.3、TypeScript 和 Webpack 的项目,引入了原生 npm 模块 leveldb-zlib。执行 electron-forge start 时可正常运行,但执行 electron-forge make 时出现报错。模块仅在主进程通过 import { LevelDB } from "leveldb-zlib"; 导入,未在渲染进程使用。
相关配置文件
webpack.rules.ts
import type { ModuleOptions } from 'webpack'; export const rules: Required<ModuleOptions>['rules'] = [ // Add support for native node modules { // We're specifying native_modules in the test because the asset relocator loader generates a // "fake" .node file which is really a cjs file. test: /native_modules[/\\].+\.node$/, use: 'node-loader', }, { test: /\.(m?js|node)$/, parser: { amd: false }, use: { loader: '@vercel/webpack-asset-relocator-loader', options: { outputAssetBase: 'native_modules', }, }, }, { test: /\.tsx?$/, exclude: /(node_modules|\.webpack)/, use: { loader: 'ts-loader', options: { transpileOnly: true, }, }, }, { test: /\.(woff|woff2|ttf|eot|png|jpg|svg|gif)$/i, use: ['file-loader'] } ];
webpack.main.config.ts
import type { Configuration } from 'webpack'; import { rules } from './webpack.rules'; export const mainConfig: Configuration = { /** * This is the main entry point for your application, it's the first file * that runs in the main process. */ entry: './src/index.ts', // Put your normal webpack config below here module: { rules, }, resolve: { extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'], }, externals: { "leveldb-zlib": "leveldb-zlib" } };
临时解决方案(编译耗时极长)
我通过在 forge.config.ts 中添加以下 hooks 实现了编译,但编译耗时极长(该方案为适配 TypeScript 修改后的版本):
import type { ForgeConfig } from '@electron-forge/shared-types'; import { MakerSquirrel } from '@electron-forge/maker-squirrel'; import { MakerZIP } from '@electron-forge/maker-zip'; import { MakerDeb } from '@electron-forge/maker-deb'; import { MakerRpm } from '@electron-forge/maker-rpm'; import { WebpackPlugin } from '@electron-forge/plugin-webpack'; import { mainConfig } from './webpack.main.config'; import { rendererConfig } from './webpack.renderer.config'; import * as path from "path"; import * as fs from "fs"; import { spawn } from "child_process"; const textDecoder = new TextDecoder(); const config: ForgeConfig = { packagerConfig: {}, rebuildConfig: {}, makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})], plugins: [ new WebpackPlugin({ mainConfig, renderer: { config: rendererConfig, entryPoints: [ { html: './src/index.html', js: './src/renderer.ts', name: 'main_window', preload: { js: './src/preload.ts', }, }, ], }, }), ], hooks: { readPackageJson: async (_forgeConfig, packageJson) => { // only copy deps if there isn't any if (Object.keys(packageJson.dependencies).length === 0) { const buffer = fs.readFileSync(path.resolve(__dirname, 'package.json')); const originalPackageJson = JSON.parse(textDecoder.decode(buffer)); Object.keys(mainConfig.externals as Record<string, unknown>).forEach(key => { packageJson.dependencies[key] = originalPackageJson.dependencies[key]; }); } return packageJson; }, packageAfterPrune: async (_forgeConfig, buildPath) => { return new Promise((resolve, reject) => { const npmInstall = spawn('npm', ['install'], { cwd: buildPath, stdio: 'inherit', shell: true }); npmInstall.on('close', (code) => { if (code === 0) { resolve(); } else { reject(new Error('process finished with error code ' + code)); } }); npmInstall.on('error', (error) => { reject(error); }); }); } } }; export default config;
需求
寻求更高效的解决方案来解决打包报错问题,避免过长的编译耗时。
内容的提问来源于stack exchange,提问作者Marshall Walker
相关产品推荐
相关产品推荐

