I have 2 different file with environment variables: .env.development and .env.production.
I am trying to load the correct file through the ConfigModule like so:
app.module.ts
#Module({
imports: [
ConfigModule.forRoot({
envFilePath: `.env.${process.env.NODE_ENV}`,
isGlobal: true,
})
],
})
In package.json I specify the right NODE_ENV per startup script:
"start:dev": "NODE_ENV=development nest start --watch",
"start:prod": "NODE_ENV=production node dist/main",
My development file contains PORT=2994 and production contains PORT=2997.
In my main.ts file I am logging both the PORT and the .env. file path + NODE_ENV of the ConfigService, like so:
const port = configService.get<number>('PORT');
console.log('Running on port: ', port);
console.log(`.env.${configService.get('NODE_ENV')}`);
The NODE_ENV file path log is always correct (.env.development for development and .env.production for production). The port however, which is supposed to be retrieved from the correct file is logged 2994 on both development and production.
Only when I remove or empty the .env.development file, the production values are used. It seems as if the .env.development will always take precedence over the .env.production file.
What am I doing wrong here?
Related
I'm using Vite (vite#3.1.8)
to build Typescript artifacts for an SPA "site" using SolidJS (solid-js#1.6.0).
here's my vite.config.ts
import { defineConfig, resolveBaseUrl } from 'vite'
import solidPlugin from 'vite-plugin-solid'
export default defineConfig({
plugins: [solidPlugin()],
server: {
port: 3000,
},
build: {
target: 'esnext',
outDir: '../htdocs',
rollupOptions: {
input: {
index: "./index.html",
dev: "./dev.html",
test: "./test.ts",
},
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
}
},
},
});
Currently, it actually builds 2 html files (index.html and dev.html) and the artifacts needed to run those files. Its great. Couldn't be happier.
I would like to have the transpiler to also kick out test.js so that I can run it to do some sanity checking before deploying to production.
I'm hoping to do vite build, and then run node ../htdocs/assets/test.js (or something similar), and have it block the final deployment if any my sanity tests fail.
however, when I attempt to do this, I get an error when I run test.js, complaining about my use of import statements.
Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
setting my package type to module in package.json doesn't fix it. changing the test file to test.mjs doesnt fix it. I'm not really sure what to try next.
What I really wish it would do is do the whole "import" as part of transpiling, and make one self-contained test.js that just runs. It seems like that is what it does when it builds index.html and dev.html, why wont it do that for my ts file?
That should work. I just tried making a new repo with your vite.config.ts, one-line index.html, dev.html, and test.ts files, and vite, vite-plugin-solid, solid-js installed. In the end I got a ../htdocs/assets/test.js file.
You might also be interested in checking out Vitest which makes testing like this easier to do, and won't accidentally end up in your deployed htdocs.
The best solution I could find was to make a separate config file for building the tests.
import { defineConfig } from 'vite'
import solidPlugin from 'vite-plugin-solid'
export default defineConfig({
plugins: [solidPlugin()],
server: {
port: 3000,
},
build: {
target: 'esnext',
outDir: '../htdocs',
lib: {
entry: "./test-runner.ts",
name: "test-runner",
fileName: "test-runner"
},
rollupOptions: {
},
},
});
and then, update my package.json to make my test script compile and run the output from that alternative vite config.
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"test": "vite build --config vite.config-tests.ts && node ../htdocs/test-runner.umd.js"
},
I want to define environment variables in my package.json where I'm using Snowpack, but as far as I know Snowpack sets the NODE_ENV automatically based on dev vs build.
Is it possible to define variables for 3 modes instead of 2, I mean:
development
preproduction
production
These are my scripts in my package.json:
"scripts": {
"start": "snowpack dev",
"build": "snowpack build NODE_ENV=pre",
"build:production": "snowpack build NODE_ENV=pro"
}
However, import.meta.env.MODE returns production for the 2 types of build.
I couldn't make it work, maybe there is another way of doing this.
My use case was not exactly the same, but similar, and you should be able to generate as many different environments as you want with this technique.
I was able to do this by writing a custom snowpack plugin to use .env files with the dotenv npm package, and two separate snowpack.config.js files; one for dev and one for prod. Here's how...
Add dotenv to your project: npm i -D dotenv
Create this new file. This will be our custom snowpack plugin
// env-loader.js
const dotenv = require('dotenv');
module.exports = function plugin(snowpackConfig, { path }) {
dotenv.config({ path: path });
return { name: 'Custom plugin from StackOverflow' };
};
Create your .env files; .env.develop and .env.production
Create your snowpack.config files; snowpack-develop.config.js and snowpack-production.config.js
Add your custom plugin to both snowpack.config files. Be sure to give it the correct path to your custom plugin, and the correct path to your .env files.
// snowpack-develop.config.js
const path = require('path');
module.exports = {
plugins: [
['./path/to/env-loader', { path: path.resolve(process.cwd(), '.develop.env') }],
],
};
Finally, add your npm scripts. Point your dev scripts to the snowpack-develop file, and prod to the snowpack-production file.
"scripts": {
"develop": "snowpack dev --config ./snowpack-develop.config.js",
"build:dev": "snowpack build --config ./snowpack-develop.config.js",
"build:prod": "snowpack build --config ./snowpack-production.config.js"
},
In snowpack, environment variables must include the prefix SNOWPACK_PUBLIC_, and to use a variable in your code you would access it like this: import.meta.env.SNOWPACK_PUBLIC_MY_VARIABLE. It runs a find-and-replace at build time.
Snowpack Config Docs
Snowpack Plugin Docs
Snowpack Env Docs
in the file of app.module.ts, I used Environment variable
imports: [
ConfigModule.forRoot({ envFilePath: [`./src/config/${process.env.NODE_ENV}.env`], isGlobal: true },),
MongooseModule.forRoot(process.env.DATABASE_URL, {
useNewUrlParser: true,
user: `${process.env.DATABASE_USER}`,
pass: `${process.env.DATABASE_PASSWD}`,
}),
It was working when I test in local,But when I build it,The env is not work,So what can I do ,Thinks
my package.json script
"build": "NODE_ENV=prod nest build", // the env not work
"start:dev": "NODE_ENV=dev nest start --watch", // it works
build and therefor nest build does not run the code, it runs the compiler to transform the ts files into js files, so there's never any check or evaluation of what process.env.WHATEVER is, it's just a translation from ts syntax (with all the types) to js syntax that can be interpreted by node.
start:dev (mapped to nest start --watch) is what is actually running the code, using node as the JavaScript engine.
You probably are wanting something like
"start:dev:prod": "NODE_ENV=prod nest start --watch"
Or you can modify the start:prod command Nest provides in new projects to be NODE_ENV=prod node dist/main.js
I am building a simple NodeJs Lambda with webpack. There is a dependent node_module using different configuration file based on NODE_ENV
let config = require(`./${process.env.NODE_ENV ? process.env.NODE_ENV : 'dev'}_env.js`);
I am setting NODE_ENV in package.json
"serve": "set NODE_ENV=qa&webpack --mode development --watch",
"serve-windows": "$env:NODE_ENV=qa&webpack --mode development --watch"
and in webpack configuration
mode: process.env.NODE_ENV ? process.env.NODE_ENV : 'default',
No matter what I do, its always including dev_env.js ignoring the NODE_ENV I am setting. I spent all night trying to figure out this looking at different posts, is there anything I am doing incorrectly?
webpack --mode development sets NODE_ENV to development. See the documentation: https://webpack.js.org/configuration/mode/#usage
Another remark, default and qa&webpack are non-standard values for NODE_ENV. Usually, the expected value is either development, test, or production.
If you want to use this approach, you will have to use a different environment variable, for example:
let config = require(`./${process.env.APP_ENV ? process.env.APP_ENV : 'dev'}_env.js`);
"serve": "set APP_ENV=qa&webpack --mode development --watch",
I'm using VueCLI 2 and build as production. THe build.js is built and compiled into 200KB. When I re-run the server as development, it loaded 3MB. I'm sure the build.js inside dist folder is 200KB. I tried to open index.html but it doesn't work and redirect to root directory on website.
Package.json
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
Webpack
module.exports = { ...
module:{
...
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
jQuery: 'jquery'
})
],
devtool: '#eval-source-map'
},
...
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: true
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return module.context && module.context.indexOf('node_modules') !== -1;
}
})
])
}
HTML
<body>
<script src="/dist/vendor.js"></script>
<script src="/dist/main.js"></script>
</body>
Command
npm run build
npm run dev
npm run build creates a dist directory with a production build of your app.
In order to serve index.html in a browser you need an HTTP server.
For example serve:
npm install -g serve
serve -s dist
The default port is 5000, but can be adjusted using the -l or --listen flags:
serve -s build -l 4000
Docs:
https://create-react-app.dev/docs/deployment#static-server
https://github.com/zeit/serve
https://cli.vuejs.org/guide/deployment.html#previewing-locally
Production build can be run locally by utilizing Vue CLI's tooling simply by running:
vue-cli-service serve --mode production
For convenience, this can be added to package.json scripts:
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"production": "vue-cli-service serve --mode production"
}
Command:
$ npm run production
Very easy with express, and highly extensible/configurable.
Install
npm install -D express
Compose
server.js
// optional: allow environment to specify port
const port = process.env.PORT || 8080
// wire up the module
const express = require('express')
// create server instance
const app = express()
// bind the request to an absolute path or relative to the CWD
app.use(express.static('dist'))
// start the server
app.listen(port, () => console.log(`Listening on port ${port}`))
Execute
node server.js
The Vue CLI tooling (vue-cli-service serve --mode production) still seemed to be serving the development files for me, albeit with process.env.NODE_ENV === 'production'.
To serve the contents of dist, the following worked for me without having to install any extra packages:
npm run build
npx serve dist
With custom port and SSL key/certificate:
npx serve dist -l 8095 --ssl-cert .\cert.pem --ssl-key .\cert-key.pem
You can also put this command into your package.json, e.g.
"scripts": {
"serve": "vue-cli-service serve",
"prod": "npx serve dist",
...
}
Then just do:
npm run prod
Build should be deployed to the server, Hence, I don't think that there is any inbuilt way in vue-cli to run build locally.
To run build locally, we need to configure the server separately and run the build on the server as follow,
1) Install lite server via below command
$ npm install -g lite-server
2) Add below scripts in package.json
"lite": "lite-server –port 10001",
"start": "npm run lite"
3) In root directory create bs-config.js file and add below script
module.exports = {
port: 3000,
server: {
baseDir: './dist'
}
}
4) Lastly, Run it via below command
$ npm run start