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

den*_*xic 10 babel webpack react-native

我正在为一个项目构建一个web(reactwebpack&babel)和移动应用程序(react-nativewith expo).因此,我为业务逻辑和redux/api库创建了一个公共库.

有些代码在网络和移动设备之间会略有不同.在我的情况下,它是localStorage vs AsyncStorage,我用它来进行身份验证......

我正在尝试为构建阶段传递一个环境变量来切换某些文件的导入,以便为每个构建加载正确的文件,这些文件只是路径链接(即没有预构建我的库,我只是这样做import '../mylib')ex:

if(PLATFORM === 'mobile'){
   import StorageModule from './mobile-storage-module`
} else {
   import StorageModule from './mobile-storage-module`
}
export default StorageModule
Run Code Online (Sandbox Code Playgroud)

试试1

@babel/preset-env 要说它是移动还是网络,以便它根据构建导入不同的库,如下所示:

.babelrc有这个:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "platform": "mobile"
      }
    ]
  ]
}
Run Code Online (Sandbox Code Playgroud)

然后在本地存储文件中我这样做:

export default () => {
    const platform = process.env.platform
    if (platform === 'mobile') {
        return import './storage-modules/storage-mobile'
    }
    return import './storage-modules/storage-web'
}
Run Code Online (Sandbox Code Playgroud)

这没用,这对我也没用.

试试2

我安装了react-native-dotenv并用以下内容创建了一个.env文件: PLATFORM=mobile 并在我的设置中设置插件.babelrc:

{
  "presets": [
    "babel-preset-expo",
    "react-native-dotenv"
  ]
}
Run Code Online (Sandbox Code Playgroud)

在我的示例文件中,我试过这个:

import { PLATFORM } from 'react-native-dotenv'
export default PLATFORM === 'mobile' ? import './storage-modules/storage-mobile' : import './storage-modules/storage-web'
Run Code Online (Sandbox Code Playgroud)

但现在我的构建不起作用.任何想法我如何在构建过程中进行动态导入,适用于反应原生应用程序和webpack构建中的babel(也使用babel)?

luk*_*eke 2

首先,@babel/preset-env它没有做你认为它会做的事。这不是为了指定您自己的变量,它是一个插件,可以自动为您想要支持的浏览器使用正确的目标和 pollyfills。

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

只需将其添加到您的 webpack 配置中即可。

plugins: [
    new webpack.DefinePlugin({
        'process.env': {
            platform: 'mobile',
        },
    }),
],
Run Code Online (Sandbox Code Playgroud)

接下来,您不能import在 if 内使用普通语句。 import在任何代码运行之前得到解析,无论是在 webpack 构建时,还是在脚本加载的受支持环境中。要在运行时导入某些内容,您需要使用动态导入。

下面是一个示例,展示了它的样子。

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

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