如何管理 Webpack/Electron 应用程序的配置?

Posted

技术标签:

【中文标题】如何管理 Webpack/Electron 应用程序的配置?【英文标题】:How to manage configuration for Webpack/Electron app? 【发布时间】:2017-11-04 09:32:02 【问题描述】:

我正在使用 Webpack 2 和 Electron 在 Mac 上构建 nodejs 应用程序。

在我的项目的根目录中,我有目录“数据”,我将配置存储在一个 json 中,如 data/configurations/files.json(实际上有不同的文件具有动态名称)

在 webpackaing 之后,当我调用:fs.readdirSync(remote.app.getAppPath()); 以获取根目录中的文件时,我只得到了这些打包:[ "default_app.js", "icon.png", "index.html", "main.js", "package.json", "renderer.js" ]

使用 FS ReadSync 调用path.join(remote.app.getAppPath(), 'data/tests/groups.json'); 会导致问题Error: ENOENT, data/tests/groups.json not found in /Users/myuser/myproject/node_modules/electron/dist/Electron.‌​app/Contents/Resourc‌​es/default_app.asar。所以似乎整个数据文件夹都没有被 webpacker 拾取。

Webpack 配置使用json-loader,我没有找到任何文档提到任何关于包含特定文件或 json 的特殊内容。或者我是否必须在我的代码中以不同的方式引用 json 文件,因为它们可能打包在 main.js 下。

Electron/Webpack 管理 JSON 配置文件的最佳实践是什么?在 webpacking 项目时我做错了什么吗?

我的项目基于 https://github.com/SimulatedGREG/electron-vue 使用 webpack/electron/vue

【问题讨论】:

这只是一个意见问题吗? 我不明白你的问题。 这里有需要解决的实际问题还是您只是想对如何编写配置提出意见? 您需要更清楚地了解您想要实现的目标、尝试过的内容以及面临的问题,以便我们更好地为您提供帮助。我认为您可能想要的是Webpack's require.context,您可以使用它来动态加载目录中的所有(json)文件。 我更新了具体的代码和错误信息。我正在尝试使用 fs.readFileSync 从数据文件夹中读取 json,但 webpacker 似乎不包含数据文件夹 【参考方案1】:

Webpack 的误解

首先要了解的一点是webpack 不会捆绑通过fs 或其他要求文件路径的模块所需的文件。这些类型的资产通常被标记为静态资产,因为它们没有以任何方式捆绑在一起。 webpack 只会捆绑 required 或 imported (ES6) 的文件。此外,根据您的 webpack 配置,您的项目根目录可能并不总是与生产构建中的输出相匹配。

根据 electron-vue 文档的项目结构/文件树,您会发现只有 webpack 包和 static/ 目录在生产版本中可用。 electron-vue 还有一个方便的__static 全局变量,可以在开发和生产中提供指向static/ 文件夹的路径。您可以使用此变量,类似于使用 __dirnamepath.join 访问您的 JSON 文件或任何文件的方式。

静态资产的解决方案

似乎electron-vue 样板的当前版本已经为您解决了这个问题,但我将描述如何使用webpack 进行设置,因为它不仅可以应用于 JSON 文件,而且还可以应用于申请任何webpack + electron 设置。以下解决方案假定您的 webpack 构建输出到一个单独的文件夹,在这种情况下我们将使用 dist/,假定您的 webpack 配置位于项目的根目录中,并假定 process.env.NODE_ENV 设置为 @ 987654342@ 开发期间。

static/ 目录

在开发过程中,我们需要一个地方来存储我们的静态资产,所以让我们将它们放在一个名为static/ 的目录中。在这里,我们可以放置文件,例如 JSON,我们知道我们需要使用 fs 或其他需要文件完整路径的模块来读取这些文件。

现在我们需要使 static/ assets 目录在生产版本中可用。

但是webpack 根本不处理这个文件夹,我们该怎么办?

让我们使用简单的copy-webpack-plugin。在我们的webpack 配置文件中,我们可以在构建用于生产 时添加此插件,并将其配置为将static/ 文件夹复制到我们的dist/ 文件夹中。

new CopyWebpackPlugin([
    
      from: path.join(__dirname, '/static'),
      to: path.join(__dirname, '/dist/static'),
      ignore: ['.*']
    
])

好的,资产已投入生产,但如何在开发和生产中获取此文件夹的路径?

创建一个全局 __static 变量

使这个__static 变量有什么意义?

    webpack + electron 设置中使用 __dirname 不可靠。在开发过程中__dirname可能引用存在于您的src/ 文件中的目录。在生产中,由于webpack 将我们的src/ 文件捆绑到一个脚本中,因此您形成的到达static/ 的路径不再存在。此外,您放在src/ 中的那些不是required 或imported 的文件永远不会进入您的生产版本。

    在处理与开发和生产的项目结构差异时,在开发过程中尝试获取static/ 的路径将非常烦人,必须始终检查您的process.env.NODE_ENV

让我们通过创建一个事实来源来简化这一点。

使用webpack.DefinePlugin,我们可以设置__static 变量仅在开发中,以生成指向<projectRoot>/static/ 的路径。根据您是否有多个 webpack 配置,您可以将其应用于 mainrenderer 进程配置。

new webpack.DefinePlugin(
    '__static': `"$path.join(__dirname, '/static').replace(/\\/g, '\\\\')"`
)

在生产中,我们需要在代码中手动设置__static 变量。这是我们可以做的...

index.htmlrenderer 进程)

<!-- Set `__static` path to static files in production -->
<script>
    if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
</script>
<!-- import webpack bundle -->

ma​​in.jsmain 进程)

// Set `__static` path to static files in production
if (process.env.NODE_ENV !== 'development') 
    global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')


// rest of application code below

现在开始使用你的 __static 变量

假设我们有一个简单的 JSON 文件,需要使用 fs 读取,这就是我们现在可以完成的事情......

static/someFile.json

"foo":"bar"

someScript.jsrenderermain进程)

import fs from 'fs'
import path from 'path'

const someFile = fs.readFileSync(path.join(__static, '/someFile.json'), 'utf8')

console.log(JSON.parse(someFile))
// =>  foo: bar 

结论

webpack 用于将 required 或 imported 的资产捆绑到一个漂亮的捆绑包中。使用fs 或其他需要文件路径的模块引用的资产被视为静态资产webpack 不直接处理这些。使用copy-webpack-pluginwebpack.DefinePlugin,我们可以设置一个可靠的__static 变量,该变量在开发和生产环境中生成static/ 资产目录的路径。

最后,我个人还没有看到任何其他 webpack + electron 样板处理这种情况,因为这不是很常见的情况,但我认为我们都同意拥有一个 来源事实 到静态资产目录是缓解开发人员疲劳的绝妙方法。

【讨论】:

【参考方案2】:

我认为混淆(如果有的话)可能来自这样一个事实,即 webpack 不仅“打包”、嵌入、事物、代码等......而且还使用其插件处理内容。

html 插件就是一个很好的例子,因为它只是在构建时生成一个 html 文件。

这与配置文件问题有何关系? 取决于您如何“要求”“配置”文件,您使用什么插件来处理该内容。

你可以嵌入它,或者只是将它作为文本加载,从文件系统或 http,或者...

如果是配置文件,我猜你希望它在运行时被解析, 否则,它只是花哨的硬编码值,也许您最好将其作为简单对象在源代码中输入。

在这种情况下,我认为 webpack 对运行时的需求几乎没有增加,因为没有什么可以预先打包以供以后使用,

所以我可能会改为或“要求”它,我会从文件系统中读取它,例如:

// read it parse it relative to appPath/cwd, 
const config = JSON.parse(
    fs.readfileSync( 
        path.join( app.getAppPath(), "config.json" ),
        "utf-8"
    ))
//note: look fs-extra, it does all that minus the app.path plus async

electron 会从文件系统中读取它,或者如果使用 Electron.require 会从 asar|fileSystem 中读取它(如果我没记错的话,按照这个顺序,我可能是错的),

【讨论】:

感谢您的帮助,我都检查了 fs-extra。使用 path.join(remote.app.getAppPath(), 'data/tests/groups.json' 会导致问题 Error: ENOENT, data/tests/groups.json not found in /Users/myuser/myproject/node_modules/electron /dist/Electron.app/Contents/Resources/default_app.asar. 所以看起来整个数据文件夹没有被 webpacker 拾取 不客气,检查路径: 'node_modules/electron/dist' ,即你当前的appPath,它会在built-and-packed 时以不同的方式解析,...也许在开发环境中,您想使用 'process.cwd' 或 '__dirname' 相对文件尝试读取 'config-file',但这取决于您和您的设置【参考方案3】:

Webpack 设计理念集中在非常简单但功能强大的概念上:

转换并捆绑您的应用实际使用的所有内容。

为了实现这一点,webpack 引入了一个强大的依赖图概念,它能够通过所谓的加载器管理几乎任何类型的依赖项(不仅仅是 *.js 模块)。

加载器的目的是以使声明import smth from 'your_dependency' 有意义的方式转换您的依赖关系。例如,json-loader 在加载 *.json 文件时调用 JSON.parse(...) 并返回配置对象。因此,为了利用 webpack 依赖解析系统来管理 JSON,从安装 json-loader 开始:

$ npm install --save-dev json-loader

然后按以下方式修改您的webpack.config.js

module.exports = 
  ...
  module: 
    rules: [
      test: /\.json$/, use: 'json-loader'
    ]
  
  ...
;

此时,webpack 应该能够通过它们的绝对路径解析您的 JSON 依赖项,因此以下应该可以工作(我在这里假设您有一个根上下文目录的子目录 config,包含文件 sample.json):

import sampleCfg from './config/sample.json';

但是导入物理路径并不会产生优雅、健壮和可维护的代码(例如考虑可测试性),因此将别名添加到您的 webpack.config.js 以抽象出您的物理 .config/ 被认为是一种好习惯导入语句中的文件夹

module.exports = 
  ...
  resolve: 
    alias: 
      cfg: './config'
    
  
  ...

然后你就可以像这样导入你的 JSON 配置了:

import sampleCfg from 'cfg/sample.json'

最后,如果你使用SimulatedGREG/electron-vue Electron 项目模板(正如你在帖子中提到的那样),那么你就有了三个 webpack 配置文件:

.electron-vue/webpack.web.config.js - 如果您将此模板仅用于普通 Web 开发(即不用于构建本机 Electron 项目),请使用此配置文件;

.electron-vue/webpack.main.config.js - 使用此文件配置 webpack 模块,该模块将在 Electron 的主进程中运行;

.electron-vue/webpack.renderer.config.js - 将此文件用于 Electron 的渲染器进程。

您可以在official Electron documentation 中找到有关主进程和渲染器进程的更多信息。

【讨论】:

以上是关于如何管理 Webpack/Electron 应用程序的配置?的主要内容,如果未能解决你的问题,请参考以下文章

在电子应用中使用 vue + webpack 引用静态资产

Vue项目打包成桌面程序exe除了使用electron-vue你还可以这样

如何使用 fs 与电子反应?

Maven分模块分工程管理

2021-06-10 aps高级排程如何管理产品开发

Python应用实战案例-Python协程管理精讲万字长文(建议收藏)