Why is my amplify environment variable appearing for just a moment then disappearing again [duplicate] - reactjs

So i'm using the Contentful API to get some content from my account and display it in my Next.Js app (i'm using next 9.4.4). Very basic here. Now to protect my credentials, i'd like to use environment variables (i've never used it before and i'm new to all of this so i'm a little bit losted).
I'm using the following to create the Contentful Client in my index.js file :
const client = require('contentful').createClient({
space: 'MYSPACEID',
accessToken: 'MYACCESSTOKEN',
});
MYSPACEID and MYACCESSTOKEN are hardcoded, so i'd like to put them in an .env file to protect it and don't make it public when deploying on Vercel.
I've created a .env file and filled it like this :
CONTENTFUL_SPACE_ID=MYSPACEID
CONTENTFUL_ACCESS_TOKEN=MYACCESSTOKEN
Of course, MYACCESSTOKEN and MYSPACEID contains the right keys.
Then in my index.js file, i do the following :
const client = require('contentful').createClient({
space: `${process.env.CONTENTFUL_SPACE_ID}`,
accessToken: `${process.env.CONTENTFUL_ACCESS_TOKEN}`,
});
But it doesn't work when i use yarn dev, i get the following console error :
{
sys: { type: 'Error', id: 'NotFound' },
message: 'The resource could not be found.',
requestId: 'c7340a45-a1ef-4171-93de-c606672b65c3'
}
Here is my Homepage and how i retrieve the content from Contentful and pass them as props to my components :
const client = require('contentful').createClient({
space: 'MYSPACEID',
accessToken: 'MYACCESSTOKEN',
});
function Home(props) {
return (
<div>
<Head>
<title>My Page</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main id="page-home">
<Modal />
<NavTwo />
<Hero item={props.myEntries[0]} />
<Footer />
</main>
</div>
);
}
Home.getInitialProps = async () => {
const myEntries = await client.getEntries({
content_type: 'mycontenttype',
});
return {
myEntries: myEntries.items
};
};
export default Home;
Where do you think my error comes from?
Researching about my issue, i've also tried to understand how api works in next.js as i've read it could be better to create api requests in pages/api/ but i don't understand how to get the content and then pass the response into my pages components like i did here..
Any help would be much appreciated!
EDIT :
So i've fixed this by adding my env variables to my next.config.js like so :
const withSass = require('#zeit/next-sass');
module.exports = withSass({
webpack(config, options) {
const rules = [
{
test: /\.scss$/,
use: [{ loader: 'sass-loader' }],
},
];
return {
...config,
module: { ...config.module, rules: [...config.module.rules, ...rules] },
};
},
env: {
CONTENTFUL_SPACE_ID: process.env.CONTENTFUL_SPACE_ID,
CONTENTFUL_ACCESS_TOKEN: process.env.CONTENTFUL_ACCESS_TOKEN,
},
});

if you are using latest version of nextJs ( above 9 )
then follow these steps :
Create a .env.local file in the root of the project.
Add the prefix NEXT_PUBLIC_ to all of your environment variables.
eg: NEXT_PUBLIC_SOMETHING=12345
use them in any JS file like with prefix process.env
eg: process.env.NEXT_PUBLIC_SOMETHING

You can't make this kind of request from the client-side without exposing your API credentials. You have to have a backend.
You can use Next.js /pages/api to make a request to Contentful and then pass it to your front-end.
Just create a .env file, add variables and reference it in your API route as following:
process.env.CONTENTFUL_SPACE_ID
Since Next.js 9.4 you don't need next.config.js for that.
By adding the variables to next.config.js you've exposed the secrets to client-side. Anyone can see these secrets.
New Environment Variables Support
Create a Next.js App with Contentful and Deploy It with Vercel
Blog example using Next.js and Contentful

I recomended to update at nextjs 9.4 and up, use this example:
.env.local
NEXT_PUBLIC_SECRET_KEY=i7z7GeS38r10orTRr1i
and in any part of your code you could use:
.js
const SECRET_KEY = process.env.NEXT_PUBLIC_SECRET_KEY
note that it must be the same name of the key "NEXT_PUBLIC_ SECRET_KEY" and not only "SECRET_KEY"
and when you run it make sure that in the log says
$ next dev
Loaded env from E:\awesome-project\client\.env.local
ready - started server on http://localhost:3000
...
To read more about environment variables see this link

Don't put sensitive things in next.config.js however in my case I have some env variables that aren't sensitive at all and I need them Server Side as well as Client side and then you can do:
// .env file:
VARIABLE_X=XYZ
// next.config.js
module.exports = {
env: {
VARIABLE_X: process.env.VARIABLE_X,
},
}

You have to make a simple change in next.config.js
const nextConfig = {
reactStrictMode: true,
env:{
MYACCESSTOKEN : process.env.MYACCESSTOKEN,
MYSPACEID: process.env.MYSPACEID,
}
}
module.exports = nextConfig
change it like this

Refer docs
You need to add a next.config.js file in your project. Define env variables in that file and those will be available inside your app.

npm i --save dotenv-webpack#2.0.0 // version 3.0.0 has a bug
create .env.development.local file in the root. and add your environment variables here:
AUTH0_COOKIE_SECRET=eirhg32urrroeroro9344u9832789327432894###
NODE_ENV=development
AUTH0_NAMESPACE=https:ilmrerino.auth0.com
create next.config.js in the root of your app.
const Dotenv = require("dotenv-webpack");
module.exports = {
webpack: (config) => {
config.resolve.alias["#"] = path.resolve(__dirname);
config.plugins.push(new Dotenv({ silent: true }));
return config;
},
};
However those env variables are gonna be accessed by the server. if you want to use any of the env variables you have to add one more configuration.
module.exports = {
webpack: (config) => {
config.resolve.alias["#"] = path.resolve(__dirname);
config.plugins.push(new Dotenv({ silent: true }));
return config;
},
env: {
AUTH0_NAMESPACE: process.env.AUTH0_NAMESPACE,
},
};

For me, the solution was simply restarting the local server :)
Gave me a headache and then fixed it on accident.
It did not occur to me that env variables are loaded when the server is starting.

Related

dotenv not working when deploy React code to S3

I have a .env file with one variable API_BASE_URL. And I use webpack, dotenv and webpack.DefinePlugin to build the react app. The code is working on my localhost and my local server by serve dist using http-server. When I deploy my to S3 using AWS codepipeline, even though I set API_BASE_URL on AWS codebuild part, but the deployed app on S3 cannot load the variable. Anyone knows where is wrong?
webpack:
const dotenv = require("dotenv")
module.exports = () => {
const env = {} || dotenv.config().parsed
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`${next}`] = JSON.stringify(env[next])
return prev
}, {})
...
plugins: [
new webpack.DefinePlugin(envKeys),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
]
...
.env(it's on the root directory)
API_BASE_URL = xxxxxx
App file
const App = () => {
console.log("API_BASE_URL", API_BASE_URL)
return (
...
set enviroment variable on aws
cannot find the varible on S3
If you are using cra, you need to add REACT_APP_ prefix before your env variable name.
https://create-react-app.dev/docs/adding-custom-environment-variables/
But in any case to access the environment variable you have to call it from process.env -> process.env.YOUR_VARIABLE_NAME
https://nodejs.org/dist/latest-v8.x/docs/api/process.html#process_process_env

next/image configuration in Next.js config file

I’m implementing the Next.js Image component in my Headless project. The CMS that I’m using is WordPress. And since the image is coming from an external website, I need to specify the domain on next.config.js, as the documentation specifies:
https://nextjs.org/docs/basic-features/image-optimization
const nextConfig = {
image: {
domains: ['https://example.com'],
},
}
But in my next.config.js file I’ve already have this configuration:
const withStyles = require('#webdeb/next-styles');
module.exports = withStyles({
sass: true,
modules: true,
});
So my struggle is to combine this two on the config file.
Just for some context, without the image configuration, I have this error:
Error: Invalid src prop on next/image, hostname is not configured under images in your next.config.js
I've tried putting it together like the code bellow with the use of next-compose-plugins, but the error keeps showing:
const withStyles = require('#webdeb/next-styles');
const withPlugins = require('next-compose-plugins');
const nextConfig = {
image: {
domains: ['https://example.com'],
},
}
module.exports = withPlugins([
[withStyles({
sass: true,
modules: true,
})]
], nextConfig);
Without the nextConfig at the end of the module.exports, the code works without a problem.
A detail on the URL that I need to pass is that it's a subdomain and an homolog environment, but it doesn't need credentials to be accessed. I don't think it's the issue, tho.
Since I'm new with the Next.js, I just can't figure out how this configuration needs to work.
Your config object should be passed to the last plugin call. So in your case it would look like the following:
const withStyles = require('#webdeb/next-styles');
module.exports = withStyles({
sass: true,
modules: true,
images: {
domains: ['https://example.com'],
}
});
Also note that the correct entry for the next/image configuration is images and not image. Which is why it's probably not working when you tried with next-compose-plugins, as everything else seems to be correct in that code snippet.
For anyone whose above methods doesn't work, please remove the https:// or http:// in next.config.js;
module.exports = {
reactStrictMode: true,
images: {
domains: ['https://your-domain.com'], //make it 'your-domain.com'
},
};

Got an error Invalid src prop ('here is a link') on `next/image`, hostname "localhost" is not configured under images in your `next.config.js`

I am using the Image component from Next.js (it's a new feature of Next.js). I've tried to give the source URL:
{`${API}/user/photo/${blog.postedBy.username}`}
But it shows me this error. I also make changes in my next.config.js as
module.exports = {
images: {
domains: ['localhost'],
},
}
but nothing works for me. Please help if you know anything about this.
const src = `${API}/user/photo/${blog.postedBy.username}`;
<Image loader={() => src} src={src} width={500} height={500}/>
Here, loader is a function that generates the URLs for your image. It appends a root domain to your provided src, and generates multiple URLs to request the image at different sizes. These multiple URLs are used in the automatic srcset generation, so that visitors to your site will be served an image that is the right size for their viewport.
Edit next.config.js :
module.exports = {
reactStrictMode: true,
images: {
domains: ['example.com'],
},
}
Yes, I finally got the answer. Make loader function to load it from the destination of the image.
const myLoader=({src})=>{
return `${API}/user/photo/${blog.postedBy.username}`;
}
Use this loader function the loader attribute of an Image tag.
<Image loader={myLoader} src={`${API}/user/photo/${blog.postedBy.username}`} width={500}
height={500}/>
This works for me perfectly
I had the same issue, You need to restart your dev server, you need to do that each time you make changes on your next.config.js file.
The API string should include the port. e.g. localhost:3001
There are a whole bunch of out-of-date answers here that suggest setting the domains key in next.config.js. As of Next 12.3.0 this is no longer correct; see: https://nextjs.org/docs/messages/next-image-unconfigured-host
Instead, one should use a remotePatterns property, which is a little more complicated than the old domains:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/account123/**',
},
],
},
}
Inside next.config.js file.
Add Image src domain name:
const nextConfig = {
reactStrictMode: true,
images : {
domains : ['sangw.in', 'localhost', 'picsum.photos'] // <== Domain name
}
}
module.exports = nextConfig
Adding 'localhost' in the domains array will fix the issue,
Unfortunately nextJS didn't refresh the server automatically after configuration file(next.config.js) change.
You have to restart the server manually to reflect the changes.
You can also try by set reactStrictMode value reactStrictMode: true,
here is the full export object
module.exports = {
reactStrictMode: true,
images: {
domains: [
"localhost",
process.env.WORDPRESS_API_URL.match(/(http(?:s)?:\/\/)(.*)/)[2], // Valid WP Image domain.
"2.gravatar.com",
"0.gravatar.com",
"secure.gravatar.com",
],
},
};
First of all add and restart the dev server.
domains: ['localhost']
And be sure to return the image link with http(s) protocole
image link with localhost:port/... is wrong , return as http://localhost/... ( or with https )
I've faced the same issue, and my domains were correct. Deleting .next and node_modules folders, and running yarn/npm install fixed the issue.
For me, in next.config.js,
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
domains: [ "abc.def.org", ]
},
}
module.exports = nextConfig
and then in my Image tag
<Image
unoptimized // for image caching, else error
src={profile.picture}
alt={profile.picture || "IMG"}
width={60}
height={60}
/>

React/Next.js recommended way to set constants such as backend API URLs

I am looking through next.js documentation and trying to understand what the suggested approach is for setting URLs that change in different environments. Mostly, I want to ensure that I'm pointing backend URLs correctly in development versus production.
I suppose you can create a constants configuration file, but is there a supported, best practice for this?
Open next.config.js and add publicRuntimeConfig config with your constants:
module.exports = {
publicRuntimeConfig: {
// Will be available on both server and client
yourKey: 'your-value'
},
}
you can call it from another .js file like this
import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig()
console.log(publicRuntimeConfig.yourKey)
or even call it from view like this
${publicRuntimeConfig.yourKey}
You can configure your next app using next-runtime-dotenv, it allows you to specify serverOnly / clientOnly values using next's runtime config.
Then in some component
import getConfig from 'next/config'
const {
publicRuntimeConfig: {MY_API_URL}, // Available both client and server side
serverRuntimeConfig: {GITHUB_TOKEN} // Only available server side
} = getConfig()
function HomePage() {
// Will display the variable on the server’s console
// Will display undefined into the browser’s console
console.log(GITHUB_TOKEN)
return (
<div>
My API URL is {MY_API_URL}
</div>
)
}
export default HomePage
If you don't need this separation, you can use dotenv lib to load your .env file, and configure Next's env property with it.
// next.config.js
require('dotenv').config()
module.exports = {
env: {
// Reference a variable that was defined in the .env file and make it available at Build Time
TEST_VAR: process.env.TEST_VAR,
},
}
Check this with-dotenv example.

How to use "webpack.DefinePlugin" with React Gatsby and React-Bodymoving?

I am pretty new to React but I want to set
BODYMOVIN_EXPRESSION_SUPPORT in Webpack's Define plugin with Gatsby v1.
I followed the links below but I don't get what exactly I suppose to do...
https://github.com/QubitProducts/react-bodymovin
https://www.gatsbyjs.org/docs/environment-variables/
I made the file named .env.development and put it to src folder. the content in this file is below.
plugins: ([
new webpack.DefinePlugin({
BODYMOVIN_EXPRESSION_SUPPORT: true
})
])
The folder structures is
root--
|
|- public //where the build goes
|
|- src -- //where I develop site
|-components
|-data
|-pages
|-style
|-.env.development
What I noticed is there is a line said
/*global BODYMOVIN_EXPRESSION_SUPPORT*/
in bodymovin library and I think I just need to change that. I could modify in library directly maybe but I don't think that a best way to get around this problem. Does someone know how to set this up right?
Thanks in advance!
EDIT 2019-09-02
To use environment variables from .env files I recommend using dotenv because it's so simple. Here's an example that creates an object of all the variables in the .env file and makes them accessible on the client side (i.e in React) through DefinePlugin.
// gatsby-node.js
var dotenv = require('dotenv');
const env = dotenv.config().parsed;
// Create an object of all the variables in .env file
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
exports.onCreateWebpackConfig = ({ stage, rules, loaders, plugins, actions }) => {
actions.setWebpackConfig({
plugins: [
// Add the environment variables to webpack.DefinePlugin with define().
plugins.define(envKeys)
]
});
};
Here's an example of how I get the application name and version from package.json and using it in my service worker, I'm using Gatsby V2 though. Having the version in the service worker makes caching easier to handle. As you wrote, DefinePlugin is the way to go but it's a bit different when we use it in Gatsby.
We need to import the package.json file and add our custom webpack configuration in gatsby-node.js, with plugins.define() we tell webpack to use DefinePlugin:
const packageJson = require('./package');
exports.onCreateWebpackConfig = ({
plugins,
actions,
}) => {
actions.setWebpackConfig({
plugins: [
plugins.define({
__NAME__: JSON.stringify(packageJson.name),
__VERSION__: JSON.stringify(packageJson.version),
}),
],
})
}
The two defined variables __NAME__ and __VERSION__ are now accessible in my service worker sw.js:
self.addEventListener('install', function (e) {
// eslint-disable-next-line
console.log(__NAME__, __VERSION__);
e.waitUntil(
caches.open(__NAME__ + __VERSION__).then(function(cache) {
return cache.addAll(filesToCache);
})
);
});
Gatsby Reference: https://www.gatsbyjs.org/docs/add-custom-webpack-config/

Resources