VueJS place multiple .env in folder - vue.js

Hello I'm using VueJS 2 and I have multiple .env in my project.
My app have .env for each company to select the company configuration (skin color / files...)
Actually I have all my .env in the root folder:
.env.company1-dev
.env.company1-staging
.env.company1-prod
.env.company2-dev
.env.company2-staging
.env.company2-prod
.env.company3-dev
.env.company3-staging
.env.company3-prod
So when I'll get 20 companies it will be confused on my root folder so it is possible to create a folder where I can place all my .env ?
The idea :
/environments/company1/
.env.dev
.env.staging
.env.prod
/environments/company2/
.env.dev
.env.staging
.env.prod
/environments/company3/
.env.dev
.env.staging
.env.prod

On your vue.config.js file you can add:
const dotenv = require("dotenv");
const path = require("path");
let envfile = ".env";
if (process.env.NODE_ENV) {
envfile += "." + process.env.NODE_ENV;
}
const result = dotenv.config({
path: path.resolve(`environments/${process.env.VUE_APP_COMPANY}`, envfile)
});
// optional: check for errors
if (result.error) {
throw result.error;
}
the before run you can set VUE_APP_COMPANY to a company name and run your app,
Note: It's important to put this code on vue.config.js and not in main.js because dotenv will use fs to read files.
References
https://github.com/motdotla/dotenv#path
https://github.com/vuejs/vue-cli/issues/787
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables

The accepted answer we have also used in the past. But I found a better solution to handle different environments. Using the npm package dotenv-flow allows not only the use of different environments but has some more benefits like:
local overwriting of variables by using .env.local or .env.staging.local and so on
definition of defaults using .env.defaults
In combination we have set up our projects with this configuration:
.env
.env.defaults
.env.development
.env.production
.env.staging
.env.test
And the only thing you have to do in your vue.config.js, nuxt.config.js or other entry points is
require('dotenv-flow').config()
Reference: https://www.npmjs.com/package/dotenv-flow

The powershell solution
I was handling exactly the same problem. Accepted solution is kind of ok, but it did not solve all differences between companies. Also, if you are using npm, your scripts can look nasty. So if you have powershell, here is what I suggest - get rid of the .env files :)
You can keep your structure like you want in the question. Just convert the env files to ps1.
/build/company1/
build-dev.ps1
build-stage.ps1
build-prod.ps1
/build/company2/
build-dev.ps1
build-stage.ps1
build-prod.ps1
Inside each of those, you can fully customize all env variables, run build process and apply some advanced post-build logic (like careful auto-deploy, publishing, merging with api project, ..).
So for example company1\build-stage.ps1 can look like this:
# You can pass some arguments to the script
param (
[string]$appName = "company1"
)
# Set environment variables for vue pipeline
$env:VUE_APP_ENVIRONMENT = "company1-stage";
$env:NODE_ENV="development";
$env:VUE_APP_NAME=$appName;
$env:VUE_APP_API_BASE_URL="https://company1.stage.mycompany.com"
# Run the vue pipeline build
vue-cli-service build;
# Any additional logic e.g.
# Copy-Item -Path "./dist" -Destination "my-server/my-app" -Recurse¨
Last part is easy - just call it (manualy or from integration service like TeamCity). Or, you can put it inside package.json.
...
"scripts": {
"build-company1-stage": "#powershell -Command ./build/company1/build-stage.ps1 -appName Company-One",
}
...
The you can call whole build process just by calling
npm run build-company1-stage
Similary, you can create localhost, dev, prod, test and any other environment. Let the javascript handle the part of building the app itself. For other advanced work, use poweshell. I think that this solution gives you much more flexibility for configuration and build process.
P.S.
I know that this way I'm merging configuration and build process, but you can always extract the configuration outside the file if it gets bigger.

Related

Why is runtimeConfig doesn't see environment variables in Nuxt 3?

I do yarn build without the .env file
Add the .env file to the project
I do yarn start.
Print the useRuntimeConfig().public.baseURL to the console and get undefined.
Why is runtime not tracking my environment variables?
.env
NUXT_PUBLIC_BASE_URL=https://example.com/api/v1
nuxt.config.js
export default defineNuxtConfig({
runtimeConfig: {
public: {
baseUrl: ''
}
},
plugins/app.js
export default defineNuxtPlugin(() => {
console.log('baseURL', useRuntimeConfig().public.baseURL
})
From the documentation page:
However, after your server is built, you are responsible for setting environment variables when you run the server. Your .env file will not be read at this point. How you do this is different for every environment. On a Linux server, you could pass the environment variables as arguments using the terminal DATABASE_HOST=mydatabaseconnectionstring node .output/server/index.mjs. Or you could source your env file using source .env && node .output/server/index.mjs.
Note that for a purely static site, it is not possible to set runtime configuration config after your project is prerendered.
So, source .env && yarn start should do it.
You might check the version of nuxt.
If it's the bridge version, runtimeConfig cannot work.
Cause I use #nuxt/bridge, not work.
and then it worked on the 3.0.0-rc.3 version. I've tried.
baseUrl: process.env.NUXT_PUBLIC_BASE_URL
try it that way. what you do is setting it explicitly to a empty string.

vue as nx plugin and using environment variables (nx-plus/vue)

I've migrated vue app to nx, all is fine now except of one thing - previously, .env file was used in both dev and production environments, during development as well as build, vue-cli-service took care of that. Now I struggle with app build - it doesn't seem to read .env file, or I just do it wrong.
I've tried to add dotenv-webpack and add it in the configure-webpack.js but during build none of the variables was accessible. Here is the file example:
//.env
SOME_API_URL=$API_URL
// config.ts
export const CONFIG = {
api_url = process.env.SOME_API_URL
}
// during build process.env is undefined
build command looks like this:
export API_URL='http://vue-app.com'; nx build frontend --skip-nx-cache
You would need to switch to Vite but we’ve had good success using this plugin for our applications: https://github.com/chf007/vite-plugin-nx-dotenv

How to auto save compiled vue files when running npm run serve

With vue.js when setting up a project using vue CLI i can run
$ npm run serve
to compile the files and start a port at localhost:8080
My question is what can i do so that the generated that got rendered in the page be also saved to a directory in my development machine.
Just like auto-saving and modifying so that i can be able to use the file on another project which depends on the generated files all during development
Are you sure it's not already creating a bundle somewhere? In some kind of build or dist folder?
Inside the webpack config you can check what value is used for output.
I don't know if an easier solution exists. But what i would suggest is :
Set writeToDisk option true. This will make sure your bundle written in to disk. Link
Then add an after-emit hook to the webpack pipeline:
const exec = require('child_process').exec; // use exec to run shell command
module.exports = {
...
plugins: [
...
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('CopyOutputPlugin', (compilation) => {
exec('command to copy output folder to desired folder');
});
}
}
]
};
child_process documentation.

Webpack 4 : ERROR in Entry module not found: Error: Can't resolve './src'

I was trying to run webpack-4 first time
webpack ./src/js/app.js ./dist/app.bundle.js
it shows warning / error :
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
ERROR in multi ./src/js/app.js ./dist/app.bundle.js
Module not found: Error: Can't resolve './dist/app.bundle.js' in 'D:\wamp64\www\webpack-4'
# multi ./src/js/app.js ./dist/app.bundle.js
Then i tried to change the mode
webpack --mode development
it shows :
ERROR in Entry module not found: Error: Can't resolve './src'
Resolved
Spent a lot of time to find out the solution.
Solution: Add index.js file into src folder.
That's it!.. solved :)
During Research, I found some facts about webpack 4 :
webpack 4 doesn’t need a configuration file by default!
webpack 4 there is no need to define the entry point: it will take ./src/index.js as the default!
Met this problem when deploying on now.sh
Solution: Use Default Behavior
Move entry point to src/index.js.
This leverage webpack#4 default value for entry:
By default its value is ./src/index.js, but you can specify a
different (or multiple entry points) by configuring the entry property
in the webpack configuration.
Solution: Be Specific
As #Lokeh pointed out, if you don't want to change your JS file location you can always use path.resolve() in your webpack.config.js:
entry: path.resolve(__dirname, 'src') + '/path/to/your/file.js',
Adding a context explicitly in webpack.config.js fixed issue for me. Adapt the following piece of code in your project:
context: __dirname + '/src',
entry: './index.js',
webpack ./src/js/app.js --output ./dist/app.bundle.js --mode development
This worked for me. I had the same trouble, it is because of a new version of webpack
webpack version 4.46.0
Perhaps someone gets stuck during migration from webpack 4 to 5.
in case of multiple webpack config files and if anyone uses merge:
Say webpack.common.js relies on some variables passed from cli eg:
module.export = (env) => {
const {myCustomVar} = env;
return {
// some common webpack config that uses myCustomVar
}
}
When you require common config in say webpack.prod.js:
const { merge } = require('webpack-merge'); // <-- `merge` is now named import if you are using > v5
const common = require('./webpack.common.js');
const getProdConfig = () => {....}
module.exports = (env) => {
return merge(common(env), getProdConfig()); // <-- here, `call` common as its exported as a fn()
};
I had a similar error and was able to resolve it with the command webpack src/index.js -o dist/bundle.js the -o did the trick. The issue wasn't the location of index.js it was missing the operator for defining the output path location.
See https://webpack.js.org/api/cli/
Version of webpack was 4.44.1
Other solutions didn't work. I solved this by adding this to package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack" //this
},
Then npm run build and it works. At first i've tried with npx webpack. Would love to know why it works.
Just leaving this here, incase someone is not paying attention to the details like me, I had the same error, but because my webpack config file was named webpack.config instead on webpack.config.js, so my custom configurations were never picked and webpack was falling back to the defaults entry "src/index.js"
As of webpack ^4.29.6 you don't need any configuration file so instead of giving path in package.json we need to write simply "build": "webpack" and keep index.js as entry point in src folder. However if you want to change entry point you can do so in webpack config file
For Rails 6 application this steps worked for me:
1) bundle exec rails webpacker:install
system will reinstall webpacker but will rewrite few files:
modified: config/webpack/environment.js
modified: config/webpacker.yml
modified: package.json
modified: yarn.lock
2) Return configs to initial state:
git checkout config/webpack/environment.js
git checkout config/webpacker.yml
package.json and yarn.lock you can leave as they are
Spent a lot of time similarly to others to get around this annoying problem. Finally changed webpack.config.js as follows:-
output: {
path: path.resolve(__dirname, './src'), //src instead of dist
publicPath: '/src/', //src instead of dist
filename: 'main.js' //main.js instead of build.js
}
...as Edouard Lopez and Sabir Hussain mentioned that you don't need to mention an entry point, removed that also and the app compiled after a long frustration.
So my problem, which I would wager is a lot of people's problem is that I set the entry path based on my whole app root. So in my case, it was /client/main.ts. But because my webpack.config.js file was actually inside /client, I had to move into that folder to run webpack. Therefore my entry was now looking for /client/client/main.ts.
So if you get this error you need to really look at your entry path and make sure it is right based on where you are running webpack and where your webpack.config.js file is. Your entry path needs to be relative to where you are running webpack. Not relative to your app root.
I had this problem when changing between React/Rails gems. Running rails webpacker:install restored me to the Rails webpacker defaults, but also overwrote all of my config files. Upon closer inspection, the culprit turned out to be my webpack/development.js file, which in a previous gem version had gotten modified from this Rails webpacker default:
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()
Once I restored the file to those contents, this error went away. Specifically I had been missing the module.exports = environment.toWebpackConfig() line, which apparently is pretty important for those who want to avoid Rails webpacker thinking it needs a src/index.js file (it doesn't)

what is the most reasonable way apply webpack to a full-stack node app?

i've been studying up on webpack for a couple of weeks now, and i've seen many examples of front end setups, and probably just this one setup for a backend.
i'm trying to setup a react app with a node back-end (e.g. express, koa, hapi, etc) where i would need at least one transpilation step for the back-end (e.g. babel, coffeescript, etc), and i think it would be nice to use webpack there for consistency vs adding another build mechanism to the mix (e.g. gulp, grunt, etc).
it would also be great if i could make changes to the backend and have the server restart automatically (watch style).
i'm wondering if the best way to do that is to basically have two distinct project setups with their own package.json and webpack.config files. maybe nest the back-end one under a server folder in the top level project folder, and use one or more script directives in the top level package.json file to control the two.
i guess i might have to proxy one server to the other to avoid CORS issues as well.
looking for any guidance from those more webpack battle tested than i for a decent setup.
regards,
tony.
Easiest way is to split this into two tasks: a build step that outputs to a folder (e.g. 'server'), then watch the output folder for changes and restart server task.
1. Build task
This can be in the same webpack.config as client building code - you can export an array and webpack will watch all of them.
Example webpack.config.js (top half is for server)
module.exports = [
{
name: 'server code, output to ./server',
entry: './index.js',
output: {
filename: './server/index.js'
},
target: 'node'
},
{
name: 'client side, output to ./public',
entry: './app.js',
output: {
filename: './public/app.js'
}
}
];
2.Watch Step
For the watch step, nodemon monitor changes and restart. Otherwise you could add a watch task to your server.js manually using something like fs.watch or node-watch.