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 } }
四.不抽離 webpack配置的方案antd(npm run build 后找不到圖片路徑,暫未解決)
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'
五.抽離 webpack配置的方案
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"
然后 npm run package
成功后頁面會生成一個package文件,里面有我們打包好的文件

