首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于Webpacker中的环境变量动态加载文件(Rails 6)

基于Webpacker中的环境变量动态加载文件(Rails 6)
EN

Stack Overflow用户
提问于 2020-07-22 14:31:46
回答 1查看 1K关注 0票数 0

我第一次在堆叠溢出的时候,请仁慈一点;)我会尽力的!

上下文:

我正在与webpacker一起开发Rails 6应用程序。这是一个由多家公司共享的程序,为了应用“一个代码,多个设置”模式,我们决定将所有与公司相关的配置文件移到不同的文件夹中,并将公司名称作为变量放在我们的.env文件中。我们需要更改一些配置变量以及一些地理数据(这样我们的客户就可以创建到某个地址的新传递)。基本上这就是看起来的样子:

代码语言:javascript
复制
Project folder 
| config 
  | companies
    | a_first_company
      | rails_config.rb
      | geofencing.js
    | a_second_company
      | rails_config.rb
      | geofencing.js
    | ....

在.env文件中:

代码语言:javascript
复制
COMPANY=a_first_company

在rails配置(application.rb)中,我们使用了一个简单的:

代码语言:javascript
复制
require_relative "companies/#{ENV['COMPANY']}/rails_config"

但是现在,JS部分来了!我遇到麻烦了。

问题:

我希望在现有脚本中动态地包含一个JSON对象。一个示例geofencing.js如下所示:

代码语言:javascript
复制
module.exports = {
  "countries": ["be"],
  "polygon": [
    50.8917729, 4.3004608,
    ...
    50.9162381, 4.3450928,
    50.8917729, 4.3004608
  ]
}

我试图将它作为一个geofencing变量导入到我现有的地址自动完成脚本中:

/app/javascript/plugins/places.js

代码语言:javascript
复制
// I know it doesn't work that way, but basically that what I would like to do:
const geofencing = require(`/config/companies/${process.env.COMPANY}/geofencing`);
...

const initPlaceAutocomplete = () => {
  
    ...

    var placesAutocomplete = places(
            {
                // And use the variable here...
                insidePolygon: [geofencing.polygon],
                type: 'address',
                // And there...
                countries: geofencing.countries,
                templates: {
                    value: (suggestion) => {
                        return suggestion.name;
                    }
                },
                container: addressInput
            }
        );

     ...
}

export { initPlaceAutocomplete };

此文件是使用<%= javascript_pack_tag 'delivery_new' %>导入视图中的。

/app/javascript/packs/delivery_new.js

代码语言:javascript
复制
import { initPlaceAutocomplete } from '../plugins/places';
initPlaceAutocomplete();

...

这个解决方案(我还没有找到):

我尝试过几种方法,比如导入webpack配置(/config/webpack/environment.js)中的文件,就像在ProvidePlugin文档中一样。

代码语言:javascript
复制
const {environment} = require('@rails/webpacker')
const path = require('path');
const webpack = require('webpack')

environment.plugins.prepend('Provide',
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        Popper: ['popper.js', 'default'],
        geofencing: path.resolve(path.join(__dirname, '..', '..', 'config', 'companies', process.env['COMPANY'], 'geofencing'))
    })
)

module.exports = environment

..。但没起作用。

我还尝试过在几个地方导入“地理位置”,在console中总是有相同的结果:Uncaught ReferenceError: geofencing is not defined

不过,我注意到,我可以访问process.env脚本中的places.js变量:当我在Chrome中重新加载页面时,在文件中编写console.log(process.env['COMPANY']);会提示我开发控制台中的公司名称。

除此之外,我不得不说我迷路了。我基本上是Webpack‘魔术’的新手;)

如果你需要更多关于我的设置的信息,请告诉我。

提前感谢您的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-23 11:21:53

您应该能够要求在require()表达式中使用与示例类似的内插模块。尝试使用相对路径,例如(假设父目录是兄弟):

代码语言:javascript
复制
require(`../config/${process.env.COMPANY}/geofencing`)

上面的表达式将只向包中添加公司地理参数化模块。

如果您希望这是动态的,webpack可以在运行时解析内插,前提是将请求路径限定为目录;您已经在这里使用"../config/“进行此操作。因此,webpack将把所有公司的地理信息模块都包括在这个包中。至于使用,我可能会将require语句移到函数中:

代码语言:javascript
复制
function initPlaceAutocomplete(company) {
  const geofencing = require(`../config/${company}/geofencing`)
  // ...
}

// usage
import { initPlaceAutocomplete } from "../plugins/places"
initPlaceAutocomplete(process.env.COMPANY)

此时,这可能是动态进口的一个很好的用例,也就是说,webpack支持TC39关于在运行时动态加载模块的建议

您可以使用require("../config...")函数语法代替import()函数语法。与require()不同,import()函数语法异步解析。

现在webpack将捆绑所有公司的地理应用模块,但作为单独的“块”,以保持您的初始脚本的大小。webpack将在运行时插入代码来异步解析这些“块”。为了支持这一点,import()表达式返回一个承诺,因此,我在这里使用异步/等待语法。

代码语言:javascript
复制
async function initPlaceAutocomplete(company) {
  const geofencing = await import(`../companies/${company}/config`)
  
  // ...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63036679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档