gpt4 book ai didi

webpack - Laravel Mix/Webpack环境相关变量的客户端代码

转载 作者:行者123 更新时间:2023-12-02 10:54:44 24 4
gpt4 key购买 nike

我正在寻找一种在开发机上使用Laravel Mix构建资产的方法,该方法随后将与生产中的参数匹配。

例如,我有一个用于我的API的基本URL,它是用于本地开发的http://foo.test/api/v1,而在我的生产服务器上是https://foo.com/api/v1

因此,在我的客户代码(例如http.js)中,我想执行以下操作:

Vue.axios.defaults.baseURL = API_BASE_URL;


现在,在运行 API_BASE_URL时应将 http://foo.test/api/v1替换为 npm run dev,或者在运行 https://foo.com/api/v1时应替换为 npm run prod

我已经尝试了以下无效的方法。

webpack.mix.js

mix.webpackConfig(webpack => {
return {
plugins: [
new webpack.DefinePlugin({
API_BASE_URL: JSON.stringify('https://foo.com/api/v1'),
})
]
}
});


然后在http.js中

Vue.axios.defaults.baseURL = API_BASE_URL;


编译为:

Object({"NODE_ENV":"production"}).API_BASE_URL;

我也尝试使用 process.env.API_BASE_URL这种方法。

最佳答案

有点晚了,我不知道它是否仍然适用,但是我们可能不是唯一寻求这一点的人。
我在此上花了很多时间,试图找出确切的问题。我将在这里分享我的故事,希望其他人可以避免浪费时间。

传递给您的客户端应用程序的基本上是process.env的内容。
Laravel Mix试图保护您,以免暴露整个.env(通过dotenv加载)
过滤变量并仅允许以MIX_开头的变量。
此行为来自MixDefinitionsPlugin

组装Webpack配置后,它将首先放置您的自定义插件,然后是mix插件。
这意味着MixDefinitionsPlugin将始终具有最后一个字。

如果可以解决该限制,那么一个简单的解决方案是:

在您的.env中添加以下内容:

MIX_API_URL=http://foo.test/api/v1


重新编译资产时,客户端上会出现一个 process.env.MIX_API_URL
就这么简单。

顺便说一句,由于这是使用 dotenv-expand加载的,因此您甚至可以使用其他变量(即,如果您的api已经设置了后端):

MIX_API_URL=${API_URL}


如果要针对生产变体执行此操作,则麻烦最少的是(临时)将您的 .env文件替换为生产文件。
只需创建一个shell脚本来构建您的生产变体:


用产品 .env替换开发 .env
运行 npm run production
恢复您的开发 .env


做完了有第二种解决方案,它很丑陋,但我更喜欢它,请继续阅读:)



还在?

我对此并不满意,因为我只想能够运行 npm run production并且它可以工作,所以我更进一步了。

由于在JavaScript转换时仅使用最后定义的 process.env,因此最接近该插件的插件将获胜。
如上所述,这是MixDefinitionsPlugin,您对此无能为力。

如果研究实现我们想要的其他几种方式

在MixDefinitionsPlugin之后添加您自己的?

(除了脚本替换.env之外,这是我能找到的唯一可行的解​​决方案)

在插件完成加载后,Mix会以插件为参数发出“ loading-plugins”事件。
这意味着您将获得一组准备就绪且非常漂亮的插件,这些插件将用于webpack。

最初,我尝试将插件插入数组的末尾,但是该插件仅在编译后执行,因此您一无所获。
另一种方法是弄清楚该插件位于何处并与其一起工作。
如果您可以在那里修改其内容,则理论上可以“即时”添加值,这些值也将最终出现在您的浏览器中。
这是我做的。

基本上可以归结为以下几点:

if (mix.inProduction()) {
Mix.listen('loading-plugins', plugins => {
const _ = require('lodash');
let define = _.find(plugins, plugin => {return plugin.constructor.name === 'DefinePlugin'});
define.definitions['process.env'].MIX_API_URL = 'http://foo.com/api/v1';
});
}


(请注意,我们正在这里查找DefinePlugin而不是MixDefinitionsPlugin,因为它已经完成了工作)

由于您可以在此处添加所需的内容而无需 MIX_前缀,因此,您可以在此处为这两个都设置API_URL:

Mix.listen('loading-plugins', plugins => {
const _ = require('lodash');
let define = _.find(plugins, plugin => {return plugin.constructor.name === 'DefinePlugin'});
define.definitions['process.env'].API_URL = mix.inProduction() ?
'http://foo.com/api/v1' : 'http://foo.test/api/v1';
});


您也可以在此处加载另一个.env文件(通过 dotenv.config()),然后将其合并到定义中,天空是极限。

.env的其他名称?

我在想其他事情。

MixDefinitionsPlugin构造函数允许这种可能性( function MixDefinitionsPlugin(envPath)),不幸的是,实际的实现不允许:

return new webpack.DefinePlugin(
new MixDefinitionsPlugin().getDefinitions(merge)
);


因此,没有这种运气,这是无法使用的。

不同的文件夹?

接下来是检查是否可以使用生产 .env文件创建其他文件夹。

Mix有一个 Paths对象,用于存储根。所以这里的想法是存储我的替代.env
在子目录中,更新根目录和presto。

Mix.paths.setRootPath(Mix.paths.root('./resources/assets/production'));


这适用于 .env,但它破坏了许多其他功能。根用作webpack的上下文,例如
purify-css插件的配置(vs和刀片文件的cs清理),最重要的是,它也破坏了URL加载器。
也不要去这里(除非您想拦截Webpack配置并在任何地方恢复根,这都不值得)

因此,这里结束了我生命中大约5个小时的故事。
我距离JavaScript专家不远,所以也许我犯了一些错误或遗漏了一些东西,但这是我的故事:)

关于webpack - Laravel Mix/Webpack环境相关变量的客户端代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48906425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com