Deluze / electron-vue-template

Simple Vue3 + Electron starter template in TypeScript, including ViteJS and Electron Builder
MIT License
534 stars 104 forks source link

How to use static assets #5

Closed damms005 closed 2 years ago

damms005 commented 2 years ago

Since this project is inspired by electron-vue, it is safe to assume that there will be some way to support static assets

How do we assess static assets with this, please?

Deluze commented 2 years ago

If you want to add static/public assets to the front-end you can use the public directory in the renderer directory (see vite config, publicDir).

If you want to copy assets to your main process app directory, you can define them in extraResources in the electron-builder config.

Currently there's no such thing as a static directory to allow for easy access to the assets in both processes. I think it would be a nice addition to this template. I don't mind making this a thing.

Deluze commented 2 years ago

May I ask what you're trying to achieve?

damms005 commented 2 years ago

Big kudos to you for replying very fast, and thanks for the awesome work you are doing with this project.

To answer your question: I want to bundle two files with my app:

  1. an sqlite database file
  2. a splash image/icon

I need a way to reliably reference the two files above during development and also in production.

How do I achieve this, please?

PS: I could not follow the suggestion you made about using the public directory in the renderer directory because the render directory does not have any folder named public and creating the folder works well during dev but when electron app built and released, the resources in this public folder gives Failed to load resource: net::ERR_FILE_NOT_FOUND

Fundamentally, I have no understanding of how files are mapped in dev relative to production. Also, I also have a vague knowledge of how the dev files map. e.g. I changed preload.js to preload.ts to take advantage of TypeScript and the location of the new compiled preload.js just messed things up in terms of relative file references

(if you got a minute, we can pair-program on a few things - I can grant you access to my repo. It's a pretty new and interesting project, nicely written so you may like it. If I must, I don't mind paying for you to take a look!)

Deluze commented 2 years ago

Your first point is completely valid, there's no public subdirectory in the renderer directory, you currently have to make one yourself.

Can you give me a snippet of how your src attribute is set on your img tag on the front-end & related directory tree?

This works perfectly fine for me on the dev & prod environment (assuming src/renderer/public/myImagine.png exists):

<img src="/myImage.png">

For your database, the easiest approach I can come up with is;

{
    "from": "src/main/resources",
    "to": "resources",
    "filter": ["**/*"]
}

To get the path to your database file:

import { app } from 'electron';

const pathToFile = app.getAppPath() + '/resources/yourFileName';

You can add this to your own project, this should solve your issue.

I'm thinking of adding this to the template, since working with files on a desktop app is a common scenario.

If you want to contact me, you can do so on Discord: Deluze#0001. I'm more available there, but I highly prefer to keep the convo here for other developers to refer to.

damms005 commented 2 years ago

This is awesome. I appreciate your swift response, once again.

So, after pulling about a half of my hair out, I figured out that after putting the asset into src/renderer/public/images/full-icon-white.png, referencing it as /images/full-icon-white.png only works in dev, but gives the error I mentioned above in prod. When I removed the leading slash / (i.e. images/full-icon-white.png) it works perfectly well in dev and prod.

For the db part, I was just coding-up a similar approach when I got your response to this GitHub issue. I resolved to creating the database at runtime using app.getPath("userData"). That way, I can predictably work with the location of the db. I'll however try your suggestion and let you know how it goes.

damms005 commented 2 years ago

I'm thinking of adding this to the template, since working with files on a desktop app is a common scenario.

And yes, working with files on a desktop app is a common scenario with electron js, I presume. Such addition will make this template richer. It's a lot of breeze already. Makes me remember Laravel framework. Thanks a lot!

damms005 commented 2 years ago

To get the path to your database file:

import { app } from 'electron';

const pathToFile = app.getAppPath() + '/resources/yourFileName';

Using the above, I wrote this little script to see how things look like in dev and prod:

fs.readdir(app.getAppPath(), function (err, files) {
  if (err) {
    return "Unable to scan directory: " + err;
  }

  console.log(`Content of ${app.getAppPath()} (app.getAppPath()) : `, files.join(", "));
});

In dev, I get:

Content of /home/.../src/main (app.getAppPath()) : backend, icons, main.ts, preload.js, resources

In prod (packages with node scripts/build-vue.js && electron-builder -c config/electron-builder.json --win), I get:

Content of C:\Users\deo\AppData\Local\Programs\schoolserver\resources\app.asar (app.getAppPath()) : .github, LICENSE, buildResources, icon.ico, node_modules, package.json, renderer, src, tailwind.config.js, tsconfig.json, types.ts

As you can see from the output, I cannot simply app.getAppPath() + '/resources/myFileName' and be sure to reference the same file on dev and prod environments.

(Note that I added some items myself). My electron-builder.json however looks like this:

{
    "appId": "myAppIdHere",
    "directories": {
        "output": "dist"
    },
    "nsis": {
        "oneClick": false,
        "perMachine": false,
        "allowToChangeInstallationDirectory": true,
        "shortcutName": "SchoolServer",
        "createDesktopShortcut": true
    },
    "win": {
        "target": "nsis",
        "icon": "src/static/icons/favicon.ico"
    },
    "linux": {
        "target": ["snap"]
    },
    "files": [
        "!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}",
        "!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples}",
        "!**/node_modules/*.d.ts",
        "!**/node_modules/.bin",
        "!src/renderer",
        "!config",
        "!README.md",
        "!scripts",
        "!build",
        "!dist",
        {
            "from": "build/renderer",
            "to": "renderer",
            "filter": ["**/*"]
        },
        {
            "from": "src/main/resources",
            "to": "resources",
            "filter": ["**/*"]
    }
    ],
    "publish": [
        {
            "provider": "github",
            "releaseType": "release"
        }
    ]
}
Deluze commented 2 years ago

Sorry for the late response, I currently have a lot of things going on in my life.

I added handling of static assets to this template, so it's supported natively now. I tested it, and it works on both production and development environments 😄 (Please refer to the README.md on how to use it)

If that still doesn't fix your issue, please re-open this issue.