This is the 9th day of my participation in Gwen Challenge.

The cause is to climb some beautiful woman’s photo, want to show. A Vue project was generated with Vite scaffolding, but because the images are constantly updated, the folder location cannot be changed. In my experience, a project cannot reference resources outside of the project. So if you want to use NodeJs API to read local files, just Electron can meet the needs of display, also can meet the needs of loading local files.

The overall train of thought

As shown above, electron’s ipcMain and ipcRenderer communication capabilities are utilized for data exchange. So the front end project also needs the ipcRenderer for electron.

Set up the project

Vite initializes the project

npm init @vitejs/app show-avatar -- --template vue-ts
Copy the code

Electron code generation

Create the electron directory and create the main.ts file (part)

function createWindow() {
  const mainWindow = new BrowserWindow({
    height: 600.webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      nodeIntegration: true.contextIsolation: false,},width: 800});const isDev = process.env.NODE_ENV === "development";
  if (isDev) {
    mainWindow.loadURL("http://localhost:8080/");
  } else {
    mainWindow.loadFile(path.join(__dirname, ".."."dist/index.html"));
  }

  mainWindow.webContents.openDevTools();
}
app.on("ready".() = > {
  createWindow();

  app.on("activate".function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});
app.on("window-all-closed".() = > {
  if(process.platform ! = ="darwin") { app.quit(); }});Copy the code

There are several issues that need to be addressed:

How to use typescript in electron? How to use typescript in electron

Use typescript in electron

Create a new tsconfig.json file because it is different in nature from the vite generated file, such as the output directory etc.

{
    "extends": "./tsconfig.json"."compilerOptions": {
        "outDir": "build"."noEmit": false."module": "commonjs"."baseUrl": "."."sourceMap": false,},"include": ["electron"]}Copy the code

Since the desired effect is similar to that of hot update, whenever the main.ts entry file changes, the electron application will be recompiled and built. So nodemon’s help is needed:

npm i nodemon -D
Copy the code

At the same time, vite applications in the development environment and production environment is differentiated, in the development environment using the local server to open the service, real-time compilation to display HTML file content, but in the production environment, is added in the compilation can run directly files. Cross env is also required to differentiate the environment on the electron side:

npm i cross-env -D
Copy the code

After the installation is complete, change the package.json file.

"scripts": {
    "dev": "vite"."build": "vite build"."serve": "vite preview"."dev:electron": "tsc -p tsconfig.electron.json && cross-env NODE_ENV=development electron ./build/main.js"."dev:tsc": "nodemon --watch electron/main.ts --exec 'npm run dev:electron'"
  },
Copy the code

Run the command to start:

npm run dev:tsc
Copy the code

You can see that the program is already running

Get data in electron main process

Added in main.ts:

const str = path.resolve('xxx');
let avaterArr: any[];
glob(
  "**/*.png",
  {
    cwd: str,
  },
  (err, files) = >{ avaterArr = files; }); ipcMain.on("request-data".async(event: IpcMainEvent, ... arg:any[]) = > {const avaterBuffer = avaterArr.splice(0.10).map(async (v: string) = > {const file = await fsPromise(path.join(str, v));
    const arrayBufferView = new Uint8Array(file);
    return arrayBufferView;
  });
  const data = await Promise.all(avaterBuffer);
  await event.reply("data", { root: str, avaterArr: data });
});
Copy the code

Use electron’s ipcRenderer on the front end

Modify the helloWorld. vue file to import {ipcRenderer} from “electron”; After vite is updated, the electron deguer reports an error and ipcRenderer cannot be used. There are two problems.

First, using electron on the front requires the Node environment, so there are two configurations in the main.ts file:

nodeIntegration: true.contextIsolation: false.Copy the code

The second problem is that improt cannot be used in the Node environment, so it has to be changed to require. A Vite plugin was developed to help solve this problem

Vite plug-in writing

Using vite exposed hook Transform to solve this problem, it is important to note that in the development environment we need to convert import to require, but in the production environment we do not need to package electron into HTML. External; external; external; external; external; external; external;

const reloadElectornPlugin = (): VitePlugin= > {
  let configEnv: ConfigEnv;
  return {
    name: "reload-electorn-plugin".config(conf, env) {
      configEnv = env;
    },
    transform: (code: string, id: string) = > {
      const opts = {
        excludes: ["electron"]};if(configEnv.command ! = ="serve") return code;

      const parsed = path.parse(id);
      if(! extensions.includes(parsed.ext))return code;
      // Then change to Babel
      const node: any = acorn.parse(code, {
        ecmaVersion: "next".sourceType: "module"});let codeRet = code;
      node.body.reverse().forEach((item) = > {
        if(item.type ! = ="ImportDeclaration") return;
        if(! opts.excludes.includes(item.source.value))return;

        const statr = codeRet.substring(0, item.start);
        const end = codeRet.substring(item.end);
        const deft = item.specifiers.find(
          ({ type }) = > type= = ="ImportDefaultSpecifier"
        );
        const deftModule = deft ? deft.local.name : "";
        const nameAs = item.specifiers.find(
          ({ type }) = > type= = ="ImportNamespaceSpecifier"
        );
        const nameAsModule = nameAs ? nameAs.local.name : "";
        const modules = item.specifiers
          .filter(({ type }) = > type= = ="ImportSpecifier")
          .reduce((acc, cur) = > acc.concat(cur.imported.name), []);
        
      codeRet = `${statr}const { ${modules.join(",")} } = require(${ item.source.raw })${end}`;
      });
      returncodeRet; }}; };Copy the code

It should be ready by now.

More article summarizes

See more article activities, wrote a few hydrology, also wrote a few attentively, whenever want to pick up the pen to write an article, always worried about their output of high quality articles, afraid of misleading others, so pigeon many days, today is still paying debts. At the same time, I also reflected on my own situation: my basic knowledge is weak, I have not formed a system, and my thinking is not clear enough, resulting in a lot of nonsense in the process of writing the article, including the knowledge is not pure enough. So, more fuel.