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

时间:2017-06-02 21:54:52

标签: javascript node.js webpack electron

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

在根目录中的项目中,我有目录'数据'我将配置存储在json中的数据/配置/ files.json(实际上有不同的动态名称文件)

在我打电话给webpacka之后:fs.readdirSync(remote.app.getAppPath());来获取根目录中的文件我只得到这些包装:[ "default_app.js", "icon.png", "index.html", "main.js", "package.json", "renderer.js" ]

使用FS ReadSync调用的{p> 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,我没有找到任何文档提及包含特定文件或jsons的任何特殊内容。或者我必须以不同方式引用代码中的json文件,因为它们可能包含在main.js下。

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

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

3 个答案:

答案 0 :(得分:14)

Webpack误解

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

根据电子视频文档的项目结构/文件树,您会发现只有webpack个包和static/目录可用于生产建设。 electron-vue还有一个方便的__static全局变量,可以在开发和生成中提供到static/文件夹的路径。您可以使用此变量,类似于__dirnamepath.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/文件夹中。

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

好的,资产正在生产中,但如何在开发和生产中获得此文件夹的路径?

创建全局__static变量

  

制作此__static变量的重点是什么?

  1. __dirname + webpack设置中使用electron并不可靠。在开发期间,__dirname 可以引用src/文件中存在的目录。在制作中,由于webpack将我们的src/文件捆绑到一个脚本中,因此您形成的static/形成的路径不再存在。此外,您放在src/内但未requireimport的文件永远不会进入您的生产版本。

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

    < / LI>

    因此,让我们通过创建一个事实来源来简化这一过程。

    使用webpack.DefinePlugin我们只能在开发中设置__static变量 ,以产生指向<projectRoot>/static/的路径。如果您有多个webpack配置,则可以将其应用于mainrenderer流程配置。

    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 renderermain流程)

    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用于将requireimport的资产捆绑在一起。使用fs或其他需要文件路径的模块引用的资产被视为静态资产,而webpack不会直接处理这些资产。使用copy-webpack-pluginwebpack.DefinePlugin,我们可以设置一个可靠的__static变量,在开发和生产过程中生成static/资产目录的路径。

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

答案 1 :(得分:2)

我认为混淆(如果有的话)可能来自这样一个事实,即webpack不仅包装&#34;包装,内容,代码等......而且还可以通过其插件处理内容。

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

这与配置文件问题有什么关系? 很好地取决于你是如何&#34;要求&#34; &#34; config&#34;文件,您用于处理该内容的插件。

您可以从文件系统或http中嵌入它,或者只是将其作为文本加载,否则......

对于配置文件,我想你希望它在运行时被解析,
否则它只是花哨的硬编码值,或许你可以更好地简单地在源代码中输入它作为简单的对象。

在这种情况下,我认为webpack对运行时需求几乎没有任何影响,因为在以后的使用中没有任何预先打包的内容,

所以我可能会改为或者&#34;要求&#34;它,我会从文件系统中读取它,例如:

// 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.require将从asar | fileSystem读取它(如果我没记错的话,按顺序,我可能是错的),

答案 2 :(得分:1)

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包含文件{{1 }}):

sample.json

但是导入物理路径不会产生优雅,强大和可维护的代码(例如,考虑可测试性),因此将{@ 1}}中的别名添加为摘要物理被认为是一种很好的做法{导入语句中的{1}}文件夹

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

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

webpack.config.js

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

  • module.exports = { ... resolve: { alias: { cfg: './config' } } ... } - 如果您仅将此模板用于普通Web开发(即不用于构建本机Electron项目),请使用此配置文件;

  • import sampleCfg from 'cfg/sample.json' - 使用此文件配置将在Electron主要流程中运行的webpack模块;

  • SimulatedGREG/electron-vue - 将此文件用于Electron的渲染器处理。

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