Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
React native 在babel构建阶段传递环境变量以导入不同的文件_React Native_Webpack_Babeljs - Fatal编程技术网

React native 在babel构建阶段传递环境变量以导入不同的文件

React native 在babel构建阶段传递环境变量以导入不同的文件,react-native,webpack,babeljs,React Native,Webpack,Babeljs,我正在为一个项目建立一个网站(react,带有webpack&babel)和移动应用程序(react native,带有expo)。因此,我为业务逻辑和redux/api库创建了一个公共库 网络和移动设备之间的一些代码会略有不同。在我的例子中,它是localStorage vs AsyncStorage,我使用它进行身份验证以及其他事情 我试图为构建阶段传递一个环境变量,以切换某些文件的导入,以便为每个构建加载正确的文件,这些构建只是路径链接(即没有我的库的预构建,我只是执行导入“../myli

我正在为一个项目建立一个网站(
react
,带有
webpack
&
babel
)和移动应用程序(
react native
,带有
expo
)。因此,我为业务逻辑和redux/api库创建了一个公共库

网络和移动设备之间的一些代码会略有不同。在我的例子中,它是localStorage vs AsyncStorage,我使用它进行身份验证以及其他事情

我试图为构建阶段传递一个环境变量,以切换某些文件的导入,以便为每个构建加载正确的文件,这些构建只是路径链接(即没有我的库的预构建,我只是执行
导入“../mylib”
)例如:

尝试1

@babel/preset env
说明它是移动的还是网络的,以便根据构建方式导入不同的库:

我的
.babelrc
有以下功能:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "platform": "mobile"
      }
    ]
  ]
}
然后在本地存储文件中执行以下操作:

export default () => {
    const platform = process.env.platform
    if (platform === 'mobile') {
        return import './storage-modules/storage-mobile'
    }
    return import './storage-modules/storage-web'
}
这不管用,这对我也不管用

尝试2次

我安装并创建了一个
.env
文件,其中包含:
PLATFORM=mobile
并在my
中设置插件。babelrc

{
  "presets": [
    "babel-preset-expo",
    "react-native-dotenv"
  ]
}
在我的示例文件中,我尝试了以下方法:

import { PLATFORM } from 'react-native-dotenv'
export default PLATFORM === 'mobile' ? import './storage-modules/storage-mobile' : import './storage-modules/storage-web'

但是现在我的构建不起作用了。知道我如何在react native app和webpack build(也使用babel)中为babel工作的构建过程中进行动态导入吗

首先,
@babel/preset-env
并不像你想象的那样。这不是为了指定您自己的变量,它是一个插件,可以为您想要支持的浏览器自动使用正确的目标和pollyfill

获取环境变量的最简单方法是使用webpack define插件(它是webpack的一部分,因此不需要安装任何额外的东西)

只需将其添加到您的网页配置中

plugins: [
    new webpack.DefinePlugin({
        'process.env': {
            platform: 'mobile',
        },
    }),
],
接下来,您不能在ifs中使用普通的
import
语句。
import
在任何代码运行之前都会得到解析,无论是在webpack构建的环境中,还是在脚本加载的支持环境中。 要在运行时导入某些内容,需要使用动态导入

下面是一个这样的例子

export default new Promise(async resolve => {
    resolve(
        process.env.platform === 'mobile'
            ? (await import('./mobile.js')).default
            : (await import('./desktop.js')).default
    );
});

您现在可以像平常一样从此文件导入,但请注意,默认导出是一种承诺

正如您问题的标题所说的“在babel构建阶段”,我假设您希望为桌面和移动设备构建不同的构建(而不是为两者构建一个构建,并在运行时动态加载所需的模块)。所以我会这样说:

import './storage-modules/storage-PLATFORM';
package.json中定义桌面和移动设备的运行脚本:

"scripts": {
  "devmobile": "cross-env NODE_ENV=development PLATFORM=mobile webpack --progress",
  "dev": "cross-env NODE_ENV=development webpack --progress",
}
。。。或者你可以为桌面版和移动版创建两个不同的
webpack.config.js
文件,但我认为上面的方法更简单

然后
npm运行devmobile
为移动设备构建,而
npm运行dev
为桌面构建

因为我在Windows上,所以我使用
cross-env
,但这是独立于操作系统的推荐方式

然后我会使用网页包的
NormalModuleReplacementPlugin

(基于)

在您的webpack.config.js中:

// defining the wanted platform for the build (comfing form the npm run script)
const targetPlatform = process.env.PLATFORM || 'desktop';

// then use the plugin like this
plugins: [
  new webpack.NormalModuleReplacementPlugin(/(.*)-PLATFORM(\.*)/, function(resource) {
    resource.request = resource.request.replace(/-PLATFORM/, `-${targetPlatform}`);
  }),
]
…如果您有以下两个文件:

./storage-modules/storage-mobile.js
./storage-modules/storage-desktop.js
在脚本中导入所需的一个,如下所示:

import './storage-modules/storage-PLATFORM';
这样,生成的生成将只包含用于生成过程的当前平台所需的文件

另一个可能的解决方案可能是,但我还没有测试它。也许值得一试,似乎很容易


如果您想要一个构建并动态导入所需的模块,您可以在
app.js
(或其他)中执行类似操作:

或:

巴贝尔必须做到这一点。
有关动态导入的网页包的更多信息。

您可以使用将平台传递给巴贝尔

"build-mobile": "PLATFORM=mobile ...",
"build-app": "PLATFORM=app ...",

下面的答案中有没有一个能帮助你实现这个目标?你打开了一个+50赏金,但没有接受任何答案,也没有在这段时间内对他们发表评论。甚至是一句“谢谢但没有帮助”…也没有给任何人赏金。非常好…我很忙。道歉。生活就是这样,谢谢!您对内置2文件的假设几乎是正确的。实际上,我只是将它们包含在我的项目中,所以没有预构建,只是直接链接到它们的路径。不幸的是,我无法在react native build中访问构建脚本。我只能在我的web版本上访问它。所以我希望有一个退路是可能的,即在web中,我定义“PLATFORM=web”,对于react版本,“如果没有定义,请选择mobile”样式。可能吗?
(async () => {
    const storageModule = await import(
        /* webpackChunkName: "[request]" */
        `./storage-modules/storage-${targetPlatform}`
    );
    // use the loaded module
})();
"build-mobile": "PLATFORM=mobile ...",
"build-app": "PLATFORM=app ...",