vite+electron+vue3 (ts) 搭建开发框架

具体使用版本:vite v2.4.3+electron v13.1.7+vue v3.0.5

目录结构如下:

node_modules  依赖包

  public  vite创建的目录,为vue服务的,实际没多大用

  release  打包后编译输出的目录,该目录的根目录下存放打包后的安装包

    bundled  该目录存放vue打包后的文件(html js css img等)

    win-unpacked  该目录存放编译后生成的可执行文件及相关的dll,不包含安装包

  resource  资源目录

  script     此目录存放各种脚本,比如编译脚本,启动脚本,签名脚本等

  src  源码目录

    render  渲染进程源码目录
    
    preload  (好像不需要也行。估计vue-cli搭建的才需要)vue页面中不能使用nodejs和electron,electron手册中要求通过preload.js隔离vue页面和main.js的交互

    main  主进程源码目录

    common  两个进程都会用到的共用源码目录

  package.json  项目配置文件

  index.html  vue3的入口页面
  
  .env  配置文件

  .gitignore  git目录过滤文件


第一步:

通过vite 相关命令 新建一个vue3的项目

参考:https://cn.vitejs.dev/guide/#scaffolding-your-first-vite-project

省略这一步的安装过程

第一步的注意点:

1、cmd 控制台需要管理员权限


第二步:

到项目根目录(vite命令搭建好的项目根目录):

cmd(管理员身份)

cd /d 项目根目录

执行添加 electron 模块

npm i -D electron@latest

第三步:

添加 dotenv 依赖模块

# with npm
npm install dotenv
# or with Yarn 
yarn add dotenv

在src/main目录下新建一个 app.ts 文件内容如下:

/**
 * electron 主文件
 */
 import { join } from 'path'
 import { app, BrowserWindow } from 'electron'
 import dotenv from 'dotenv'
 
 dotenv.config({ path: join(__dirname, '../.env') })
 
let win: BrowserWindow;
 
 function createWindow() {
   // 创建浏览器窗口
   win = new BrowserWindow({
     width: 1024,
     height: 768,
     webPreferences: {
       nodeIntegration: true,
       contextIsolation: false,
       //preload:join(__dirname, '../preload/preload.js')
     },
   })
   win.webContents.openDevTools();


   const URL = app.isPackaged
     ? `file://${join(__dirname, '../index.html')}` // vite 构建后的静态文件地址
     : `http://localhost:${process.env.PORT}` // vite 启动的服务器地址

   win.loadURL(URL);
 }
 app.whenReady().then(() => {
  createWindow()
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  }
)})
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

第四步:

添加 @rollup/plugin-node-resolve 依赖:

npm install @rollup/plugin-node-resolve --save-dev

添加 @rollup/plugin-commonjs 依赖:

npm install --save-dev rollup-plugin-commonjs

添加 @rollup/plugin-typescript 依赖:

npm install --save-dev @rollup/plugin-typescript

添加 @rollup/plugin-alias 依赖:

npm install --save-dev @rollup/plugin-alias

添加 @rollup/plugin-json 依赖:

npm install --save-dev @rollup/plugin-json


在script目录下新建rollupjs的配置文件,用于指定编译ts文件转js文件 (rollup.config.ts)

import { join } from 'path';
import { RollupOptions } from 'rollup';
// 为了支持import xx from 'xxx'
import nodeResolve from '@rollup/plugin-node-resolve';
// 为了让rollup识别commonjs类型的包,默认只支持导入ES6
import commonjs from '@rollup/plugin-commonjs';
// ts转js的编译器
import typescript from '@rollup/plugin-typescript';
import alias from '@rollup/plugin-alias';
// 支持加载json文件
import json from '@rollup/plugin-json';
// 读取package.json
import pkg from '../package.json';

import { builtins } from './utils';

export default (env = 'production') => {
  const options: RollupOptions = {
    input: join(__dirname, '../src/main/app.ts'),
    output: [{
      file: pkg.main, 
      format: 'cjs',// 使用 CommonJs 模块化
      name: 'ElectronMainBundle',
      sourcemap: true,
    }
      // , {
      // file: "dist/preload/preload.js", 
      // format: 'cjs',// 使用 CommonJs 模块化
      // name: 'preload',
      // sourcemap: true,
      // }
    ],
    plugins: [
      typescript({
        exclude: 'node_modules/**',
        typescript: require('typescript'),
      }),
      json(),// 支持引入 json 文件
      commonjs({
        // 支持 CommonJs 模块
          include: 'node_modules/**'
      }),
      nodeResolve(),// 支持 node_modules 下面的包查找
      alias({
        //路径别名
        entries: [
          { find: '@render', replacement: join(__dirname, '../src/render') },
          { find: '@main', replacement: join(__dirname, '../src/main') },
          { find: '@src', replacement: join(__dirname, '../src') },
          { find: '@root', replacement: join(__dirname, '..') },
        ]
      }),
    ],
    external: [
      // 打包避开内置模块
      ...builtins(),
      'electron',
    ],
  }

  return options
}


添加 chalk 依赖模块:

npm install chalk

添加 http 依赖模块:

npm i http

在script新建utils.ts文件 用于监听vite 启动再启动electron

import { builtinModules } from 'module'
import { get } from 'http'
import { green } from 'chalk'

/** 轮询监听 vite 启动 */
export function waitOn(arg0: { port: string | number; interval?: number; }) {
  console.log("轮询监听 vite 启动");
  return new Promise(resolve => {
    const { port, interval = 149 } = arg0
    const url = `http://localhost:${port}`
    let counter = 0
    const timer: NodeJS.Timer = setInterval(() => {
      get(url, res => {
        clearInterval(timer)
        console.log('[waitOn]', green(`"${url}" are already responsive.`), `(${res.statusCode}: ${res.statusMessage})`)
        resolve(res.statusCode)
      }).on('error', err => {
        console.log('[waitOn]', `counter: ${counter++}`)
      })
    }, interval)
  })
}

/** node.js builtins module */
export const builtins = () => builtinModules.filter(x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x))

添加minimist 依赖模块:

npm install -g @types/minimist


在script目录下新建 build-main.ts 文件 根据rollup.config.ts配置文件指定的ts文件转js文件

/**
 * electron 打包
 */
import { join } from 'path';
import { spawn, ChildProcess } from 'child_process';
import { watch, rollup, OutputOptions } from 'rollup';
import minimist from 'minimist';
import chalk from 'chalk';
import ora from 'ora';
import electron from 'electron';
import dotenv from 'dotenv';
import { waitOn } from './utils';
import options from './rollup.config';
import { main } from '../package.json';
 
dotenv.config({ path: join(__dirname, '../.env') });
 
const argv = minimist(process.argv.slice(2));
const opts = options(argv.env);
const TAG = '[build-main.ts]';
const spinner = ora(`${TAG} Electron build...`);
 
 if (argv.watch) {
   waitOn({ port: process.env.PORT as string }).then(msg => {
     const watcher = watch(opts)
     let child: ChildProcess
     watcher.on('change', filename => {
       const log = chalk.green(`change -- ${filename}`)
       console.log(TAG, log)
     });
     watcher.on('event', ev => {
       if (ev.code === 'END') {
         if (child) child.kill()
         child = spawn(
           electron as any,
           [join(__dirname, `../${main}`)],
           {
             stdio: 'inherit',
             env: Object.assign(process.env, { NODE_ENV: argv.env }),
           })
       } else if (ev.code === 'ERROR') {
         console.log(ev.error)
       }
     });
   });
 } else {
   spinner.start();
   rollup(opts)
     .then(build => {
       spinner.stop()
       console.log(TAG, chalk.green('Electron build successed.'))
       build.write(opts.output as OutputOptions)
     })
     .catch(error => {
       spinner.stop()
       console.log(`\n${TAG} ${chalk.red('构建报错')}\n`, error, '\n')
     });
 }

第五步:

配置 package.json 文件

首先添加 concurrently 依赖模块

npm install -g concurrently

然后修改package.json如下:

image.png

{
  "name": "electron-vue",
  "version": "0.0.0",
  "main": "dist/main/app.js",
  "license": "MIT",
  "scripts": {
    "dev": "concurrently -n=vue,ele -c=green,blue \"npm run dev:vue\" \"npm run dev:ele\"",
    "dev:vue": "vite",
    "dev:ele": "node -r ts-node/register script/build-main --env=development --watch",
    "build": "vue-tsc --noEmit && vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "chalk": "^4.1.1",
    "concurrently": "^6.2.0",
    "dotenv": "^10.0.0",
    "fs-extra": "^8.1.0",
    "ora": "^5.4.1",
    "vue": "^3.0.5"
  },
  "devDependencies": {
    "@rollup/plugin-alias": "^3.1.4",
    "@rollup/plugin-commonjs": "^19.0.1",
    "@rollup/plugin-json": "^4.1.0",
    "@rollup/plugin-node-resolve": "^13.0.2",
    "@rollup/plugin-typescript": "^8.2.3",
    "@types/minimist": "^1.2.2",
    "@vitejs/plugin-vue": "^1.2.5",
    "@vue/compiler-sfc": "^3.0.5",
    "electron": "^13.1.7",
    "electron-chromedriver": "^13.0.0",
    "ts-node": "^10.1.0",
    "typescript": "^4.3.2",
    "vite": "^2.4.3",
    "vue-tsc": "^0.0.24"
  },
  "keywords": [
    "vite",
    "electron",
    "vue3",
    "rollup"
  ]
}

第六步:

配置 tsconfig.json

image.png

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    // 目标文件所在路径
    "outDir": "./dist",
    "baseUrl": "./",
    "lib": ["esnext", "dom","ES6"],
    "paths": {
      "@render/*": ["src/render/*"],
      "@main/*": ["src/main/*"],
      "@src/*": ["src/*"],
      "@root/*": ["./*"]
    },
    "allowSyntheticDefaultImports": true
  },
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "script/*.ts"]
}

第七步:

配置 vite.config.ts 

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { join } from 'path';
require('dotenv').config({ path: join(__dirname, '.env') })

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    port: parseInt(process.env.PORT),
  },
  build: {
    outDir: join(__dirname, 'dist/render'),
    assetsDir: '', // 相对路径 加载问题
    rollupOptions: {
      output: {
        format: 'cjs', // 配置 Rollup 打包输出 CommonJs 格式
      },
      external: ['electron'], // 告诉 Rollup 不要去打包 electron
    },
  },
  optimizeDeps: {
    exclude: ['electron'], // 告诉 Vite 不要转换 electron 模块
  },
});

第八步:

修改根目录的index.html

image.png

然后运行:

npm run dev

效果:

image.png

第九步:引用electron API或者Node API

vue组件内:

const electron = window.require('electron');
const fse = window.require('fs-extra')
const fs = window.require('fs')

效果:

image.png


.env文件内容:

image.png

本文作者:admin

本文链接:https://www.javalc.com/post/71.html

版权声明:本篇文章于2021-07-22,由admin发表,转载请注明出处:分享你我。如有疑问,请联系我们

WPF MVVM(数据驱动模式) 简易代码生成工具

发表评论

取消
扫码支持