The core advantage of Electron is the ability to seamlessly integrate various web technologies and frameworks. This article will detail how to integrate and use various web technologies in Electron.
Frontend Framework Integration
1. React Integration
bash# Create React app npx create-react-app my-electron-app cd my-electron-app # Install Electron npm install --save-dev electron electron-builder # Modify package.json { "main": "public/electron.js", "homepage": "./", "scripts": { "electron": "electron .", "electron-dev": "concurrently \"npm start\" \"wait-on http://localhost:3000 && electron .\"", "electron-pack": "electron-builder", "preelectron-pack": "npm run build" } }
javascript// public/electron.js const { app, BrowserWindow } = require('electron') const path = require('path') let mainWindow function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }) // Load dev server in development const startUrl = process.env.ELECTRON_START_URL || url.format({ pathname: path.join(__dirname, '../build/index.html'), protocol: 'file:', slashes: true }) mainWindow.loadURL(startUrl) if (process.env.ELECTRON_START_URL) { mainWindow.webContents.openDevTools() } } app.whenReady().then(createWindow)
2. Vue Integration
bash# Create Vue app npm create vue@latest my-electron-app cd my-electron-app # Install Electron npm install --save-dev electron electron-builder # Modify package.json { "main": "electron/main.js", "scripts": { "electron": "electron .", "electron:dev": "vite & electron .", "electron:build": "vite build && electron-builder" } }
javascript// electron/main.js const { app, BrowserWindow } = require('electron') const path = require('path') let mainWindow function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }) // Development environment if (process.env.NODE_ENV === 'development') { mainWindow.loadURL('http://localhost:5173') mainWindow.webContents.openDevTools() } else { mainWindow.loadFile(path.join(__dirname, '../dist/index.html')) } } app.whenReady().then(createWindow)
3. Angular Integration
bash# Create Angular app ng new my-electron-app cd my-electron-app # Install Electron npm install --save-dev electron electron-builder # Modify package.json { "main": "electron/main.js", "scripts": { "electron": "electron .", "electron:dev": "ng build --watch & electron .", "electron:build": "ng build && electron-builder" } }
javascript// electron/main.js const { app, BrowserWindow } = require('electron') const path = require('path') let mainWindow function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }) // Development environment if (process.env.NODE_ENV === 'development') { mainWindow.loadURL('http://localhost:4200') mainWindow.webContents.openDevTools() } else { mainWindow.loadFile(path.join(__dirname, '../dist/my-electron-app/index.html')) } } app.whenReady().then(createWindow)
State Management Integration
1. Redux Integration
bashnpm install redux react-redux @reduxjs/toolkit
javascript// store/index.js import { configureStore } from '@reduxjs/toolkit' import rootReducer from './reducers' const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredActions: ['persist/PERSIST'] } }) }) export default store
javascript// preload.js const { contextBridge, ipcRenderer } = require('electron') contextBridge.exposeInMainWorld('electron', { store: { getState: () => ipcRenderer.invoke('store:getState'), dispatch: (action) => ipcRenderer.invoke('store:dispatch', action) } })
javascript// main.js const { ipcMain } = require('electron') const store = require('./store') ipcMain.handle('store:getState', () => { return store.getState() }) ipcMain.handle('store:dispatch', (event, action) => { store.dispatch(action) })
2. Vuex Integration
javascript// store/index.js import { createStore } from 'vuex' export default createStore({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, actions: { increment({ commit }) { commit('increment') } } })
javascript// preload.js const { contextBridge, ipcRenderer } = require('electron') contextBridge.exposeInMainWorld('electron', { store: { getState: () => ipcRenderer.invoke('store:getState'), dispatch: (action) => ipcRenderer.invoke('store:dispatch', action) } })
3. Pinia Integration
javascript// stores/counter.js import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++ } } })
UI Component Library Integration
1. Material-UI Integration
bashnpm install @mui/material @emotion/react @emotion/styled
javascript// App.js import React from 'react' import { Button, TextField, Container, Typography } from '@mui/material' import { createTheme, ThemeProvider } from '@mui/material/styles' const theme = createTheme({ palette: { primary: { main: '#1976d2', }, }, }) function App() { return ( <ThemeProvider theme={theme}> <Container maxWidth="sm"> <Typography variant="h4" component="h1" gutterBottom> Electron + Material-UI </Typography> <Button variant="contained" color="primary"> Click Me </Button> <TextField fullWidth label="Email" variant="outlined" margin="normal" /> </Container> </ThemeProvider> ) } export default App
2. Ant Design Integration
bashnpm install antd
javascript// App.js import React from 'react' import { Button, Input, Typography, Card } from 'antd' import 'antd/dist/reset.css' const { Title } = Typography function App() { return ( <Card style={{ width: 400, margin: '100px auto' }}> <Title level={3}>Electron + Ant Design</Title> <Button type="primary">Click Me</Button> <Input placeholder="Enter your email" style={{ marginTop: 16 }} /> </Card> ) } export default App
3. Element Plus Integration
bashnpm install element-plus
javascript// main.js import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import App from './App.vue' const app = createApp(App) app.use(ElementPlus) app.mount('#app')
vue<!-- App.vue --> <template> <el-card style="width: 400px; margin: 100px auto;"> <h3>Electron + Element Plus</h3> <el-button type="primary">Click Me</el-button> <el-input v-model="email" placeholder="Enter your email" style="margin-top: 16px" /> </el-card> </template> <script> export default { data() { return { email: '' } } } </script>
Build Tool Integration
1. Webpack Integration
javascript// webpack.config.js const path = require('path') module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, resolve: { extensions: ['.js', '.jsx'] }, target: 'electron-renderer' }
2. Vite Integration
javascript// vite.config.js import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], base: './', build: { outDir: 'dist', assetsDir: 'assets' } })
3. Parcel Integration
javascript// .parcelrc { "extends": "@parcel/config-default", "targets": { "default": { "distDir": "dist" } } }
CSS Framework Integration
1. Tailwind CSS Integration
bashnpm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
javascript// tailwind.config.js module.exports = { content: [ "./src/**/*.{js,jsx,ts,tsx}", "./public/index.html" ], theme: { extend: {}, }, plugins: [], }
css/* src/index.css */ @tailwind base; @tailwind components; @tailwind utilities;
jsx// src/App.js function App() { return ( <div className="min-h-screen bg-gray-100 flex items-center justify-center"> <div className="bg-white p-8 rounded-lg shadow-lg"> <h1 className="text-2xl font-bold mb-4">Electron + Tailwind CSS</h1> <button className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"> Click Me </button> </div> </div> ) }
2. Bootstrap Integration
bashnpm install bootstrap
javascript// src/index.js import 'bootstrap/dist/css/bootstrap.min.css' import 'bootstrap/dist/js/bootstrap.bundle.min.js'
jsx// src/App.js function App() { return ( <div className="container mt-5"> <div className="card"> <div className="card-body"> <h1 className="card-title">Electron + Bootstrap</h1> <button className="btn btn-primary">Click Me</button> <input type="email" className="form-control mt-3" placeholder="Enter your email" /> </div> </div> </div> ) }
Chart Library Integration
1. Chart.js Integration
bashnpm install chart.js
javascript// src/ChartComponent.js import React, { useEffect, useRef } from 'react' import Chart from 'chart.js/auto' function ChartComponent() { const chartRef = useRef(null) const chartInstance = useRef(null) useEffect(() => { if (chartRef.current) { const ctx = chartRef.current.getContext('2d') chartInstance.current = new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }) } return () => { if (chartInstance.current) { chartInstance.current.destroy() } } }, []) return <canvas ref={chartRef}></canvas> } export default ChartComponent
2. ECharts Integration
bashnpm install echarts
javascript// src/EChartsComponent.js import React, { useEffect, useRef } from 'react' import * as echarts from 'echarts' function EChartsComponent() { const chartRef = useRef(null) const chartInstance = useRef(null) useEffect(() => { if (chartRef.current) { chartInstance.current = echarts.init(chartRef.current) const option = { title: { text: 'ECharts Example' }, tooltip: {}, xAxis: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: {}, series: [{ name: 'Sales', type: 'bar', data: [5, 20, 36, 10, 10, 20, 30] }] } chartInstance.current.setOption(option) } return () => { if (chartInstance.current) { chartInstance.current.dispose() } } }, []) return <div ref={chartRef} style={{ width: '600px', height: '400px' }}></div> } export default EChartsComponent
Animation Library Integration
1. Framer Motion Integration
bashnpm install framer-motion
javascript// src/AnimatedComponent.js import React from 'react' import { motion } from 'framer-motion' function AnimatedComponent() { return ( <motion.div initial={{ opacity: 0, scale: 0.5 }} animate={{ opacity: 1, scale: 1 }} transition={{ duration: 0.5 }} style={{ width: 200, height: 200, backgroundColor: '#1976d2', borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white' }} > Animated Box </motion.div> ) } export default AnimatedComponent
2. GSAP Integration
bashnpm install gsap
javascript// src/GSAPComponent.js import React, { useEffect, useRef } from 'react' import gsap from 'gsap' function GSAPComponent() { const boxRef = useRef(null) useEffect(() => { gsap.to(boxRef.current, { rotation: 360, duration: 2, repeat: -1, ease: 'linear' }) }, []) return ( <div ref={boxRef} style={{ width: 100, height: 100, backgroundColor: '#1976d2', borderRadius: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white' }} > GSAP Box </div> ) } export default GSAPComponent
Best Practices
1. Environment Variable Management
javascript// .env.development ELECTRON_START_URL=http://localhost:3000 API_URL=http://localhost:5000
javascript// .env.production API_URL=https://api.example.com
javascript// electron/main.js const startUrl = process.env.ELECTRON_START_URL || url.format({ pathname: path.join(__dirname, '../build/index.html'), protocol: 'file:', slashes: true })
2. Hot Reload Configuration
bashnpm install --save-dev electron-reload
javascript// electron/main.js if (process.env.NODE_ENV === 'development') { require('electron-reload')(__dirname, { electron: path.join(__dirname, '..', 'node_modules', '.bin', 'electron'), hardResetMethod: 'exit' }) }
3. Code Splitting
javascript// Use React.lazy const LazyComponent = React.lazy(() => import('./LazyComponent')) function App() { return ( <React.Suspense fallback={<div>Loading...</div>}> <LazyComponent /> </React.Suspense> ) }
Common Questions
Q: How to use React Router in Electron?A: Use React Router normally, but configure history to createHashHistory or use MemoryHistory.
Q: How to handle differences between Electron and Web environments?A: Use environment variables and conditional judgment to distinguish code execution in different environments.
Q: How to optimize Electron app bundle size?A: Use code splitting, Tree Shaking, resource compression and other techniques to optimize bundle size.
Q: How to use Service Worker in Electron?A: Register Service Worker in main process, ensure using it in correct context.