refactor: use vite alternative rollup

This commit is contained in:
草鞋没号
2021-11-11 17:52:50 +08:00
parent be6e33c148
commit b4fc358318
37 changed files with 555 additions and 1187 deletions

View File

@@ -10,19 +10,22 @@ if (!app.requestSingleInstanceLock()) {
let win: BrowserWindow | null = null
function bootstrap() {
async function bootstrap() {
win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
preload: path.join(__dirname, '../preload/index.cjs'),
},
})
if (app.isPackaged) {
win.loadFile(path.join(__dirname, '../render/index.html'))
win.loadFile(path.join(__dirname, '../renderer/index.html'))
} else {
const pkg = await import('../../package.json')
const url = `http://${pkg.env.HOST || '127.0.0.1'}:${pkg.env.PORT}`
win.loadURL(url)
win.maximize()
win.webContents.openDevTools()
win.loadURL(`http://localhost:${process.env.PORT}`)
}
}

View File

@@ -1,7 +1,6 @@
import fs from 'fs'
import { contextBridge, ipcRenderer } from 'electron'
import { domReady } from './utils'
import { injectWsCode } from './ws'
import { useLoading } from './loading'
const isDev = process.env.NODE_ENV === 'development'
@@ -9,10 +8,6 @@ const { removeLoading, appendLoading } = useLoading()
domReady().then(() => {
appendLoading()
isDev && injectWsCode({
host: process.env.HOST, // '127.0.0.1'
port: process.env.PORT_WS as string, // process.env.npm_package_env_PORT_WS
})
})

View File

@@ -1,118 +1,56 @@
function loadingBootstrap() {
const loadingStyle = document.createElement('style')
const loadingBox = document.createElement('div')
loadingStyle.id = 'preload-loading-style'
loadingBox.id = 'preload-loading-box'
loadingStyle.textContent += `
/* https://projects.lukehaas.me/css-loaders/ */
.loading-box { height: 100vh; width: 100vw; position: fixed; left: 0; top: 0; display: flex; align-items: center; background-color: #242424; z-index: 9; }
.load1 .loader,
.load1 .loader:before,
.load1 .loader:after {
background: #ffffff;
-webkit-animation: load1 1s infinite ease-in-out;
animation: load1 1s infinite ease-in-out;
width: 1em;
height: 4em;
}
.load1 .loader {
color: #ffffff;
text-indent: -9999em;
margin: 88px auto;
position: relative;
font-size: 11px;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.load1 .loader:before,
.load1 .loader:after {
position: absolute;
top: 0;
content: '';
}
.load1 .loader:before {
left: -1.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.load1 .loader:after {
left: 1.5em;
}
@-webkit-keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}
@keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}`
loadingBox.classList.add('loading-box', 'load1')
loadingBox.innerHTML += '<div class="loader"></div>'
const appendLoading = () => {
document.head.appendChild(loadingStyle)
document.body.appendChild(loadingBox)
}
const removeLoading = () => {
const _loadingStyle = document.getElementById('preload-loading-style')
const _loadingBox = document.getElementById('preload-loading-box')
// Ensure the remove child exists.
_loadingStyle && document.head.removeChild(_loadingStyle)
_loadingBox && document.body.removeChild(_loadingBox)
};
return { loadingStyle, loadingBox, removeLoading, appendLoading }
}
/** 闪屏 loading */
/**
* https://tobiasahlin.com/spinkit
* https://connoratherton.com/loaders
* https://projects.lukehaas.me/css-loaders
* https://matejkustec.github.io/SpinThatShit
*/
export function useLoading() {
let _isCallRemoveLoading = false
const { appendLoading, removeLoading } = loadingBootstrap();
const className = `loaders-css__square-spin`
const styleContent = `
@keyframes square-spin {
25% { transform: perspective(100px) rotateX(180deg) rotateY(0); }
50% { transform: perspective(100px) rotateX(180deg) rotateY(180deg); }
75% { transform: perspective(100px) rotateX(0) rotateY(180deg); }
100% { transform: perspective(100px) rotateX(0) rotateY(0); }
}
.${className} > div {
animation-fill-mode: both;
width: 50px;
height: 50px;
background: #fff;
animation: square-spin 3s 0s cubic-bezier(0.09, 0.57, 0.49, 0.9) infinite;
}
.app-loading-wrap {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #282c34;
z-index: 9;
}
`
const oStyle = document.createElement('style')
const oDiv = document.createElement('div')
// 5 秒超时自动关闭
setTimeout(() => !_isCallRemoveLoading && removeLoading(), 4999)
oStyle.id = 'app-loading-style'
oStyle.innerHTML = styleContent
oDiv.className = 'app-loading-wrap'
oDiv.innerHTML = `<div class="${className}"><div></div></div>`
return {
appendLoading,
appendLoading() {
document.head.appendChild(oStyle)
document.body.appendChild(oDiv)
},
removeLoading() {
_isCallRemoveLoading = true
removeLoading()
document.head.removeChild(oStyle)
document.body.removeChild(oDiv)
},
}
}

View File

@@ -1,37 +0,0 @@
/**
* Ws client side
*/
/** Inject ws client-side code */
export function injectWsCode(options: {
host: string
port: string | number
}) {
const oScript = document.createElement('script')
oScript.id = 'ws-preload-hot-reload'
oScript.innerHTML = `
${__ws_hot_reload_for_preload.toString()}
${__ws_hot_reload_for_preload.name}(${JSON.stringify(options)})
`
document.body.appendChild(oScript)
}
function __ws_hot_reload_for_preload(options: { host: string; port: string | number }) {
const ws = new WebSocket(`ws://${options.host}:${options.port}`)
ws.onmessage = function (ev) {
try {
console.log('[preload] ws.onmessage:', ev.data)
const data = JSON.parse(ev.data) // { "cmd": "string", data: "string|number" }
if (data.cmd === 'reload') {
setTimeout(() => window.location.reload(), 999)
}
} catch (error) {
console.warn(`ws.onmessage should be accept "JSON.string" formatted string.`)
console.error(error)
}
}
}

View File

@@ -1,89 +0,0 @@
<template>
<h1>{{ msg }}</h1>
<label>
<input type="checkbox" v-model="useScriptSetup" /> Use
<code>&lt;script setup&gt;</code>
</label>
<label>
<input type="checkbox" v-model="useTsPlugin" /> Provide types for
<code>*.vue</code> imports
</label>
<p>
Recommended IDE setup:
<a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
+
<template v-if="!useScriptSetup">
<a
href="https://marketplace.visualstudio.com/items?itemName=octref.vetur"
target="_blank"
>Vetur</a>
+
<a
href="https://marketplace.visualstudio.com/items?itemName=znck.vue-language-features"
target="_blank"
>Vue DX</a>
</template>
<template v-else>
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
</template>
</p>
<p v-if="useTsPlugin">
tsconfig setup:
<br />1. Install and add
<code>@vuedx/typescript-plugin-vue</code> to tsconfig plugins
<br />2. Delete <code>src/shims-vue.d.ts</code>
<br />3. Open
<code>src/main.ts</code> in VSCode
<br />4. Open VSCode command input
<br />5. Search and run "Select TypeScript version" -> "Use workspace version"
</p>
<button @click="count++">count is: {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Vite Docs</a> |
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</a>
</p>
</template>
<script lang="ts">
import { ref, defineComponent } from 'vue'
export default defineComponent({
name: 'HelloWorld',
props: {
msg: {
type: String,
required: true
}
},
setup: () => {
const count = ref(0)
const useScriptSetup = ref(false);
const useTsPlugin = ref(false);
return { count, useScriptSetup, useTsPlugin }
}
})
</script>
<style scoped>
a {
color: #42b983;
}
label {
margin: 0 0.5em;
font-weight: bold;
}
code {
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: #304455;
}
</style>

View File

@@ -1,8 +0,0 @@
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.ts"></script>
</body>
</html>

13
src/renderer/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,18 @@
{
"name": "vite-vue-ts",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview"
},
"dependencies": {
"vue": "^3.2.16"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.9.3",
"typescript": "^4.4.3",
"vite": "^2.6.4",
"vue-tsc": "^0.3.0"
}
}

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,3 +1,9 @@
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<div class="logo-box">
<img style="height:200px;" src="./assets/electron.png" alt="Electron logo">
@@ -6,21 +12,19 @@
<span/>
<img style="height:200px;" alt="Vue logo" src="./assets/vue.png" />
</div>
<HelloWorld msg="Electron@15 + Vite@2 + Vue@3" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.logo-box {
display: flex;
width: 100%;
@@ -30,5 +34,4 @@ export default {
.logo-box span {
width: 74px;
}
</style>

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,52 @@
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<p>
Recommended IDE setup:
<a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
+
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
</p>
<p>See <code>README.md</code> for more information.</p>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
Vite Docs
</a>
|
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</a>
</p>
<button type="button" @click="count++">count is: {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<style scoped>
a {
color: #42b983;
}
label {
margin: 0 0.5em;
font-weight: bold;
}
code {
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: #304455;
}
</style>

8
src/renderer/src/env.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}

13
src/renderer/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
export { }
declare global {
interface Window {
/** Expose some Api through preload script */
bridge: {
fs: typeof import('fs')
ipcRenderer: import('electron').IpcRenderer
removeLoading: () => void
}
}
}

View File

@@ -1,10 +1,9 @@
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App)
.mount('#app')
.$nextTick(window.removeLoading)
.mount('#app')
.$nextTick(window.removeLoading)
console.log('fs', window.fs)
console.log('ipcRenderer', window.ipcRenderer)

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}