mac m1 electron生产环境使用prisma,sqlite

news/2024/9/20 6:19:04 标签: macos, electron, sqlite

最近在用electron开发一个适合自己的小应用,技术选型中使用prisma和sqlite在进行数据存储,写这篇文章的目的就是用来记录下遇到的一些问题。

开发环境使用prisma

1、开发环境使用prisma非常的简单,只需要按照教程安装prisma,然后执行npx prisma init --datasource-provider sqlite 即可。脚本会生成schema文件
在schema文件中编写自己的模型。
开发环境中执行

npx prisma migrate dev --name xxxx

可以看到在我们的prisma目录下会有个迁移文件夹migrations,里面会生成我们的sql。这时候我们可以直接使用@prisma/client

import { PrismaClient } from '@prisma/client'
const prismaInstance = new PrismaClient()

可以用prismaInstance实例来进行数据库操作咯,这时候如果你使用的是ts并且安装了prisma的vs code插件你就会发现它的语法提示非常人性化,如果你之前有orm的基础就可以直接上手。

在生产环境中使用

一般情况下开发环境有nodejs环境,全局安装了prisma我们只需要把migrations文件夹拷贝到开发环境并且执行下面命令就行。

npx prisma migrate deploy

electronelectronbuilderprisma_30">在electron中你使用electron-builder打包要怎么做才能正常使用prisma呢?

1、首先你得把migrations文件夹拷贝到安装包中,在package.json中使用extraResources来将我们所需要的migrations文件移入到安装包中。

"build": {
    "extraResources": [
      {
        "from": "prisma/migrations",
        "to": "resources/prisma/migrations"
      },
      {
        "from": "prisma/schema.prisma",
        "to": "resources/prisma/schema.prisma"
      }
    ]
}

这样打包后如果你打开 join(process.resourcesPath,'resources/prisma')这个路径就会发现migrations文件夹已经被移入,然后我们要执行npx prisma migrate delploy,但是在我们的electron生产环境中没有npx命令该怎么做,这时候我们就需要使用prisma提供的二进制来进行操作了。
根据不同的环境prisma会提供不同的二进制,比如我这边是mac m1,那么你就要在schema.prisma中加入以下内容,prisma运行过程中就会去下载drawin-arm64的二进制

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "darwin-arm64"]
}

下载完你就会发现node_modules/@prisma/engines下会多出两个二进制文件

在这里插入图片描述

libquery是sql引擎,没有它就不能进行数据库操作。
schema就是我们刚才说的执行npx prisma migrate deploy的,可以理解为全局安装的prisma就是执行的这个二进制。
这样我们就可以直接使用二进制来执行我们的命令咯,前提是我们把二进制拷贝到了安装包内,你也可以使用extraResources属性,但我这边并没有写,因为electron一般会对文件都打包进asar二进制中,但是如果有些三方库的二进制打入二进制会出现一些意想不到的问题,所以可以在package.json设置asarUnpack,意味着不用吧这些文件进行二进制打包。

"build":{
 "asarUnpack": [
      "**/node_modules/prisma/**/*",
      "**/node_modules/@prisma/**/*"
    ]
}

我们怎么拿到那些不需要被打包的二进制呢?我们代码中怎么写呢,路径是什么呢?代码如下

const appUnpackedPath = app.getAppPath().replace('app.asar', 'app.asar.unpacked')
const schemePath = electronIsDev ? resolve(__dirname, '../node_modules/@prisma/engines/schema-engine-darwin-arm64') : resolve(appUnpackedPath, './node_modules/@prisma/engines/schema-engine-darwin-arm64')

上面是对开发环境进行了判断,读者可以自行处理,appUnkpackedPath就是我们的二进制存放路径。
我们可以开发编写一套统一的处理代码,这套也是我从github某篇issue上直接拿下来的。

export async function runPrisma(command: string[]) {
  try {
    const exitCode = await new Promise((r, _) => {
      const prismaPath = resolve(electronIsDev ? resolve(__dirname, '../node_modules') : resolve(appUnpackedPath, './node_modules'), 'prisma', 'build', 'index.js')
      logger.info(process.cwd(), 'cwd')
      const child = fork(prismaPath, command, {
        cwd: electronIsDev ? process.cwd() : join(appUserPath, 'resources'),
        env: {
          ...process.env,
          DATABASE_URL: process.env.DATABASE_URL,
          PRISMA_QUERY_ENGINE_LIBRARY: queryPath,
          PRISMA_SCHEMA_ENGINE_BINARY: schemePath,
        },
        stdio: 'pipe',
      })

      child.on('message', (msg) => {
        logger.info(msg)
      })

      child.on('error', (err) => {
        logger.error('Child process got error:', err)
      })

      child.on('close', (code) => {
        logger.info(code)
        r(code)
      })

      child.stdout?.on('data', function (data) {
        // console.log(data)

        logger.info('prisma: ', data.toString())
      })

      child.stderr?.on('data', function (data) {
        logger.error('prisma: ', data.toString())
      })
    })

    if (exitCode !== 0) {
      throw Error(`command ${command} failed with exit code ${exitCode}`)
    }

    return exitCode
  } catch (e) {
    logger.error(e)
    throw e
  }
}

我们执行只需要传入参数进行即可

要注意我们的命令执行路径,也就是cwd参数要传入正确,要确保路径下面的文件内容格式符合prisma要求,prisma/migrations/xx类似这样即可

runPrisma(['migrate', 'deploy'])

上面代码中还有个queryPath,这个path是用来获取执行sql的引擎的,如果没有他我们就不能进行数据库操作,开发环境不需要我们指定引擎的二进制,但是在electron中需要我们来指定一下,有两种方法一种是使用环境变量process.env.PRISMA_QUERY_ENGINE_BINARY = queryPath,但是这种方法我这一直没成功,所以在github上找到了一种隐藏api方式来直接指定

const prismaInstance = new PrismaClient({
  __internal: {
    engine: {
      binaryPath: queryPath,
    },
  },
} as any)

这个__internal是一个非标准api,但是使用了发现能正常执行了。如果不指定就会一直报错
Can not spawn Query Engine when using Electron

结语

最后寻找感兴趣开发小工具的小伙伴一起来开发,目前我给这个产品取名Ew Box,Everything You Want,技术栈使用如下:

对以上技术感兴趣,还有一些不错的idea的小伙伴都可以加入哟,后续可以使用你感兴趣的任何技术栈都可以集成其中
产品没有盈利目的,都是些简单的小功能点,做一款适合自己的小工具,就单纯想扩展或者提升技术面的小伙伴可以尝试加入哟
目前产品功能有压缩图片/密码箱/todo日历等功能,有想法的朋友可以一起加入哟。


http://www.niftyadmin.cn/n/5666738.html

相关文章

自动驾驶,被逼着上市?

上市了,然后呢? 转载:定焦(dingjiaoone)原创 作者 | 黎明 编辑 | 魏佳 很多人从来没体验过自动驾驶,但自动驾驶公司正在抢着上市。 今年以来,已有十多家自动驾驶相关公司启动上市流程。最新上…

CDH Hive集群的create/drop慢问题,在200s 多一点处理分析

现象: CREATE TABLE test911 (SN String,PN_CODE String); Total time spent in this metastore function was greater than 1000ms : createTable_(Table, )200091 Hive集群的 create/drop 操作时间基本都稳定在 200s 多一点。 分析: HMS会实时向Sentr…

网课视频怎么录制?零基础屏幕录制方法分享

随着在线教育的兴起,网课录制成为了教师和学习者不可或缺的技能之一,无论是想要分享知识、制作教程,还是记录学习过程,掌握屏幕录制方法都至关重要。 这时候我们就需要一款简单易用、功能齐全的屏幕录制软件,市面上有…

kafka 超详细的消息订阅与消息消费几种方式

kafka 消息订阅与消息消费几种方式 本文主要内容 消费者订阅几种方式 订阅多个主题 按正则表达式订阅 消息消费几种方式 按分区消费 按主题消费 不区分 “ 笔者建议一开始学习Kafka最好不要用SpringBoot 集成方式,因为SpringBoot推崇用注解方式,比如KafkaList…

组件封装有哪些注意事项—面试常问优美回答

组件封装有哪些注意事项—面试常问优美回答 关键点及回答建议与代码案例 组件设计原则 关键点:高内聚低耦合、接口清晰、职责单一。回答建议: “在设计组件时,我遵循高内聚低耦合的原则,确保组件内部逻辑紧密相关,同…

sensitive-word 敏感词 v0.20.0 数字全部匹配,而不是部分匹配

敏感词系列 sensitive-word-admin 敏感词控台 v1.2.0 版本开源 sensitive-word-admin v1.3.0 发布 如何支持分布式部署? 01-开源敏感词工具入门使用 02-如何实现一个敏感词工具?违禁词实现思路梳理 03-敏感词之 StopWord 停止词优化与特殊符号 04-…

课题分享:宿舍管理系统小程序,基于微信小程序+SSM+mysql

一、前言介绍 互联网概念的产生到如今的蓬勃发展,用了短短的几十年时间就风靡全球,使得全球各个行业都进行了互联网的改造升级,标志着互联网浪潮的来临。在这个新的时代,各行各业都充分考虑互联网是否能与本行业进行结合&#xf…

一键转换:Python如何轻松将PPT转换为PDF

哈喽,大家好,我是木头左! 准备工作:安装必要的Python库 在开始之前,确保你的系统中已经安装了Python环境。接下来,需要安装python-pptx和pdf2image这两个库。可以通过pip命令进行安装: pip install python-pptx pdf2image如果你使用的是Anaconda,那么可以使用: con…