Atom 和 VSCode 都是基于 Electron 开发的项目,在好奇心的催动下,我就组合了一个简单的 Electron + Snowpack 的框架。
简介
Electron
Electron 是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。通过将 Chromium 和 Node.js 嵌入其二进制文件中,Electron 允许您维护一个 JavaScript 代码库并创建可在 Windows、macOS 和 Linux 上运行的跨平台应用程序——无需本地开发经验。
目前据 Github 统计已有 20 多万个项目使用中,并且由于它很好的兼容 HTML+JS+CSS 的前端开发,也使得许多的项目极为方便的从 B/S 架构移植到 C/S 架构,从而减小了 Desktop 开发者的学习曲线(规避了 Qt 和 Gtk 的学习)。
React
React(有时叫 React.js 或 ReactJS),是一个为数据提供渲染为 HTML 视图的开源 JavaScript 库。React 视图通常采用包含以自定义 HTML 标记规定的其他组件的组件渲染。React 为程序员提供了一种子组件不能直接影响外层组件("data flows down")的模型,数据改变时对 HTML 文档的有效更新,和现代单页应用中组件之间干净的分离。
它由 Facebook、Instagram 和一个由个人开发者和企业组成的社群维护。根据 JavaScript 分析服务 Libscore,React 目前正在被 Netflix、Imgur、Bleacher Report、Feedly、Airbnb、SeatGeek、HelloSign 等很多网站的主页使用。
Typescript
TypeScript 是一种开源的编程语言,该语言项目由微软进行维护和管理。TypeScript 不仅包含 JavaScript 的语法,而且还提供了静态类型检查以及使用看起来像基于类的面向对象编程语法操作 Prototype。C#的首席架构师以及 Delphi 和 Turbo Pascal 的创始人安德斯·海尔斯伯格参与了 TypeScript 的开发。
TypeScript 是为开发大型应用而设计的,并且 TypeScript 可转译成 JavaScript。由于 TypeScript 是 JavaScript 的严格超集,任何现有的 JavaScript 程序都是合法的 TypeScript 程序。
TypeScript 支持为现存 JavaScript 库添加类型信息的定义文件,方便其他程序像使用静态类型的值一样使用现有库中的值。目前有第三方提供常用库如 jQuery、MongoDB、Node.js 和 D3.js 的定义文件。
TypeScript 编译器本身也是用 TypeScript 编写,并被转译为 JavaScript,以 Apache 许可证第二版发布。
Snowpack
Snowpack 是一款闪电般快速的前端构建工具,专为现代 Web 设计。 它是开发工作流程中更重、更复杂的打包程序(如 webpack 或 Parcel)的替代品。Snowpack 利用 JavaScript 的原生模块系统(称为 ESM)来避免不必要的工作,无论您的项目有多大,都能保持快速。
snowpack 不仅内置 esbuild 的支持,同时也可以通过配置来支持 webpack。在开发过程中,Snowpack 为您的应用程序提供未捆绑的服务。每个文件只需要构建一次,然后永久缓存。当文件更改时,Snowpack 会重建该单个文件。
目录结构
react-snowpack-electron-typescript
├── node_modules
├── package.json
├── package-lock.json
├── pnpm-lock.yaml
├── public
│ └── index.html
├── README.md
├── snowpack.config.mjs
├── src
│ ├── App.tsx
│ └── index.tsx
└── tsconfig.json
复制代码
开发流程
推荐使用pnpm来代替 npm 和 yarn。主要是它优越的性能和对 npm 的完美兼容。
pnpx create-snowpack-app react-snowpack-electron-typescript --template @snowpack/app-template-minimal
复制代码
您现在可以前往新目录并使用以下两个命令启动 Snowpack:
cd react-snowpack-electron-typescript
pnpm start
复制代码
您应该会看到您的新网站启动并运行!
现在您已经启动并运行了一个基本项目,要安装 React,请在您的项目目录中运行以下命令:
pnpm add -D react react-dom
复制代码
配置 typescript 运行以下命令:
pnpm add -D typescript @types/react @types/react-dom
复制代码
添加渲染内容:
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Starter Snowpack App" />
<title>Doughnut</title>
</head>
<body>
<div id='root'></div>
<script type="module" src="%PUBLIC_URL%/dist/index.js"></script>
</body>
</html>
复制代码
src/index.tsx
import React from 'react';
import { render } from 'react-dom';
import App from './App.jsx';
render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
复制代码
src/App.tsx
import React from 'react';
function App() {
return (
<>
<h1>my first snowpack+react app</h1>
<h2>hello ❄️Snowpack❄️</h2>
</>
)
}
export default App;
复制代码
在项目的 root 目录下touch tsconfig.json
,用于配置 typescript:
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"jsx": "preserve",
"noEmit": true,
"skipLibCheck": true,
"typeRoots": [
"node_modules/@types",
"types"
]
},
"include": [
"src",
"types"
]
}
复制代码
再执行touch main.js
, 根据官网教程配置:
const { app, BrowserWindow } = require('electron');
function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
contextIsolation: true,
},
});
if (process.env.NODE_ENV === 'production') {
win.loadFile('./build/index.html');
} else {
win.loadURL('http://localhost:8080');
}
// Open the DevTools.
win.webContents.openDevTools();
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
复制代码
参考我的package.json
:
"main": "main.js",
"scripts": {
"dev": "concurrently \"npm run snowpack-dev\" \"npm run electron-start\"",
"electron-start": "electron .",
"snowpack-dev": "snowpack dev",
"snowpack-build": "snowpack build",
"test": "echo \"This template does not include a test runner by default.\" && exit 1"
},
"devDependencies": {
"@types/react": "^17.0.34",
"@types/react-dom": "^17.0.11",
"concurrently": "^6.4.0",
"electron": "15.3.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"snowpack": "^3.3.7",
"typescript": "^4.4.4"
}
复制代码
最后通过pnpm dev
运行。
感谢
在此,特别感谢 github 的 stepanvanzuriak 提供的snowpack-electron-react库, 使我对 snowpack 和 electron 的结合有了全新的认识。
之前,我并不了解 Node.js 和 Webpack 所发展的生态,而且主要从事 MVC 架构下的后端开发。但是,随着对于前端不断研究和发掘之后,越发地觉得软件开发是一件值得钻研一生,充满趣味和创造力的爱好。"Here, I‘m just a kid who interests on it."
评论