React+electron项目搭建 打包
一.搭建react+electron项目
1.创建一个react项目
create-react-app my-app
cd my-app
npm start
看下页面是否打开,是否运行正确。
注意:如果页面没有src文件夹,
第一种:卸载全局安装包:
npm uninstall -g create-react-app
yarn global remove create-react-app
然后 npm start,浏览器会打开页面。
如果第一种不行,用第二种
第二种:忽视掉本地的create-react-app已存在的版本进行项目的创建
npx --ignore-existing create-react-app my-app
2. 引入electron
npm install electron --save-dev
3. 配置
1):在package.json配置入口文件,具体如下:
“main”:”main.js”
修改启动命令:
2):main.js文件编写
const { app, BrowserWindow } = require('electron')
const path = require('path')
const pkg = require('./package.json');
let mainWindow
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// 加载应用----react 打包
//mainWindow.loadURL(url.format({
//pathname: path.join(__dirname, './build/index.html'),
//protocol: 'file:',
//slashes: true
//}))
// 加载应用----适用于 react 项目和开发阶段npm run electron
mainWindow.loadURL('http://localhost:3000/');
mainWindow.on('closed', function () {
mainWindow = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', function () {
if (mainWindow === null) createWindow()
})
启动:
npm start npm run dev/electron 两个命令都执行时,浏览器打开页面,会打开桌面应用。
二.搭建react路由
npm install --save react-router-dom
src/Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ReactMap from './router/routerMap';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<div>
<ReactMap />
</div>
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
src/router/routerMap.js
import React from 'react'
import { HashRouter as Router, Route } from 'react-router-dom'
import Login from '../pages/Login/Login'
class ReactMap extends React.Component {
updateHandle() {
console.log("每次router变化后触发")
}
render() {
return (
<Router history={this.props.history}>
<Route exact path="" component={Login} />
</Router>
)
}
}
export default ReactMap;
三.搭建redux
npm install --save react-redux
npm install --save redux
npm install --save redux-thunk
src/Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ReactMap from './router/routerMap';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import rootRedux from './redux'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
const enhancer = composeEnhancers(applyMiddleware(thunk));
const store = createStore(
rootRedux,
enhancer
// applyMiddleware(thunk),
// window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
ReactDOM.render(
<div>
<Provider store={store}>
<ReactMap />
</Provider>
</div>
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
src/redux/index.js
import { combineReducers } from 'redux'
import set from './set'
export default combineReducers({
data: set
})
src/redux/set.js
const set = (state = [], action) => {
switch (action.type) {
case 'GET_LIST':
return {
...state,
list: action.list
}
case 'SET_USERNAME':
return {
...state,
userName: action.list
}
default: return state
}
}
export default set
src/actions/index.js
export const getList = () => {
return {
type: 'GET_LIST',
list: '1111'
}
}
export const setUserName = (list) => {
return {
type: 'SET_USERNAME',
list: list
}
}
四.不抽离
cnpm install --save react-app-rewired customize-cra
cnpm install --save babel-plugin-import
1.配置less,less-loader
cnpm install --save less less-loader
2. 根目录新建config-overrides.js文件
const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra')
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
// addLessLoader 添加less的引用
// fixBabelImports 按需加载antd组件
// addWebpackAlias 路径别名配置
/* 路径别名配置 */
module.exports = override(
addWebpackAlias({
'@': resolve('src'),
components: resolve('./src/components'),
assets: resolve('./src/assets'),
static: resolve('./src/static'),
img: resolve('./src/static/img'),
js: resolve('./src/static/js'),
css: resolve('./src/static/css'),
}),
/* antd组件按需加载 */
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1DA57A' },
}),
);
3. 修改package.json文件,目录结构
4. 使用:页面引用less
import '@/static/css/index.less'
五.抽离
npm run eject
运行后会出现config文件夹,在里面配置less 和路径别名配置
1.配置less,less-loader
cnpm install --save less less-loader
在webpack.config.js里面进行less的配置
2.配置路径别名
在webpack.config.js里面进行路径别名的配置
六.打包
1.打包的准备工作:
在package.json,里面加上”homepage”:”.”
在public里面加上main.js 和 package.json 和 preload.js
package.json
{
"name":"crh_chat",
"version":"1.0-test",
"main":"main.js",
"author": {
"name":"YOURNAME"
},
"license": "MIT"
}
main.js
如果需要引用一些模块就加入preload: path.join(__dirname, 'preload.js'),不用可以注释掉这段
const electron = require('electron');
const path = require('path');
// 控制应用生命周期的模块
const { app } = electron;
// 创建本地浏览器窗口的模块
const { BrowserWindow } = electron;
// 指向窗口对象的一个全局引用,如果没有这个引用,那么当该javascript对象被垃圾回收的
// 时候该窗口将会自动关闭
let win;
function createWindow() {
// 创建一个新的浏览器窗口
win = new BrowserWindow({
width: 1920,
height: 1080,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
});
// 并且装载应用的index.html页面
win.loadURL(`file://${__dirname}/index.html`);
// 打开开发工具页面
//win.webContents.openDevTools();
// 当窗口关闭时调用的方法
win.on('closed', () => {
// 解除窗口对象的引用,通常而言如果应用支持多个窗口的话,你会在一个数组里
// 存放窗口对象,在窗口关闭的时候应当删除相应的元素。
win = null;
});
}
// 当Electron完成初始化并且已经创建了浏览器窗口,则该方法将会被调用。
// 有些API只能在该事件发生后才能被使用。
app.on('ready', createWindow);
/* var mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false
}
}); */
// 当所有的窗口被关闭后退出应用
app.on('window-all-closed', () => {
// 对于OS X系统,应用和相应的菜单栏会一直激活直到用户通过Cmd + Q显式退出
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 对于OS X系统,当dock图标被点击后会重新创建一个app窗口,并且不会有其他
// 窗口打开
if (win === null) {
createWindow();
}
});
preload.js 这里引入了electron,需要用的时候,window.electron
global.electron = require('electron')
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
有两个地方需要preload.js 外面那个是开发时要用的,public里面是打包后需要用到的。
2.npm run build
成功后会出现build文件夹,双击index.html在浏览器打开,可以正常运行
3.npm run package
在pacakge.json里面的scripts配置
"package": "electron-packager ./build package0514 --win --out package/ --arch=x64 --app-version=1.1.0 --electron-version=8.0.0"
然后
成功后页面会生成一个package文件,里面有我们打包好的文件