使用 electron-forge 和 webpack 在电子应用程序中设置 sqlcipher

Setting up sqlcipher in an electron app using electron-forge and webpack

我正在尝试打开一个用 sqlcipher 加密的 sqlite3 数据库。我有密码,我可以使用 sqlitebrowser 成功打开它。

我使用 this template 开始我的项目。它基于 electron-forge webpack 插件。

当我输入 yarn start 时,它会创建一个 .webpack 文件夹,所有编译代码都放在里面。当我停止终端命令时,这个文件夹就消失了。

然后我想使用包 @journeyapps/sqlcipher 打开我的数据库,但是这一行导致主进程出错:const sqlite3 = require("@journeyapps/sqlcipher")

错误是: Error: Cannot find module '<<my_path>>/.webpack/main/native_modules/lib/binding/napi-v6-linux-x64/node_sqlite3.node'


包文档说明了关于将它与 electron-forge 一起使用的两件事:

  1. 确保文件夹node_modules/@journeyapps/sqlcipher/lib/binding/napi-v6-linux-x64存在 -> 是的,它存在

  2. 在 package.json "config": { "forge": { "electronRebuildConfig": { "onlyModules": [] // Specify other native modules here if required } } 中使用 electron-rebuild 的 onlyModules 选项禁用此库的重建 -> 我做到了,我添加了代码行

我仍然有错误,但我觉得它可以“轻松”解决(对 webpack 的理解比我多得多)。事实上,一个解决方案是每次启动应用程序时将文件夹 binding/napi-v6-linux-x64 移动到 .webpack 中,对吗?


我试过electron-rebuild -f -w sqlite3,重建成功但没有任何反应,我仍然有同样的错误。


我被困在这里,无法继续我的应用程序,因为它依赖于读取此数据库。 我应该开始一个新项目并避免使用 webpack 吗?您有成功导入并使用此包的项目示例吗?

提前感谢您的帮助!

好吧,我终于想通了。事实上,我尝试了很多小改动,但我设法让应用程序(几乎)按预期工作。

我是如何找到解决方案的

首先:这与库 sqlcipher 本身没有任何关系。其实是webpack在处理native libraries时的配置问题

我使用 Webpack 和 Typescript 模板 (npx create-electron-app test-electron-forge-github --template=typescript-webpack) 开始了 electron-forge 的全新最小安装,并添加了 sqlite3@journeyapps/sqlcipher。它起作用了,所以我在我的 Webpack 配置中做了很多更改,使其更接近 electron-forge 一个。

警告

我所做的更改破坏了 Redux。我选择牺牲 Redux 以使 sqlcipher 工作,因为今天我没有找到让它们都工作的解决方案。

旧的 Webpack 配置文件

main.webpack.js

module.exports = {
  resolve: {
    extensions: ['.ts', '.js']
  },
  entry: './electron/main.ts',
  module: {
    rules: require('./rules.webpack'),
  }
}

renderer.webpack.js

module.exports = {
  resolve: {
    extensions: ['.ts', '.tsx', '.js']
  },
  module: {
    rules: require('./rules.webpack'),
  },
}

rules.webpack.js

module.exports = [
    {
        test: /\.node$/,
        use: 'node-loader',
    },
    {
        test: /\.(m?js|node)$/,
        parser: { amd: false },
        use: {
            loader: '@marshallofsound/webpack-asset-relocator-loader',
            options: {
                outputAssetBase: 'native_modules',
            },
        },
        resolve: {
            fullySpecified: false,
        }
    },
    {
        test: /\.(js|ts|tsx)$/,
        exclude: /node_modules/,
        use: {
            loader: 'babel-loader',
        }
    },
    {
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
            name: '[path][name].[ext]',
        },
    },
    {
        test: /\.(sass|less|css)$/,
        use: [
            'style-loader',
            'css-loader',
            'postcss-loader',
            'sass-loader',
        ]
    },
]

新配置

main.webpack.js

module.exports = {
    resolve: {
        extensions: ['.ts', '.js']
    },
    entry: './electron/main.ts',
    module: {
        rules: [
            ...require('./rules.webpack'),

            {
                test: /\.(m?js|node)$/,
                parser: { amd: true },
                use: {
                    loader: '@vercel/webpack-asset-relocator-loader',
                    options: {
                        outputAssetBase: 'native_modules',
                        emitDirnameAll: true,
                    },
                }
            },
        ],
    }
}

本机模块配置已从 rules.webpack.js 移至 main.webpack.js。这是由于如果规则保留在 rules.wepback.ts 文件中,渲染器进程中会发生错误。 window 将打开但会保持空白。在控制台中,会出现错误:__dirname is not defined。从我采取解决方案的地方看到这个Github issue

另请注意,我更改了加载器,因为之前的加载器没有正常工作。

renderer.webpack.js 不变

rules.webpack.js

module.exports = [
    {
        // We are 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: /\.(js|ts|tsx)$/,
        exclude: /node_modules/,
        use: {
            loader: 'babel-loader',
        }
    },
    {
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
            name: '[path][name].[ext]',
        },
    },
    {
        test: /\.(sass|less|css)$/,
        use: [
            'style-loader',
            'css-loader',
            'postcss-loader',
            'sass-loader',
        ]
    },
]

Redux

我不得不从 rules.webpack.js 中删除这个 属性:

resolve: {
    fullySpecified: false,
}

这一行使 Redux 工作。

结论

我真的不知道它是如何工作的,但它确实有效。如果你和我一样挣扎,我希望它能对你有所帮助。