Support 2 base URL's in Vue - vuejs2

Is it possible to support 2 base URL's, /test/app and /app with the Vue router? The http requests also have to use the updated path for API calls.
Maybe it's possible to do this with aliases in vue router. But this doesn't solve the API call problem for vue resource. And this would mean I have to create 2 paths for every page.

First and foremost, just so that you're aware, Vue-Resource has been deprecated from official recommendation status because they don't perceive Ajax as a functionality that requires deep integration with the Vue ecosystem.
Now, to the larger question. It sounds like you're trying to use different urls based on which environment you're in (ie. local development vs. production). The easiest way to do this would be to go to the file where you define your Vue-Resource root url and add the following:
var isProduction = process.env.NODE_ENV === 'production'
var rootUrl = (isProduction) ? 'http://production.domain/api' : 'http://localhost:8080/api'
Vue.http.options.root = rootUrl;
This code basically tests if you're in production and, if you are, assigns the production domain api to the variable, otherwise it assigns the local development domain api.
[EDIT]
I took for granted that you would be using the Vue-CLI which sets this up for you. If you are using NPM to start your Vue server, you're probably running a command like npm run dev, which references this line in your package.json:
{
// ...
"scripts": {
"dev": "node build/dev-server.js",
// ...
}
You can change that "dev" line to something like this:
{
// ...
"scripts": {
"dev": "NODE_ENV=dev node build/dev-server.js",
// ...
}
And that will create the NODE_ENV variable with your Node script which should allow you to use it now within the Vue context.

Related

Liberary dotenv-webpack doesn't work with vue 3 and webpack-cli

I'm using Vue 3 and Webpack 5 and wanted to install dotenv-webpack, but I can't get it to work.
Here's full code: https://github.com/golebiewska-n/webpack5-vue3
Setup:
package.json script I'm using to launch the app
webpack-cli serve
webpack.config.js
const Dotenv = require('dotenv-webpack')
...
module.exports = (env) => {
return {
...
plugins: [
...
new Dotenv()
]
}
}
.env (added in the root folder of my app)
VUE_APP_VAR=123
main.js
console.log(process.env)
and output in console is: "MISSING_ENV_VAR"
I tried removing new webpack.DefinePlugin({...}) from plugins in webpack config, but it didn't help.
In fact you successfully loaded the .env file with dotenv-webpack and the VUE_APP_VAR is accessible. It is just you cannot use the entire process.env object as dotenv-webpack does not allow it showing you MISSING_ENV_VAR instead.
If you chnange line 12 in your src\Layout.vue as follows:
- return process.env
+ return process.env.VUE_APP_VAR
you get your 123 value of the variable in your Vue app.
The reason is at the time of building your application with webpack dotenv-webpack replaces the explicit string process.env.SOME_EXPLICIT_VARIABLE_NAME_HERE existing in your code with the actual value of SOME_EXPLICIT_VARIABLE_NAME_HERE if that exist in the Webpack JS environment's actual process.env object.
This means you never get the entire process.env object accessible in your webpack bundle, and the bundle does not comprise the variable names like VUE_APP_VAR=123. This is the goal of dotenv-webpack.
You can get some more details in my answer here.
PS: DefinePlugin, being returned in the build config, could override process.env. It does so in Vue CLI (which is hardly justifiable). So its effect there sould be neutralized manually for dotenv-webpack to work within Vue CLI (v4 and v5) applications as expected.

Vue WebApp - Load latest build

I'm building a Vue.js application using Vuexy BootstrapVue template, deployed in a Docker container.
I am finding that when we deploy updates to our web app, that the User has to do a hard-refresh in their browser to load the latest version of the app, otherwise they'll be navigating around a cached version.
Is there a way for me to force a client browser to load the latest version for a User?
Either on every load, or every few hours?
(I've tagged Bootstrap-Vue for transparency, but don't actually know if it has any bearing on this issue)
You are facing the cache problem and there is multiple ways to handle this.
Cache Control
You can control the cache with the header with max-age or no-store, no-cache to simple disable it, like this question/answer: How do we control web page caching, across all browsers?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
https://csswizardry.com/2019/03/cache-control-for-civilians/
Cache busting
Aappending a version (example: 1.0.0) to query string of the script tag:
<script src="path/to/your/app.min.js?v=1.0.0"
and change that version for every build.
Hashing the script file
You can also use some webpack/rollup config to build the script with a hash, like app.bf43112.js
webpack
const config = {
output: {
path: PATHS.build,
filename: "[name].[contenthash].js",
},
};
Rollup
const isProduction = process.env.NODE_ENV === 'production';
export default {
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: isProduction ? 'bundle[hash].js' : 'public/build/bundle.js',
}
};
Reference: Hashed file names using Rollup
Service Worker
Another solution, that I never tested, but sounds a good method.. is creating a service worker to control how retrieve the js file:
https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker
You can do things like deleting the cache, responding the cache with a response that you manually fetch with js, etc.

SSR rendering exceeded timeout, fallbacking to CSR for (all routes)

I created a new angular project and ran the following command:
ng add #spartacus/schematics --baseUrl https://spartacus-demo.eastus.cloudapp.azure.com:8443/ --baseSite=electronics-spa --ssr. After, I ran the command npm run dev:ssr, opened http://localhost:4200 and found the following problem:
Any ideas how to correct this bug and make the app run SSR instead of CSR? This warning message is showing for every route I try to access.
(https://github.com/SAP/spartacus/issues/10638)
it's because of SSR optimization feature available in Spartacus 3.0 and up.
You can either extend the timeout in your server.ts (passing a second parameter to NgExpressEngineDecorator.get method) or set it to 0, so it won't be fallbacking to CSR at all. Here is an example:
const ngExpressEngine = NgExpressEngineDecorator.get(engine, { timeout: 0 });
You can use API documentation to get a list of available options:
https://sap.github.io/spartacus/interfaces/SsrOptimizationOptions.html
Additionally, an extended documentation regarding this feature is on its way and should be available soon.
I encountered same issue, but changing timeout does not help!
The root cause is: the certificate of Commerce Cloud is invalid, as it is self-assigned.
Because I am using local commerce, with URL: localhost://9002
And the workaround is:
Add below config to package.json
"scripts": {
"dev:ssr": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 ng run mystore:serve-ssr",
},
[...]
"devDependencies": {
[...]
"cross-env": "^7.0.0"
}
Then run following to start Spartacus
yarn dev:ssr

How to conditionally render JS in created() or mounted()

I'm using Nuxt JS 2.4.5 and am building a static website in SPA mode where running npm run build && npm run generate will generate my website in a dist/ directory.
I'm trying to figure out how I can do an if () {} else {} statement within either mounted() or created() to check whether I'm running my project in dev mode or production/generated website mode so that I can include a Google Analytics snippet, or conditionally render other content on the page based on the mode.
I've taken a look through the documentation and have found the following: https://nuxtjs.org/api/configuration-dev which looks to be of some help to me, but haven't yet put this into practice as I'm unsure of the best approach and am looking for guidance or an example.
I'm potentially thinking about trying the following:
layouts/default.vue
...
mounted () {
if (process.env.NODE_ENV == 'production') {
// run code on generated static site, e.g: Google Analytics
} else {
// run code if in dev mode, e.g: http://localhost:3000/
}
}
...
...and then in my package.json file I'd need to set production mode potentially on the generate command which builds the website using: NODE_ENV=production
package.json
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "NODE_ENV=production nuxt generate"
}
If I then run npm run build && npm run generate it should then build my static website and the Google Analytics code should then work.
I'l love to find out how other people are doing this and their solutions, I'm trying to get Google Analytics to work for every page and thus the layouts directory seems a good place to put the code.
I would set this up in the created() or beforeCreate() hook in the default.vue. There's no hard and fast rules against setting it up like this.
If you were doing this not using Nuxt but instead vanilla Vue, I'd put it in the main.js file where Vue is initialized.

How run Angular2 (front-end) and Symfony3 (back-end API) together in development zone?

This is my first question here. I have already spent hours reading topics, but never posted a question before.
At this moment I am developping an Angular4 application. I am running my app with "ng build --watch" and a local PHP webserver pointed to the 'dist' folder of my angular app. (When using build-in liveload server 'ng serve' there isn't a PHP server available, so i fixed this with 'ng build --watch' and a local PHP build-in server of PHPStorm)
To communicate with my MYSQL database, I used before single-php files in a directory called '/api'. I added this folder to my assets in the angular-cli.json file, so the API folder is also being pushed to the 'dist' folder when running the app local.
In this case, I was able to use relative paths to point my http requests. (like a POST action to '/api/insert.php'). So when publishing my app, it was not necessary to modify the paths of my HTTP requests.
But now I would like to use a backend framework, after some research I found http://api-platform.com, a PHP framework builded on Symfony3. When i am running this API, this runs for example on localhost:8000 while my angular applciation runs on localhost:4200.
So, that means i would have to use absolute paths for my HTTP requests. (eq http://localhost:8000/api/insert.php instead of /api/insert.php).
At this moment I have 2 projects: one front-end and one back-end. To make developping faster, easier, and simpler I would like to put both projects together. I know some developpers don't like this way of architecture, but in my case it is the best solution, one project, with a front and back-end included.
Concrete: Is it possible to run a debug-webserver in development zone with my angular app running on eq localhost and my symfony3/api-platform on eq localhost/api on the same time, same domain, and same port?
I would like to keep this project folder structure to keep it clean:
- projectname (root)
--- frontend
----- (all directories/files from angular)
--- backend
----- (all directories from api-platform / symfony3)
Sincerely,
Lander
running both application on the same domain (f.ex. localhost) is no problem, but they need to run on different ports. In your case angular is running on 4200 and your PHP application on 8000. You can configure angular with a proxy, which passes requests to http://localhost:4200/api to http://localhost:8000/api
In your angular root directory (where your package.json is), create a file proxy.conf.json
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
then change your package.json to use this proxy:
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
// other scripts
}
now run the webpack server with npm start instead of ng serve
Personally, I git ignore the proxy.conf.json, because some colleagues run their backend on a different port. Therefore we created a proxy.conf.dist.json with the above contents in git. If you want to use a different port, you can just copy it and change the port, while those, who want to use the default, can simply symlink to it.
UPDATE:
We recently switched to another method, namely using environment configurations.
By default, Angular has a dev and prod environment, specified in the .angular-cli.json
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
In these files, specify the API path:
environment.ts
export const environment = {
production: false,
apiUrl: '//localhost:8000'
};
environment.prod.ts
export const environment = {
production: true,
apiUrl: '//my-api-domain.tld'
};
You can add as many environments as you want (f.ex. for tests, beta, etc.). In angular, you can use the environment by importing it:
import {environment} from '../environments/environment';
But I suggest creating a config service following this answer: https://stackoverflow.com/a/43193574/7933618
I ended up by using another backend. In my case an nodeJS server was the best, fast and most simple solution.