如何管理 Webpack/Electron 应用程序的配置?
我正在使用 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"]
path.join(remote.app.getAppPath(), 'data/tests/groups.json');
使用 FS ReadSync 调用会导致问题 Error: ENOENT, data/在/Users/myuser/myproject/node_modules/electron/dist/Electron. app/Contents/Resourc es/default_app.asar
中找不到 tests/groups.json.所以似乎整个数据文件夹都没有被 webpacker 拾取.
Webpack 配置正在使用 json-loader
并且我没有找到任何文档提到有关包含特定文件或 json 的任何特殊内容.或者我是否必须在我的代码中以不同的方式引用 json 文件,因为它们可能打包在 main.js 下.
Electron/Webpack 管理 JSON 配置文件的最佳实践是什么?在 webpacking 项目时我做错了什么吗?
我的项目基于 https://github.com/SimulatedGREG/electron-vue使用 webpack/electron/vue
解决方案Webpack 的误解
首先要了解的一点是,webpack
不会捆绑通过 fs
或其他要求文件路径的模块所需的文件.这些类型的资产通常被标记为静态资产,因为它们没有以任何方式捆绑在一起.webpack
只会捆绑 require
d 或 import
ed (ES6) 的文件.此外,根据您的 webpack
配置,您的项目根目录可能并不总是与生产构建中的输出相匹配.
根据electron-vue文档的Project Structure/File Tree,你会发现只有webpack
包和static/
目录在生产版本中可用.electron-vue 还有一个方便的 __static
全局变量,可以在开发和生产环境中提供该 static/
文件夹的路径.您可以使用此变量,类似于使用 __dirname
和 path.join
来访问您的 JSON 文件或任何文件.
静态资产的解决方案
electron-vue 样板的当前版本似乎已经为您解决了这个问题,但我将描述如何使用 webpack
进行设置,因为它不仅可以应用于 JSON 文件,还可以应用于任何 webpack
+ electron
设置.以下解决方案假设您的 webpack
构建输出到一个单独的文件夹,在这种情况下我们将使用 dist/
,假设您的 webpack
配置是位于项目的根目录中,并假定在开发过程中将 process.env.NODE_ENV
设置为 development
.
static/
目录
在开发过程中,我们需要一个地方来存储我们的静态资产,所以让我们将它们放在一个名为 static/
的目录中.在这里,我们可以放置我们知道需要使用 fs
或其他需要文件完整路径的模块读取的文件,例如 JSON.
现在我们需要使 static/
资产目录在生产构建中可用.
但是 webpack
根本不处理这个文件夹,我们该怎么办?
让我们使用简单的copy-webpack-plugin
.在我们的 webpack
配置文件中,我们可以在构建 for production 时添加这个插件,并将其配置为将 static/
文件夹复制到我们的 dist/
文件夹.
新的 CopyWebpackPlugin([{来自:path.join(__dirname, '/static'),to: path.join(__dirname, '/dist/static'),忽略: ['.*']}])
<块引用>
好的,资产已投入生产,但如何在开发和生产中获取此文件夹的路径?
创建一个全局 __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(渲染器
进程)
<!-- 为生产环境中的静态文件设置`__static`路径--><脚本>if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\/g, '\\')</脚本><!-- 导入 webpack 包 -->
main.js(main
进程)
//为生产环境中的静态文件设置 `__static` 路径if (process.env.NODE_ENV !== 'development') {global.__static = require('path').join(__dirname, '/static').replace(/\/g, '\\')}//下面的其余应用程序代码
现在开始使用你的 __static
变量
假设我们有一个简单的 JSON 文件,需要用 fs
读取,这就是我们现在可以完成的事情......
static/someFile.json
{"foo":"bar"}
someScript.js
(renderer
或 main
进程)
从'fs'导入fs从路径"导入路径const someFile = fs.readFileSync(path.join(__static, '/someFile.json'), 'utf8')console.log(JSON.parse(someFile))//=>{ 富:酒吧 }
结论
webpack
用于将 require
d 或 import
ed 的资产捆绑到一个漂亮的捆绑包中.fs
或其他需要文件路径的模块引用的资源被视为静态资源,webpack
不直接处理这些.使用 copy-webpack-plugin
和 webpack.DefinePlugin
我们可以设置一个可靠的 __static
变量,该变量会生成我们的 static/
开发和生产中的资产目录.
最后,我个人还没有看到任何其他 webpack
+ electron
样板处理这种情况,因为这不是很常见的情况,但我认为我们可以所有人都同意在静态资产目录中拥有一个事实来源是缓解开发人员疲劳的绝妙方法.
I am using Webpack 2 and Electron to build nodejs application on Mac.
In my project in the root I have directory 'data' where I store configuration in a json like data/configurations/files.json (in practices there are different files with dynamic names)
After webpackaing though when I call: fs.readdirSync(remote.app.getAppPath());
to get files in the root I get only these packed: [ "default_app.js", "icon.png", "index.html", "main.js", "package.json", "renderer.js" ]
path.join(remote.app.getAppPath(), 'data/tests/groups.json');
called with FS ReadSync leads to an issue Error: ENOENT, data/tests/groups.json not found in /Users/myuser/myproject/node_modules/electron/dist/Electron.app/Contents/Resources/default_app.asar
. So it seems that the whole data folder is not picked up by webpacker.
Webpack config is using json-loader
and I did not find any documentation mentioning anything special about including specific files or jsons. Or do I have to reference json files in my code differently as they might be packed under main.js.
What is the best practice for Electron/Webpack for managing JSON config files? Am I doing something wrong when webpacking the project?
My project is based of https://github.com/SimulatedGREG/electron-vue using webpack/electron/vue
解决方案The Webpack Misconception
One thing to understand upfront is that webpack
does not bundle files required through fs
or other modules that ask for a path to a file. These type of assets are commonly labeled as Static Assets, as they are not bundled in any way. webpack
will only bundle files that are require
d or import
ed (ES6). Furthermore, depending on your webpack
configuration, your project root may not always match what is output within your production builds.
Based on the electron-vue documentation's Project Structure/File Tree, you will find that only webpack
bundles and the static/
directory are made available in production builds. electron-vue also has a handy __static
global variable that can provide a path to that static/
folder within both development and production. You can use this variable similar to how one would with __dirname
and path.join
to access your JSON files, or really any files.
A Solution to Static Assets
It seems the current version of the electron-vue boilerplate already has this solved for you, but I'm going to describe how this is setup with webpack
as it can apply to not only JSON files and how it can also apply for any webpack
+ electron
setup. The following solution assumes your webpack
build outputs to a separate folder, which we'll use dist/
in this case, assumes your webpack
configuration is located in your project's root directory, and assumes process.env.NODE_ENV
is set to development
during development.
The static/
directory
During development we need a place to store our static assets, so let's place them in a directory called static/
. Here we can put files, such as JSONs, that we know we will need to read with fs
or some other module that requires a full path to the file.
Now we need to make that static/
assets directory available in production builds.
But
webpack
isn't handling this folder at all, what can we do?
Let's use the simple copy-webpack-plugin
. Within our webpack
configuration file we can add this plugin when building for production and configure it to copy the static/
folder into our dist/
folder.
new CopyWebpackPlugin([
{
from: path.join(__dirname, '/static'),
to: path.join(__dirname, '/dist/static'),
ignore: ['.*']
}
])
Okay so the assets are in production, but how do I get a path to this folder in both development and production?
Creating a global __static
variable
What's the point of making this
__static
variable?
Using
__dirname
is not reliable inwebpack
+electron
setups. During development__dirname
could be in reference to a directory that exists in yoursrc/
files. In production, sincewebpack
bundles oursrc/
files into one script, that path you formed to get tostatic/
doesn't exist anymore. Furthermore, those files you put insidesrc/
that were notrequire
d orimport
ed never make it to your production build.When handling the project structure differences from development and production, trying to get a path to
static/
will be highly annoying during development having to always check yourprocess.env.NODE_ENV
.
So let's simplify this by creating one source of truth.
Using the webpack.DefinePlugin
we can set our __static
variable only in development to yield a path that points to <projectRoot>/static/
. Depending if you have multiple webpack
configurations, you can apply this for both a main
and renderer
process configuration.
new webpack.DefinePlugin({
'__static': `"${path.join(__dirname, '/static').replace(/\/g, '\\')}"`
})
In production, we need to set the __static
variable manually in our code. Here's what we can do...
index.html (renderer
process)
<!-- 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
process)
// 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
Now start using your __static
variable
Let's say we have a simple JSON file we need to read with fs
, here's what we can accomplish now...
static/someFile.json
{"foo":"bar"}
someScript.js
(renderer
or main
process)
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 }
Conclusion
webpack
was made to bundle assets together that are require
d or import
ed into one nice bundle. Assets referenced with fs
or other modules that need a file path are considered Static Assets, and webpack
does not directly handle these. Using copy-webpack-plugin
and webpack.DefinePlugin
we can setup a reliable __static
variable that yields a path to our static/
assets directory in both development and production.
To end, I personally haven't seen any other webpack
+ electron
boilerplates handle this situation as it isn't a very common situation, but I think we can all agree that having one source of truth to a static assets directory is a wonderful approach to alleviate developer fatigue.
相关文章