项目初始化
- 项目目录结构
├── 项目根目录
│ ├── app
│ │ ├── main // 主进程模块
│ │ │ |—— electron.ts
│ │ │
│ │ ├── renderer // 渲染进程模块
│ │ └── other // 需要之前打包好的一个项目使用webview引入(项目需要)
│ ├── package.json
│ └──
|___
- 修改package.json
主要是注意里面的main字段,修改为以下(webpack打包的主线程代码所在位置)
"main": "./dist/electron.js"
-
安装依赖
-
安装electron
yarn add electron@11.1.1 -D 安装遇到问题 可在根目录下增加.npmrc,增加以下内容 registry=https://registry.npm.taobao.org/ electron_mirror="https://npm.taobao.org/mirrors/electron/"
-
安装react相关
yarn add react react-router react-router-dom react-dom
-
安装babel(使用babel-loader加ts的插件去编译ts)
yarn add @babel/polyfill yarn add @babel/core @babel/cli @babel/preset-env @babel/preset-react @babel/preset- typescript @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs -D
-
根目录创建babel.config.js
module.exports = { presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'], plugins: [ '@babel/plugin-transform-runtime', [ '@babel/plugin-transform-modules-commonjs', { allowTopLevelThis: true, loose: true, lazy: true } ], [ 'import', // antd按需加载 { libraryName: 'antd', libraryDirectory: 'es', style: 'css' } ] ] }
-
安装webpack相关(这里使用的还是4版本,5版本尝试了下,一堆报错改的心累就放弃了)
yarn add webpack@4.44.1 webpack-cli@3.3.12 webpack-dev-server webpack-merge html-webpack-plugin@4.3.0 clean-webpack-plugin babel-loader -D
-
创建webpack配置
根目录下添加一个webpack文件夹,里面主要有以下文件
- webpack.base.js
- webpack.main.dev.js
- webpack.main.prod.js
- webpack.render.dev.js
- webpack.render.prod.js
// webpack.base.js const path = require('path') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const isDev = process.env.NODE_ENV !== 'production' const getCssLoaders = importLoaders => [ isDev ? 'style-loader' : MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { modules: false, sourceMap: isDev, importLoaders } } ] module.exports = { resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'], alias: { '@src': path.join(__dirname, '../', 'app/renderer'), '@viz': path.join(__dirname, '../', 'app/viz/index1.html') } }, module: { rules: [ { oneOf: [ { test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { cacheDirectory: true } } }, { test: /\.css$/, use: getCssLoaders(0) }, { test: /\.less$/, use: [ ...getCssLoaders(1), { loader: 'less-loader', options: { sourceMap: isDev } } ] }, { test: /\.(jpg|png|jpeg|gif)$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash].[ext]', outputPath: 'images/' } } ] } ] } ] }, plugins: [new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: ['**/*', '!electron.js'] })] }
// webpack.main.dev.js const path = require('path') const baseConfig = require('./webpack.base.js') const webpackMerge = require('webpack-merge') const mainConfig = { entry: path.resolve(__dirname, '../app/main/electron.ts'), target: 'electron-main', output: { filename: 'electron.js', path: path.resolve(__dirname, '../dist') }, devtool: 'inline-source-map', mode: 'development' } module.exports = webpackMerge.merge(baseConfig, mainConfig)
// webpack.main.prod.js const path = require('path') const baseConfig = require('./webpack.base.js') const webpackMerge = require('webpack-merge') const webpack = require('webpack') const prodConfig = { entry: path.resolve(__dirname, '../app/main/electron.ts'), target: 'electron-main', output: { filename: 'electron.js', path: path.resolve(__dirname, '../dist') }, devtool: 'inline-source-map', mode: 'production', plugins: [ new webpack.DefinePlugin({ __dirname: '__dirname' }) ] } module.exports = webpackMerge.merge(baseConfig, prodConfig)
// webpack.render.dev.js const path = require('path') const webpackMerge = require('webpack-merge') const baseConfig = require('./webpack.base.js') const HtmlWebpackPlugin = require('html-webpack-plugin') const devConfig = { mode: 'development', entry: { index: path.resolve(__dirname, '../app/renderer/app.tsx') }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, '../dist') }, target: 'electron-renderer', devtool: 'inline-source-map', devServer: { contentBase: path.join(__dirname, '../dist'), compress: true, host: '127.0.0.1', port: 7001, hot: true }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../app/renderer/index.html'), filename: path.resolve(__dirname, '../dist/index.html'), chunks: ['index'] }) ] } module.exports = webpackMerge.merge(baseConfig, devConfig)
// webpack.render.prod.js const path = require('path') const webpackMerge = require('webpack-merge') const baseConfig = require('./webpack.base.js') const HtmlWebpackPlugin = require('html-webpack-plugin') const prodConfig = { mode: 'production', entry: { index: path.resolve(__dirname, '../app/renderer/app.tsx') }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, '../dist') }, target: 'electron-renderer', devtool: 'inline-source-map', plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../app/renderer/index.html'), filename: path.resolve(__dirname, '../dist/index.html'), chunks: ['index'] }) ] } module.exports = webpackMerge.merge(baseConfig, prodConfig)
-
编写一些代码
-
在main文件夹下的electron.ts加入如下代码
import path from 'path' import { app, BrowserWindow } from 'electron' import isDev from 'electron-is-dev' let mainWindow = null function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, enableRemoteModule: true, contextIsolation: false, webviewTag: true } }) if (isDev) { mainWindow.loadURL(`http://127.0.0.1:7001`) mainWindow.webContents.openDevTools() } else { mainWindow.loadURL(`file://${path.join(__dirname, '../dist/index.html')}`) } mainWindow.on('close', () => { mainWindow = null }) } app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) })
-
在renderer文件夹下添加index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> </body> </html>
-
在renderer文件夹下添加app.tsx
import React from 'react'; import ReactDOM from 'react-dom'; import { HashRouter as Router, Route, Switch } from 'react-router-dom'; function App() { return ( <Router> <Switch> <Route path="/"> <div>基础模板</div> </Route> </Switch> </Router> ); } ReactDOM.render(<App />, document.getElementById('root'));
-
-
配置package.json文件的脚本
scripts": { "start": "concurrently \"yarn start:render\" \"wait-on http://127.0.0.1:7001 && yarn start:main \"", // 开发环境一个指令整体启动项目,需要安装concurrently和wait-on "start:main": "webpack --config ./webpack/webpack.main.dev.js && electron ./dist/electron.js", // 启动主进程 "start:render": "webpack-dev-server --config ./webpack/webpack.render.dev.js", // 启动渲染进程 "build": "yarn build:main && yarn build:render", // 打包同上 "build:main": "webpack --config ./webpack/webpack.main.prod.js", "build:render": "webpack --config ./webpack/webpack.render.prod.js", "ele:pack": "electron-builder" // 打包后使用electron-builder(需要安装)构建exe文件 }
-
一些其他的额外配置
- elsint
- husky
- css采用css in js
- 路由使用react-router-config来管理
-
更多配置见git仓库
-
主要参考掘金小册 Electron + React 从 0 到 1 实现简历平台实战
-
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!