如今写个前端谁还不用个构建工具,天天早晨回去,找对应的项目目录,打开命令行工具,敲个
npm run xxx
,重复得有点无聊。特别面对着日渐增加的项目数量,好但愿有个工具能够帮我管理全部的项目,两手抓,一手起项目,一手抓个人叉烧包。emmmm...html
项目添加:经过拖拽项目package.json
文件到应用面板完成解析(不是.json文件?你试试) vue
项目管理:红色区域展现添加的项目,支持切换/删除/重命名;黄色区域展现package.json
中的scripts
脚本,点击便可执行;绿色区域管理该项目下的多个命令行窗口,支持增长/删除/切换;蓝色区域为命令行执行区域。 node
一次过知足您三个愿望:react
node v8
+ electron v4.0 + macOSX v10.13(还没支持windows,由于node-pty在windows上一直运行出错,使用官网demo测试都不行,黔驴技穷呀。大佬们有兴趣能够试试,指点下我 连接)electron —— electron-quick-startwebpack
package.json目录的main
字段指定electron应用的主渲染进程文件,除了该js文件之外,其余的都属于在渲染进程运行。git
"main": "electron/index.js"github
在electron/index.js中,配置electron加载的文件——开发环境下加载开发服务器文件,生成环境下加载本地文件。web
isDev
? mainWindow.loadURL('http://localhost:3000/index.html')
: mainWindow.loadFile(path.join(__dirname, '../react/build/index.html'))
复制代码
react —— create-react-appvuex
把react的index.html指向electron目录,在react/config/paths.js
中修改
appHtml: resolveApp('../electron/index.html')
react的脚手架没有默认支持stylus?心好痛啊。本身动手,丰衣足食。create-react-app脚手架默认把webpack配置藏到node_modules中,须要执行npm run eject
后才能释放出来。找到/config/webpack.config.js
文件,参照sass的配置,写一遍stylus的,这样以后xx.styl
的文件会被stylus-loader
处理,xx.module.styl
的文件会被当成局部样式处理,相似于.vue
文件的<style lang="stylus" scoped>
const stylusRegex = /\.(styl)$/;
const stylusModuleRegex = /\.module\.(styl)$/;
// module里追加stylus的配置
{
test: stylusRegex,
exclude: stylusModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'stylus-loader'
),
sideEffects: true,
},
{
test: stylusModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'stylus-loader'
),
},
复制代码
使用开发者工具。安装react-devtool(待续...)
componentDidUpdate
应用窗口resize后,web终端模拟器都要从新适配父元素的大小。在react中涉及dom更新后须要处理的逻辑(放在callback函数里),一是使用this.setState({}, callback)
;二是在componentDidUpdate
里处理。前者特别方便快捷,更新行为跟数据源绑定到一块儿,相似于vue
的vm.$nextTick
。后者就要麻烦不少了(谁叫你把状态放在全局中处理呢),要特别设定一个isNew
变量来决定dom的更新回调是否执行。
ref属性引用的传递
ref属性不属于props
,所以不走寻常路,在高阶组件里须要“委曲求全”地转发(官宣)。
// Layout.js
import Main from 'Main.js'
export default class Layout extends Component {
constructor (props) {
super(props)
this.mainRef = React.createRef()
}
render () {
return (
<Main ref={this.mainRef} />
)
}
}
// Main.js
class Main extends Component {
render () {
const {
myRef
} = this.props
return (
<div ref={myRef}></div>
)
}
}
export default React.forwardRef((props, ref) => {
// 把ref引用赋给名为'myRef'的props,达到传递的目的
return (
<Main
myRef={ref}
{...props}
/>
)
})
复制代码
异步dispatch action
可以使用redux-thunk/redux-saga,因为nodejs环境原生支持文件同步读取fs.readFileSync
,因此如下两种方法都可以。
reselect
相似vuex的computed属性
// /store/selectors/project.js
import { createSelector } from 'reselect'
// 计算依赖值
const projectsSelector = state => state.project.projects
const activeIdSelector = state => state.project.activeId
export const getXtermList = createSelector(
projectsSelector,
activeIdSelector,
(projects, id) => {
// 入参对应createSelector前两位参数的结果值
const project = projects.find(p => p.id === id)
// must return a new "xterms", otherwhiles, it cannot update. 这里使用[ ...project.xterms ]是返回新的对象引用,不然不被看作有更新
const xterms = (project && project.xterms) ? [...project.xterms] : []
return xterms
}
)
// /src/Tab.js
import { getXtermList } from '/store/selectors/project.js'
@connect(
state => ({
xterms: getXtermList(state),
})
)
class Tabs extends Component {
render () {
<div>
{
this.props.xterms.map(() => (
<div>
{/* ... */}
</div>
))
}
</div>
}
}
export default Tabs
复制代码
redux-persist
node-pty伪终端是node和系统shell之间的通信中间库;xterm.js负责绘制浏览器端的终端模拟器。web终端使用表单模拟输入,基本具有全部表单的api能力,支持代码自动触发和手动输入触发。
const os = window.require('os')
const pty = window.require('node-pty')
const Terminal = window.require('xterm').Terminal
class Xterm {
constructor () {
this.xterm = null
this.ptyProcess = null
this.createTerminal()
}
createTerminal () {
const shell = Xterm.shell
// 建立伪终端进程
this.ptyProcess = pty.spawn(shell, [], this.opts)
// 建立web终端模拟器
this.xterm = new Terminal()
this.initEvent()
}
initEvent () {
// web终端模拟器监听用户输入,写入系统shell
this.xterm.on('data', data => {
this.ptyProcess.write(data)
})
// node-pty监听系统shell输出,写入web终端模拟器
this.ptyProcess.on('data', data => {
this.xterm.write(data)
})
}
/**
* 获取系统信息,拿到对应的shell终端
*/
static get shell () {
return window.process.env[os.platform() === 'win32' ? 'COMSPEC' : 'bash']
}
}
复制代码
window.require
,就能够逃过webpack的编译main process 调试
热重启:
// package.json
"scripts": {
"start": "electron .",
"watch": "nodemon --watch . --ignore 'app' --exec \"npm start\"",
"rebuild": "electron-rebuild -f -w node-pty"
}
复制代码
打印:使用electron-log,打印信息和node调试信息同样展现在控制台中
主进程和渲染进程的通讯
Electron为主进程( main process)和渲染器进程(renderer processes)通讯提供了多种实现方式,如可使用ipcRenderer 和 ipcMain模块发送消息。经过这种方式能够模拟右键菜单进行系统级的操做(如打开系统的某个文件目录)
// react
const { ipcRenderer } = window.require('electron')
// renderer process 发送显示右键菜单的请求
ipcRenderer.send('show-context-menu'})
// electron
const {
app,
BrowserWindow,
ipcMain,
Menu,
MenuItem
} = require('electron')
const template = [
{
label: '重命名',
click: this.rename.bind(this)
},
{
label: '打开文件目录',
click: this.openFileManager.bind(this)
}
]
// 建立右键菜单
const menu = Menu.buildFromTemplate(template)
// main process 监听renderer process请求
ipcMain.on('show-context-menu', (e, data) => {
const win = BrowserWindow.fromWebContents(e.sender)
// 弹出右键菜单
menu.popup(win)
})
复制代码
原生desktop app菜单
让换肤/toggle控制台/刷新程序等app功能常驻于程序菜单项里
打包。工具使用electron-builder,确保系统环境 必定要使用nodev8版本
必定要使用nodev8版本
必定要使用nodev8版本
,曾经使用了v10
,把网上几乎全部的demo项目都运行过了一遍,发现都在打包过程当中出错,绝望地死磕了三、4天。
package.json
中加入 "homepage": "./"。由于electron应用加载资源是使用本地文件的方式,使用相对路径,而之前web服务后台习惯使用绝对路径加载。node原生模块的编译
若是项目里使用了一些node原生模块(用 C++ 编写的 Node.js 扩展),在安装后须要通过编译才能被使用。例如该项目使用了node-pty
,能够经过如下两种办法编译,不编译会报错!!第一种方式在npm install
后将自动执行,第二种则须要手动执行。
To ensure your native dependencies are always matched electron version 源自electron-builder的说明
"postinstall": "electron-builder install-app-deps"
"rebuild": "electron-rebuild -f -w node-pty"
electron依赖下载。windows和mac都有全局缓存路径的,若是使用npm下载卡住没法进行下去,能够尝试去淘宝镜像网站(electron下载连接)下载文件放到对应系统的缓存目录,而后使用npm install安装已经下载的版本号,缓存的electron文件便可被使用。(我?固然是搬个🍇(和谐了)直接下载)
发布release版本
使用Travis配合electron-builder --publish指令,git push
后自动经过travis-ci打包,把app提交到github的release中。
GitHub上已提供打包后的程序,欢迎下载使用或者下载源码自行构建(目前仅支持macOS)下载体验地址
安装程序
安装时提示非信任应用程序??抱歉,来不及作macOS签名。因此须要自行容许运行程序。处理教程
点个赞
或star
,谢谢鼓励