如何从 Next.js 中的公共文件夹中访问环境变量?

huangapple go评论66阅读模式
英文:

How can I access environment variables from a file sitting inside the public folder in Next.js?

问题

我正在集成 Firebase 云消息传递,并且需要在 public 文件夹内放置 firebase-messaging-sw.js 文件作为服务工作器。
文件需要包含我的 Firebase 配置,当然我想在环境变量中隐藏这些详细信息。我已将对象定义如下:

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

但是当我允许通知并尝试注册服务工作器时,出现错误:caught ReferenceError: process is not defined
我已在 .env.local 文件中定义了这些变量,并且我在应用程序的其他地方成功使用了这些变量。

如何从 public 文件夹中的文件访问它们?

英文:

I'm integrating Firebase Cloud Messaging, and it is required to have firebase-messaging-sw.js file inside the public folder as a service worker.
The file needs to have my firebase config, which I of course want to hide the details of in environment veriables. I have the object defined as such:

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

But now when I give permissions for notifications and it tries to register the service worker, I got the error: caught ReferenceError: process is not defined.
I have the variables defined in a .env.local file, and I've been using these same variables in my app in other places successfully.

How can I access them from a file in the public folder?

答案1

得分: 3

nextjs 的公共文件夹中的文件不经过 webpack 构建过程,因此会出现 process is undefined 的问题。

要在 firebase-messaging-sw.js 文件中使用环境变量,请按照以下步骤进行操作。

首先,创建一个名为 .env.local 的文件,如果已经有了,请跳过此步骤。

使用 npm i dotenv 安装 dotenv 包,我们将使用它来加载环境变量。

在根目录中创建一个名为 swEnvBuild.js 的文件。
在刚刚创建的 swEnvBuild.js 文件中,我们将创建一个函数,该函数会加载 .env.local 文件,然后将文件内容写入到名为 swenv.js 的公共文件夹中的新文件中。

然后我们在 firebase-messaging-sw.js 文件中导入从 swEnvBuild.js 生成的名为 swenv.js 的文件。

最后,更新你的 package.json

英文:

Files in the public folder in nextjs don't go through the webpack build process hence why process is undefined.

To use environment variables in your firebase-messaging-sw.js file, check the steps below.

First, create a .env.local file, skip this step if you already have it.

Install the dotenv package with npm i dotenv, will we use it to load the environment variables.

Create a file called swEnvBuild.js in the root directory.
In swEnvBuild.js file you just created, we will create a function that loads the .env.local file and then writes the contents of the file into a new file in the public folder called swenv.js

//swEnvBuild.js        
require('dotenv').config({ path: '.env.local' }); // make sure you have '.env.local' file.    
const fs = require('fs');

fs.writeFileSync(
  './public/swenv.js',
  `
 const process = {
          env: {
            NEXT_PUBLIC_FIREBASE_API_KEY: '${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}',
            NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: '${process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN}',
            NEXT_PUBLIC_FIREBASE_PROJECT_ID: '${process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID}',
            NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: '${process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}',
            NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: '${process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}',
            NEXT_PUBLIC_FIREBASE_APP_ID: '${process.env.NEXT_PUBLIC_FIREBASE_APP_ID}',
            NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: '${process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID}'
  }
 }`
);

Then we import the file that will be generated from swEnvBuild.js called swenv.js in the firebase-messaging-sw.js file.

//firebase-messaging-sw.js    
importScripts('swenv.js'); // this file should have all the environment variables declared, allowing you to use process.env.ANY_KEY_YOU_DEFINED

// Initialize the Firebase app in the service worker by passing the generated config
const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};

Finally, update your package.json.

"scripts": {
        "dev": "node swEnvBuild.js && next dev ",
        "build": "next build && node swEnvBuild.js",
 },

After running npm run dev, your environment variables should be accessible in firebase-messaging-sw.js using process.env

答案2

得分: -1

你需要在环境变量前加上NEXT_PUBLIC_前缀,以便它们在公共目录的文件中起作用。

引用自文档

> 为了将变量暴露给浏览器,您必须在变量前加上NEXT_PUBLIC_。

您在公共文件中无法访问process.env,而是根据文档示例在构建时将其值传递给公共文件。

> 该值将被内联到发送到浏览器的JavaScript中,因为使用了NEXT_PUBLIC_前缀。此内联发生在构建时,因此项目构建时需要设置各种NEXT_PUBLIC_环境变量。

因此,您需要从公共文件中导入一个设置函数,该函数会在构建时设置环境变量的值,我假设您可以根据需要在公共文件中命名它们,您不使用process.env,因为环境变量当然对浏览器不可用。

所以,NEXT_PUBLIC_前缀的重要性就在于能够在Next React/TypeScript的客户端代码中访问进程env变量的,而不是在公共文件夹的JavaScript文件本身中(强调环境变量的,因为您无法访问实际的Web服务器进程,这就是为什么如文档中所述动态查找不起作用)。

> // 这不会被内联,因为它使用一个变量
> const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
> setupAnalyticsService(process.env[varName])
>
> // 这不会被内联,因为它使用一个变量
> const env = process.env
> setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)

英文:

You need to prefix your environment variable with NEXT_PUBLIC_ in order for them to work in a file in the public directory.

As quoted from documentation,

> In order to expose a variable to the browser you have to prefix the
> variable with NEXT_PUBLIC_

You don't access the process.env in your public file, rather you pass its value to the public file at build time as per the documentation example.

> The value will be inlined into JavaScript sent to the browser because
> of the NEXT_PUBLIC_ prefix. This inlining occurs at build time, so
> your various NEXT_PUBLIC_ envs need to be set when the project is
> built.

So, you import a setup function from your public folder file that sets the environment variables values at built time, on your public file code I assume you can name them whatever you like, you don't use process.env as the environment variables are of course not available for the browser.

So, then the significance of the prefix NEXT_PUBLIC_ is just to be able to access the process env variables values in the Next react/typescript client side code, not in the public folder JavaScript files themselves, (the stress on the values of environment variables because you can't access actual web server process, that's why dynamic lookups don't work as stated in the docs)

> // This will NOT be inlined, because it uses a variable
> const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
> setupAnalyticsService(process.env[varName])
>
> // This will NOT be inlined, because it uses a variable
> const env = process.env
> setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)

huangapple
  • 本文由 发表于 2023年4月20日 01:33:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76057342.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定