如何管理 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/Resources/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
只会捆绑 require
d 或 import
ed (ES6) 的文件。此外,根据您的 webpack
配置,您的项目根目录可能并不总是与生产构建中的输出相匹配。
根据 electron-vue 文档的项目结构/文件树,您会发现只有 webpack
包和 static/
目录在生产版本中可用。 electron-vue 还有一个方便的__static
全局变量,可以在开发和生产中提供指向static/
文件夹的路径。您可以使用此变量,类似于使用 __dirname
和 path.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/
中的那些不是require
d 或import
ed 的文件永远不会进入您的生产版本。
在处理与开发和生产的项目结构差异时,在开发过程中尝试获取static/
的路径将非常烦人,必须始终检查您的process.env.NODE_ENV
。
让我们通过创建一个事实来源来简化这一点。
使用webpack.DefinePlugin
,我们可以设置__static
变量仅在开发中,以生成指向<projectRoot>/static/
的路径。根据您是否有多个 webpack
配置,您可以将其应用于 main
和 renderer
进程配置。
new webpack.DefinePlugin(
'__static': `"$path.join(__dirname, '/static').replace(/\\/g, '\\\\')"`
)
在生产中,我们需要在代码中手动设置__static
变量。这是我们可以做的...
index.html(renderer
进程)
<!-- 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 -->
main.js(main
进程)
// 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.js
(renderer
或main
进程)
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
用于将 require
d 或 import
ed 的资产捆绑到一个漂亮的捆绑包中。使用fs
或其他需要文件路径的模块引用的资产被视为静态资产,webpack
不直接处理这些。使用copy-webpack-plugin
和webpack.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 应用程序的配置?的主要内容,如果未能解决你的问题,请参考以下文章