翻译 | 《JavaScript Everywhere》第19章 将现有的Web应用程序与Electron集成

翻译 | 《JavaScript Everywhere》第19章 将现有的Web应用程序与Electron集成

写在最前面

大家好呀,我是毛小悠,是一位前端开发工程师。正在翻译一本英文技术书籍。

为了提高大家的阅读体验,对语句的结构和内容略有调整。如果发现本文中有存在瑕疵的地方,或者你有任何意见或者建议,可以在评论区留言,或者加我的微信:code_maomao,欢迎相互沟通交流学习。

(σ゚∀゚)σ..:*☆哎哟不错哦

第19章 将现有的Web应用程序与Electron集成

我喜欢收集浏览器书签,就像一个小孩在沙滩上收集贝壳一样。我不是一定要收集它们,但是到一天结束时,我已经在几个浏览器窗口中打开了许多选项卡。我并不是炫耀,但我怀疑应该不止我一个人是这样。所以,我使用了一些最常用的Web应用程序的桌面版本。通常,这些应用程序对比网页版并没有什么优势,但是独立应用程序的便利性使它们全天易于访问、查找和切换。

在本章中,我们将研究如何获取现有的Web应用程序并将其包装在Electron Shell中。在继续之前,你将需要安装示例APIWeb应用程序的本地副本。如果你还没有阅读整本书,请访问附录A和附录B进行操作。

集成我们的Web应用程序

在上一章中,我们设置了Electron应用程序加载index.html文件。我们也可以加载特定的URL。在本例中,我们将从加载本地运行的Web应用程序的URL开始。首先,请确保你的Web应用程序和API在本地运行。然后我们可以更新src/index.js文件,首先将BrowserWindow中的nodeIntegration设置为false。这将避免本地运行的节点应用程序访问外部站点的安全风险。

webPreferences: { nodeIntegration: false
},

现在,更改window.loadFile('index.html');,如下:

window.loadURL('http://localhost:1234');

运行Web应用程序

你的Web应用程序的本地实例将需要在1234端口上运行。如果你一直在阅读本书,请从Web应用程序目录的根目录运行npm start来启动开发服务器。

这将指示Electron加载URL,而不是文件。现在,如果你使用npm start运行该应用程序,你会看到它已加载到Electron窗口中,但有一些警告。

警告和错误

Electron浏览器开发者工具和我们的终端显示了大量警告和错误。让我们看一下其中的每一个(见图19-1)。

19-1。我们的应用程序正在运行,但显示大量错误和警告。

首先,我们的终端显示了大量SyntaxErrorUnexpected Token errors.此外,我们的开发者工具会显示几个相应的警告,指出DevTools无法解析SourceMap。这两个错误与Parcel生成source mapElectron读取source map的方式有关。不幸的是,结合我们正在使用的技术,似乎没有针对此问题的合理解决方案。最好的选择是禁用JavaScript源映射。在应用程序窗口的开发人员工具中,单击“设置”,然后取消选中“启用JavaScript源映射”(请参见图19-2)。

翻译 | 《JavaScript Everywhere》第19章 将现有的Web应用程序与Electron集成_第1张图片

19-2。禁用源映射将减少错误和警告的数量

现在,如果退出并重新启动应用程序,将不再看到与源地图有关的问题。这样做的代价是,在Electron内调试客户端JavaScript可能会更加困难,但是值得庆幸的是,我们仍然可以在Web浏览器中访问此功能和我们的应用程序。

最后两个警告与Electron的安全性有关。在将生产应用程序捆绑在一起之前,我们将解决这些问题,但是现在值得探讨这些警告是什么。

  • Electron Security Warning (Insecure Resources)电子安全警告(资源不安全)

此警告通知我们,我们正在通过http连接加载Web资源。在生产中,我们应始终通过https加载资源,以确保隐私和安全。在开发中,通过http加载本地主机不是问题,因为我们将引用托管网站,该网站在捆绑的应用程序中使用https

  • Electron Security Warning (Insecure Content-Security-Policy)电子安全警告(不安全的内容安全策略)

此警告通知我们我们尚未设置内容安全策略(CSP)。CSP允许我们指定允许我们的应用程序从哪个域加载资源,从而大大降低了跨站点脚本(XSS)攻击的风险。同样,在本地开发期间这不是问题,但在生产中很重要。我们将在本章稍后部分使用CSP

解决了我们的错误后,我们就可以设置应用程序的配置文件了。

配置

在本地进行开发时,我们希望能够运行Web应用程序的本地版本,但是在将应用程序捆绑以供其他人使用时,我们希望它引用公共可用的URL。我们可以设置一个简单的配置文件来处理此问题。

在我们的 ./ src目录,我们将添加一个 config.js文件,我们可以在其中存储特定于应用程序的属性。我已包含一个配置模板。你可用于从终端轻松复制它:

cp src/config.example.js src/config.js

现在我们可以填写应用程序的属性:

const config = {
LOCAL_WEB_URL: 'http://localhost:1234/',
PRODUCTION_WEB_URL: 'https://YOUR_DEPLOYED_WEB_APP_URL',
PRODUCTION_API_URL: 'https://YOUR_DEPLOYED_API_URL'
};
module.exports = config;​

为什么不使用.env?

在以前的环境中,我们使用.env文件来管理特定于环境的设置。在这种情况下,由于Electron应用程序捆绑其依赖项的方式,我们使用了JavaScript配置文件。

现在在Electron应用程序的主要过程中,我们可以使用配置文件来指定我们要在开发和生产中加载的URL。在src/index.js,首先导入config.js文件:

const config = require('./config');

现在,我们可以更新loadURL功能以为每种环境加载不同的URL

// load the URL
if (is.development) {
window.loadURL(config.LOCAL_WEB_URL);
} else {
window.loadURL(config.PRODUCTION_WEB_URL);
}

通过使用配置文件,我们可以轻松地为Electron提供特定于环境的设置。

内容安全政策

如本章前面所述,CSP允许我们限制应用程序是否有权从中加载资源的域名。这有助于限制潜在的XSS和数据注入攻击。在Electron中,我们可以指定CSP设置来帮助提高应用程序的安全性。要了解有关电子和Web应用程序的CSP的更多信息,我建议你有关该主题的MDN文章。

Electron提供了用于CSP的内置API,但是electronic-util库提供了更简单,更简洁的语法。在我们的src/index.js的顶部,更新electronic-util导入语句以包含setContentSecurityPolicy

const { is, setContentSecurityPolicy } = require('electron-util');

现在,我们可以为应用程序的生产版本设置CSP

// set the CSP in production mode
if (!is.development) {
setContentSecurityPolicy(`
default-src 'none';
script-src 'self';
img-src 'self' https://www.gravatar.com;
style-src 'self' 'unsafe-inline';
font-src 'self';
connect-src 'self' ${config.PRODUCTION_API_URL};
base-uri 'none';
form-action 'none';
frame-ancestors 'none';
`);
}

通过编写CSP,我们可以使用CSP评估程序工具检查错误。如果我们有意通过其他URL访问资源,则可以将其添加到CSP规则集中。

我们最终的src/index.js文件的内容如下:

const { app, BrowserWindow } = require('electron');
const { is, setContentSecurityPolicy } = require('electron-util');
const config = require('./config');
// to avoid garbage collection, declare the window as a variable
let window;
// specify the details of the browser window
function createWindow() {
window = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false
}
});
// load the URL
if (is.development) {
window.loadURL(config.LOCAL_WEB_URL);
} else {
window.loadURL(config.PRODUCTION_WEB_URL);
}
// if in development mode, open the browser dev tools
if (is.development) {
window.webContents.openDevTools();
}
// set the CSP in production mode
if (!is.development) {
setContentSecurityPolicy(` default-src 'none';
script-src 'self';
img-src 'self' https://www.gravatar.com;
style-src 'self' 'unsafe-inline';
font-src 'self';
connect-src 'self' ${config.PRODUCTION_API_URL};
base-uri 'none';
form-action 'none';
frame-ancestors 'none'; `);
}
// when the window is closed, dereference the window object
window.on('closed', () => {
window = null;
});
}
// when electron is ready, create the application window
app.on('ready', createWindow);
// quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS only quit when a user explicitly quits the application
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// on macOS, re-create the window when the icon is clicked in the dock
if (window === null) {
createWindow();
}
});

这样,我们就可以在Electron Shell中运行Web应用程序(如图19-3所示)。

翻译 | 《JavaScript Everywhere》第19章 将现有的Web应用程序与Electron集成_第2张图片

19-3。我们在Electron应用程序shell中运行的Web应用程序

结论

在本章中,我们将现有的Web应用程序集成到Electron桌面应用程序中,这使我们能够快速将桌面应用程序推向市场。值得注意的是,这种方法需要权衡取舍,因为它提供了特定于桌面的优势,并且需要Internet连接才能访问应用程序的全部功能。对于希望将台式机应用程序推向市场的我们来说,这些缺点可能值得。在下一章中,我们将研究如何构建和分发Electron应用程序。

如果有理解不到位的地方,欢迎大家纠错。如果觉得还可以,麻烦您点赞收藏或者分享一下,希望可以帮到更多人。

你可能感兴趣的:(前端)