multiple environment variable in next.js - javascript

I am currently learning to use next.js in my project which is based on 'create-react-app'. I am getting trouble on setting environment variables as .env.development, .env.staging and .env.production.
I have tried two different way. First approach did not work at all and using second approach I can access the environment variables but it creates infinite loop. Here is the setup I tried
First Approach
.env.development
REACT_APP_API_ENDPOINT=http://localhost:8000
constants/urls.js
console.log("process env", process.env); // {}
export const API_ENDPOINT = process.env.REACT_APP_API_ENDPOINT;
next.config.js
module.exports = withCSS({
cssModules: true,
});
module.exports = withPlugins([[withImages]]);
package.json
"scripts": {
"dev": "NODE_PATH=. dotenv -e .env.development next",
"build": "NODE_PATH=. dotenv -e .env.production next build",
"build:staging": "dotenv -e .env.staging next build",
"start": "next start"
},
Second Approach
.env.development
REACT_APP_API_ENDPOINT=http://localhost:8000
constants/urls.js
console.log("process env", process.env); // {}
export const API_ENDPOINT = process.env.REACT_APP_API_ENDPOINT;
next.config.js
const nextRuntimeDotenv = require("next-runtime-dotenv");
const withConfig = nextRuntimeDotenv({});
const nextConfig = {
poweredByHeader: false,
serverRuntimeConfig: {
NODE_ENV: process.env.NODE_ENV,
},
publicRuntimeConfig: {
NODE_ENV: process.env.NODE_ENV,
API_ENDPOINT: process.env.REACT_APP_API_ENDPOINT || "http://localhost:3000",
},
};
// the reason behind using multiple module.exports is that when wrapping withCss inside
// withPlugins, the css did not work. It instead gives warning that css is disabled
module.exports = withCSS({
cssModules: true,
});
module.exports = withConfig(withPlugins([[withImages]], nextConfig));
This approach creates infinite loop.

Related

NestJS Application won't hot reload after using dotenv package

I try to configure hot reload on my Nestjs application using this article: https://docs.nestjs.com/recipes/hot-reload
I followed exactly the instructions in the first section ("With CLI") but it fails for me. But I do know the reason, just don't know how to resolve this issue. My hot reload script in package.json is exactly as the article says, except 1 change:
"start:dev": "dotenv -e ./envs/.env.development -e ../../prisma/.env.development nest build --watch",
This is my script. As you can see, I apply the process with some environment variables. When running in this way, application boots fine, but Hot Reload won't work. When booting only with "start:dev": "nest build --watch",
It runs with Hot Reload. (Note that I configure webpack in nest-cli.json file, this is why it missing in script statement).
Anyone could tell why applying my own envs makes this issue?
webpack.config.js file:
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
const configuration = (options, webpack) => ({
...options,
entry: ['webpack/hot/poll?100', options.entry],
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
new RunScriptWebpackPlugin({ name: options.output.filename, autoRestart: false }),
],
});
module.exports = configuration;
nest-cli.json file:
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "#nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"webpack": true,
"webpackConfigPath": "./webpack.config.js",
"deleteOutDir": true
}
}
main.ts file:
declare const module: any;
async function bootstrap() {
const prisma = new PrismaClient();
// * https://github.com/prisma/prisma/issues/5430#issuecomment-1098715558
await prisma.$runCommandRaw({
createIndexes: 'RefreshToken',
indexes: [
{
key: {
createdAt: 1,
},
name: 'Refresh Token Index',
expireAfterSeconds: JWT_REFRESH_TOKEN_DURATION_MINUTES * 60,
},
],
});
const app = await NestFactory.create(AppModule);
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => app.close());
}
const port = config.get('port', { infer: true });
await app.listen(port);
}
bootstrap();
Ny env file:
NODE_ENV="development"
PORT="3000"

CommonJS require won't work inside Jest test file

I am testing my backend with Jest, but I keep getting this error
\node_modules\generate-key\lib\generate.coffee:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){rn = (max) ->
^
SyntaxError: Unexpected token '>'
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
at Object.<anonymous> (node_modules/generate-key/index.js:2:18)
This is my jest config file:
module.exports = { clearMocks: true, coverageDirectory: 'coverage', testEnvironment: 'node',moduleFileExtensions: ['ts', 'js', 'json', 'node'] };
My test file:
/* eslint-disable no-undef */
const { getConvertedKind } = require('../common');
test('check', () => {
expect(3).toBe(3);
});
The imported function:
exports.getConvertedKind = kind => {
const kinds = {
cinemaPass: 'cinema',
hotelPass: 'hotel',
boardingPass: 'flight',
coupon: 'coupon',
eventTicket: 'event',
transit: 'transit',
storeCard: 'wallet',
offer: 'offer'
};
return kinds[String(kind)] || null;
};
package.json:
"scripts": {
"start": "nodemon server.js",
"start:prod": "NODE_ENV=production nodemon server.js",
"debug": "ndb server.js",
"test": "jest --config ./jest.config.js"
}
It seems like you're trying to load a .coffee file and by default jest doesn't transform node_modules.
You can check the transformIgnorePatterns option and try something like:
transformIgnorePatterns: ["node_modules/(?!generate-key)"],

Entities loading for a Nx.dev Monorepo with Nest.js and TypeOrm

What I have been trying to do is to generate and run migrations with typeorm in the nest.js app within Nx.dev Monorepo.
But cannot find a way to do so.
My mono-repo looks like this
mono-repo structure
My database configurations look like this
database configurations
And this is how I have initialized my connection in the app.module.ts file
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useClass: DatabaseConfig
}),
I just wanted to know the way to generate and up the migrations.
Thanks and regards
In order to run typeorm cli in my Nx monorepo, I have added following target in my project.json:
"typeorm": {
"executor": "nx:run-commands",
"outputs": [],
"options": {
"command": "TS_NODE_PROJECT=apps/web-api/tsconfig.app.json ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli --config ./apps/web-api/src/database/cli.ts",
"cwd": "."
}
},
where cli.ts returns DataSourceOptions in my command line configuration.
Inside I have following configuration for migrations options:
migrations: [path.join(__dirname, 'migrations', '*.[tj]s')],
cli: {
migrationsDir: path.join(__dirname, 'migrations')
},
I execute it with following package.json script:
"migration:generate:web-api": "nx typeorm --project=web-api -- migration:generate -n",
In order to run migrations, I have added webpack configuration:
const glob = require('glob');
module.exports = (config, context) => {
if (config.mode === 'production') {
config.optimization = {
minimize: false,
};
const sourcePaths = ['apps/web-api/src/database/migrations/**/*.[tj]s'];
const additionalEntries = sourcePaths
.flatMap((entryPath) => glob.sync(entryPath, { absolute: false }))
.reduce((previous, current) => {
const filename = current.split('src/')[1];
previous[filename] = current;
return previous;
}, {});
config.entry = {
...config.entry,
...additionalEntries,
};
}
return config;
};
and configured my build target to use it with:
"build": {
...
"options": {
...
"webpackConfig": "apps/web-api/webpack.config.js",
}
}

How to pass arguments to webpack.conf.js?

I'm following these instructions based on this project (the official Vue Webpack template).
This is what I did:
package.js:
"scripts": {
"dev": "node build/dev-server.js",
"dev-alt": "node build/dev-server.js && set arg=alt&&webpack"
},
webpack.base.config.js:
// npm run dev-alt in the terminal
console.log('ARGS:', process.env.arg)
However ARGS: outputs undefined.
What the correct way to do this?
With Webpack 5.x and above you can no longer pass custom arguments to Webpack like --myarg=val. But you can still pass the supported arguments like --mode=production.
So what's the solution for custom args? Instead we need to write it like this, using the new --env parameter.
"build-project": webpack --mode=production --env myarg=val --env otherarg=val
Note that the custom arguments no longer start with -- after we put --env ahead of them. You'll need to put --env ahead of each custom key/value pair you need to define.
You'll also need to modify your Webpack config to export a function, rather than an object.
See this example code, taken from the docs.
const path = require('path');
module.exports = (env) => {
// Use env.<YOUR VARIABLE> here:
console.log('NODE_ENV: ', env.NODE_ENV); // 'local'
console.log('Production: ', env.production); // true
return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
};
Pass webpack arguments with --key=value in package.json
"scripts": {
"build": "webpack --mode=production --browser=firefox",
}
Access argv in webpack.config.js like this
module.exports = (env, argv) => {
if (argv.mode == "development") {
}
if (argv.browser == "firefox") {
}
};
You can pass whatever arguments you want by:
node my-script.js --myArgs thisIsTheValue
In my-script.js you can retrieve arguments by:
function getArg(key, defaultVal) {
var index = process.argv.indexOf(key),
next = process.argv[index + 1];
defaultVal = defaultVal || null;
return (index < 0) ? defaultVal : (!next || next[0] === "-") ? true : next;
}
var theArgsIWant = getArg('--myArgs', 'this is the default if argument not found');
From the article you described:
"scripts": {
"webpack-quizMaker": "set arg=quizMaker&&webpack",
"webpack-quiz": "set arg=quiz&&webpack"
}
These scritps are doing 2 things:
They are setting an environment variable in a way that only works on Windows if you're not using PowerShell. It's recommend to use cross-env here.
They are running webpack after setting the envinronment variable.
Then, inside the webpack configuration, they are reading the environment variable:
if (process.env.arg == "quiz") {
// do your thing
}
if (process.env.arg == "quizMaker") {
// do your thing
};
I recommend that you install cross-env
npm install --save-dev cross-env
And replace the scripts with this:
"scripts": {
"webpack-quizMaker": "cross-env arg=\"quizMaker\" webpack",
"webpack-quiz": "set arg=\"quiz\" webpack"
}
No need for && anymore because cross-env will call the specified command (webpack) after setting the env variable.
You can try this:
const onlyJS = process.argv.some(argument => argument === 'your argument');

How to resolve "Cannot GET /" for webpack-dev-server in inline mode

When I use webpack-dev-server (version 1.14.0) in inline mode and visit http://127.0.0.1:8080, the result is Cannot GET /.
The config in the webpack.config.js is:
devServer: {
color: true,
historyApiFallback: false,
inline: true,
hot: true,
contentBase: assetsRoot
}
The npm scripts in the package.json are
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack -p",
"clean": "node npm-scripts/del-build.script.js"
}
use node server.js
the server.js code:
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('../webpack.config');
console.log(config);
// 就是这么“复杂”!
// 往webpack的入口配置中加入 webpack-dev-server/client?http://localhost:8080/ 即可
for (var i of Object.keys(config.entry)){
config.entry[i].unshift("webpack-dev-server/client?http://localhost:8080/");
}
console.log(config.entry);
var compiler = webpack(config);
var server = new WebpackDevServer(compiler, {
});
server.listen(8080);
I came across the same question today and when I tried to search solutions, I saw this question.
Firstly I got 'Cannot Get /' on the webpage as you do, then I found that I mistake the contentBase path with"path.join(__dirname,'/dist'), lead to the server cannot find the page.
Then I solve this problem. In my webpack.config.js ,the devServer set should be:
`devServer: {`
`contentBase: path.join(__dirname, "/client/dist"),`
`compress: true,`
`hot:true,`
`port: 8888,`
`inline:true`
`}`
Maybe you can try this and check your directory again.

Categories

Resources