Configure base URL depending on environment - javascript

Suppose we have Angular 4+ app that needs to be located in different relative root URLs on different environments, i.e.:
http://localhost:4200/index.html for development
http://prod.server.com/angular-app/index.html for production
Most likely, we'd want to have that option in our environment.x.ts files:
export const environment = {
production: false,
appRoot: "/"
};
export const environment = {
production: true,
appRoot: "/angular-app/"
};
How can we configure Angular build/runtime infrastructure to automatically adjust the app depending on this option in environment.x.ts files?
UPDATE:
Since I'm using the Angular CLI toolchain indirectly via Visual Studio build/publish system (template), it'd be nice to have a solution based completely on Angular CLI + *.json/*.ts/*.js files. This way it would be suitable for any build system where Angular CLI could be used.

If you are using the Angular CLI you can do:
ng build --prod --base-href /myUrl/
OR
ng build --prod --bh /myUrl/

An alternative to the option described in #DeborahK answer could be to add build configurations to package.json and setup your IDE to specify the desired build configuration depending on environment it's building for.
Here is a snippet from package.json:
{
...
"scripts": {
...
"build": "ng build",
"build:Debug": "ng build --dev --base-href /",
"build:Release": "ng build --prod --base-href /angular-app/",
...
},
...
}
And here is a snippet of .csproj file to give you an idea of how it could be integrated with Visual Studio (credits to #Andrey_Fomin in this discussion):
<Target Name="NgBuildAndAddToPublishOutput" AfterTargets="ComputeFilesToPublish">
<Exec Command="npm run | findstr "build:$(Configuration)"" ConsoleToMSBuild="true" IgnoreExitCode="true" EchoOff="true" WorkingDirectory="$(MSBuildProjectDirectory)">
<Output TaskParameter="ConsoleOutput" PropertyName="NpmScriptName" />
</Exec>
<Exec Condition=" '$(NpmScriptName)'=='build:$(Configuration)' " Command="npm run $(NpmScriptName)" />
<Exec Condition=" '$(NpmScriptName)'!='build:$(Configuration)' " Command="npm run build" />
</Target>

UPDATED:
Carefully follow these steps and you are good to go :)
----------------------------------------------------------
1. Create 4 files in environment folder: (2 might there by default)
example:
environment.ts, environment.prod.ts,environment.test1.ts,environment.test2.ts
2. Use this common code for every file with slight change:
export const environment = {
production: true, //production is true for environment.prod.ts file
//for other test production is false
apiUrl: '' //base_url of each environment
};
3. Maintain a constant file where you will write all base urls.
code sample of constant.ts:
import { environment } from '../environments/environment';
let url = environment.apiUrl;
export const AppConstant = Object.freeze({
BASE_API_URL: url,
}
4. import this constant in your service or component class wherever your calling back-end.
5. In angular-cli.json:
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"test1": "environments/environment.test1.ts",
"test2": "environments/environment.test2.ts"
}
6.
ng build --env=prod
ng build --env=dev / ng build
ng build --env=test1
ng build --env=test2
7. if aot is creating problem. you can use : ng build --env=prod --no-aot
8. TO make things simple:
you can additonally add new build commands:
"scripts": {
"ng": "ng",
"start": "ng serve --env=local --no-aot",
"start:qa": "ng serve --env=dev --no-aot",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build:prod": "ng build --prod --env=prod --no-aot --output-hashing=all",
"build:dev": "ng build --prod --env=dev --no-aot --output-hashing=all",
"build:local": "ng build --env=local"
}
When you run,command is ==> npm run start OR npm run start:qa
OR==> npm run build:local or npm run build:dev, etc.
9. Hashing will solve caching isuue.
Hope it solves your problem. It works for me.

In angular 6 we can do it in better way, by using environment.x.ts (x means it might be production/development/configuration etc files).
suppose if its dev mode file name(environment.dev.ts)
export const environment = {
production: false,
appRoot: "/" or appRoot: "http://somerestapi"
};
suppose if its in production mode file name(environment.prod.ts)
export const environment = {
production: true,
appRoot: "/" or appRoot: "http://somerestapi"
};
and same appRoot can be used in all services as in below
service.ts file.
import { environment } from '../../environments/environment';
appRoot = environment.appRoot;
emplLoginCheckUrl = this.appRoot + "/checkValidUser";
validateUserDetails(employeeDetails): Observable<any> {
console.log(this.appRoot );
return this._httpClinet.post(this.emplLoginCheckUrl, employeeDetails);
}
after this we have one more job to do, its open your angular.json file
apply below changes to "dev": mode
"dev": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": true,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
and apply below changes to "production": mode
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
but you have to choose which one is needed to run the application, like if you want to run in dev mode use below command it will automatically apply appRoot(URL) for all aservices where you called.
ng build --configuration=dev (for development mode).
ng build --configuration=production (for production mode).

Related

Why won't my breakpoints get hit in Visual Studio Code

I'm trying the get the Visual Studio Code debugger working in my angular/typescript application but it's not working.
Here's what I have:
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug node",
"port": 9229,
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"localRoot": "${workspaceFolder}\\.dist",
"remoteRoot": "/usr/src/api/.dist",
"type": "node"
}
]
}
scripts/local-entry-point.sh
#!/usr/bin/env sh
set -e
echo "STARTING local-entry-point.sh"
FOLDER=/tmp/.dist
if [ ! -d "$FOLDER" ]; then
mkdir /tmp/.dist
fi
false | cp -ir ${FOLDER} /usr/src/api/ 2>/dev/null
rm -rf ${FOLDER}
cd scripts
npm run watch
scripts/package.json
{
"private": true,
"devDependencies": {
"#effect-ts/core": "^0.11.1"
},
"scripts": {
"watch": "nodemon --watch '/usr/src/api/.dist/**/*' -e ts,json,js -x npm run debug",
"debug": "node --inspect=0.0.0.0:9229 /usr/src/api/.dist/start.js"
}
}
docker-compose.yml
...
ports:
- 4002:8800
- 9229:9229
...
I put breakpoints in both my Typescript and the compiled Javascript in the .dist folder (on the corresponding line):
I start my application (npm run docker), start the debugger in vscode, go through the steps to run the code, but the breakpoints don't get hit.
Seems like you are using Typescript. AFAIK VSCode debugger needs a sourcemap to put breakpoints on ts projects. I think this doc might help https://code.visualstudio.com/docs/typescript/typescript-debugging

Javascripts not working on SSR with Angular 11 Universal

The SSR part is working, and it is reachable by localhost:4000, including our stylesheets etc. The package.json's relevant part is:
"dev:ssr": "ng run project:serve-ssr",
"serve:ssr": "node dist/project/server/main.js",
"build:ssr": "ng build --prod && ng run project:server:production",
"prerender": "ng run project:prerender"
But the problem is, the served website doesn't contain our javascript file in the body (eg. main.1234567.js) angular.json's relevant part is below:
{
"server": {
"builder": "#angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/project/server",
"main": "server.ts",
"tsConfig": "tsconfig.server.json"
},
"configurations": {
"production": {
"outputHashing": "media",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"sourceMap": false,
"optimization": true
}
}
}
}
When I check the dist/project/browser, I can see the index.html with the javascript files, also the javascript files themselves are in the directory.
But when I run "npm run serve:ssr", then the served website is missing all these javascript files.
What am I missing here, should I add a configuration to angular.json to include these files?

Next.js - Eslint is not linting any pages in dev mode (aside from pages/_app.js)

I'm having problems setting up eslint with Next.js. It actually properly lints all my files when I run next build, but when I run the application in dev mode (next), eslint only actually lints pages/_app.js, and totally ignores all my other files (eg. pages/index.js).
My next.config.js looks like this:
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
if (dev) {
config.module.rules.push({
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
loader: 'eslint-loader',
})
}
return config
},
}
and .eslintrc.js looks like this:
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/prop-types": 0,
"react/react-in-jsx-scope": 0
}
};
Is there a sample project somewhere that demonstrates setting up eslint with Next.js? Eslint is pretty much the standard for any modern JS web application, so I'm surprised to find no mention of eslint in the docs or any of the demo projects.
Ok I figured out the problem, next.js in dev mode doesn't actually lint any pages until you try to load them in your browser. So if you have linting errors on pages/index.js, you won't actually see them until you load your homepage in the browser. https://github.com/zeit/next.js/issues/9904
I was actually able to achieve the lint on dev mode using the npm concurrenly package with eslint-watch.
Doing this, my commands looks like (in package.json) :
"scripts": {
"dev": "concurrently \"npm run lint-js:watch\" \"npm run lint-md:watch\" \"next dev\"",
"build": "next build",
"start": "next start",
"lint-md": "remark .",
"lint-md:watch": "remark --watch .",
"lint-js": "eslint -c ./.eslintrc --ignore-path ./.eslintignore ./src",
"lint-js:watch": "esw -w -c ./.eslintrc --ignore-path ./.eslintignore"
}
Hope that will help!

webpack dev server listening a file with extension PHP ( "index.php")

everybody.
I am using the default configuration, without any additional packages.
After a run of command, "npm run dev" have opened the file PHP like a page in the browser but file have downloaded.
How I can setting config, that dev server could be listening to a file with an extension of PHP?
Config:
let path = require('path');
let conf = {
entry: './panel/js/index.js',
output: {
path: path.join( __dirname, 'panel/js' ),
publicPath: '/panel/',
filename: 'bundle.js'
},
devServer: {
index: '',
open: true,
overlay: {
warnings: true,
errors: true
},
host: 'test.io',
proxy: {
'**': {
target: 'https://test.io',
changeOrigin: true,
}
}
}
};
module.exports = conf;
package.json:
{
"name": "js",
"version": "1.0.0",
"description": "",
"main": "login-js.js",
"scripts": {
"dev": "webpack-dev-server --inline --hot --mode development --open",
"build": "webpack --mode production",
"start": "cross-env NODE_ENV=development webpack-dev-server --inline"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cross-env": "^5.2.0",
"path": "^0.12.7",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
},
"dependencies": {
"jquery": "^3.3.1"
}
}
Thank's for help.
Webpack DevServer is a simple http server, its purpose is to serve static files like html, css, js, images... (unless you are using it as a middleware in a nodejs app)
Typically you have to use its proxy option described here, pointing to your apache or nginx server which normally runs your php based webapp.
Edit based on your comments below
First of all you should use the .test domain for your local development server. See this article. You can't use test.io as it is now in your code (test.io is an existing site on the web). First make the website you are developing accessible on http://yoursitename.test or http://localhost if you run only this one site. For this you need a webserver like apache or nginx. Webpack won't serve a php site for you, it's not for that...
You should also use a better directory structure for your application files. Here's an example for common usage:
├── src
├── js
└── css
└── public
├── build
└── images
Then your webpack.config.js could look something like this (using the above structure):
const path = require('path');
const devMode = process.env.NODE_ENV !== "production";
let conf = {
mode: devMode ? "development" : "production",
entry: {
index: './src/js/index.js'
},
output: {
path: path.join( __dirname, 'public/build' ),
publicPath: '/build/',
filename: '[name].js'
},
devServer: {
index: '',
open: true,
overlay: {
warnings: true,
errors: true
},
host: 'yoursitename.test',
proxy: {
'**': {
target: 'http://yoursitename.test',
changeOrigin: true,
}
}
}
};
module.exports = conf;
Changes needed to your package.json:
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --progress",
"build": "cross-env NODE_ENV=production webpack -p --progress",
"start": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --open"
}
How to expand your knowledge
I have to tell you that these things are the very basics of Webpack and if you still can't succeed to make your app work, you should read a lot of documentation and articles about Webpack (as I did when I was new to it).
Start here and go trough all the items on the left. Guides will provide you a lot of examples and configuration will be useful when you know the basics well...

Using node-modules in main.js using electron-builder and webpack

First of all I do not know if the problem I am having is because of webpack or electron-builder or a combination.
To the problem.
When I build for development I am able to use installed node-modules in the main.js file specified in my package.json file{"main" : "app/main.js"}.
However when I have used electron builder to create an installer. When I have installed the app using the installer I get the following error message when starting the app:
My guess is that I get this message because the the needed node-modules can not be found by main.js. So how do I make them available?
I hope there is someone smarter than me our just better at googling :)
Package.js:
{
"main": "app/main.js",
"scripts": {
"hot-server": "node hot-server.js",
"build-bundle": "rimraf app/dist.release && better-npm-run build-bundle",
"start": "better-npm-run start",
"start-hot": "better-npm-run start-hot",
"backend": "node backend-dummy.js",
"dist-win": "npm run build-bundle && rimraf dist && build --win --ia32",
"dist-mac": "npm run build-bundle && rimraf dist && build --mac"
},
"betterScripts": {
"start": {
"command": "electron ./",
"env": {
"NODE_ENV": "production"
}
},
"start-hot": {
"command": "electron ./",
"env": {
"HOT": 1,
"NODE_ENV": "development"
}
},
"build-bundle": {
"command": "webpack --config webpack.config.production.js --progress --profile --colors",
"env": {
"NODE_ENV": "production"
}
}
},
"bin": {
"electron": "./node_modules/.bin/electron"
},
"build": {
"appId": "app",
"files": [
"dist.release/*",
"dist.resources/*",
"main.js",
"thirdparty/*",
"app.html"
],
"extraFiles": [
"lang/*",
{
"from": "build/extra",
"to": "./",
"filter": "**/*"
}
],
"asar": true
}
So I found a solution to my problem. What I did was I looked at this project:
https://github.com/chentsulin/electron-react-boilerplate
Where they have a special webpack.config.electron.js file that bundles all the node_modules for the main.development.js file into a main.js file that contains everything we need. And then when the electron program starts it uses this main.js bundle to run. To make this happen you need to add a build script in your package.json file that executes webpack.config.electron.js.
I think it is easier to understand how to solve it by looking the linked project than for me to explain.

Categories

Resources