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

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.

Related

Spartacus API calls return 504 (Gateway Timeout) when running using Server Side Rendering (SSR)

I'm trying to get Spartacus to work with SSR. When opening the default URL, http://localhost:4200, the storefront renders, as expected, but only after I clear the site data first. When I attempt to browse the storefront, API calls fail with a 504 (Gateway timeout). Chrome dev tools indicates the error is happening in the service worker. At this point, I'm wondering if I configured Spartacus incorrectly. When running Spartacus using yarn start rather than yarn serve:ssr, I can load the home page and browse the site normally.
OS: Ubuntu 16.04.6 LTS
Chrome Version: 73.0.3683.75
Node version: 11.15.0
Angular CLI version: 8.3.8
Yarn version: 1.19.1
ng new ssr-spartacus-app --style=scss
cd ssr-spartacus-app
ng add #spartacus/schematics --baseUrl https://localhost:9002 --baseSite cmssiteuid --pwa --ssr
rm src/app/app.component.html
echo "<cx-storefront>Loading...</cx-storefront>" > src/app/app.component.html
yarn build:ssr
yarn serve:ssr
Before running yarn build:ssr, I made following change to the app.module.ts file:
Before
context: {
baseSite: ['cmssiteuid'],
},
After
authentication: {
client_id: 'mobile_android',
client_secret: 'secret',
},
context: {
urlParameters: ['baseSite', 'language', 'currency'],
baseSite: ['cmssiteuid'],
},
I also set anonymousConsents to false. With this set to true, I was getting a lot of CORs errors.
If been scratching my head with this for a little while now and I'm hoping someone with more knowledge of Spartacus' inner workings can shed some light on why Spartacus is behaving this way with SSR.
I'm not sure that I can give you some certain recipe to fix the issue, obviously I need more details and logs relates to your problem, but still, based on my experience I can share with you some tips and tricks about how we should play with such issues (which relates to SSR).
Some set of theory which relates to SSR
https://angular.io/guide/universal (you can feel free to use Angular official documentation as a primary source, cuz Spartacus uses Angular OOTB features to make it works)
https://sap.github.io/spartacus-docs/server-side-rendering-in-spartacus/
https://enable.cx.sap.com/tag/tagid/spartacus (SSR related videos)
Practical approaches for debugging SSR
You should observe and analyze console output during starting your application in Node.js
You can use SSR configuration from example Storefront application (https://github.com/SAP/spartacus/tree/develop/projects/storefrontapp) like a starting point, cuz OOTB SSR works like a charm
Something from Spartacus team https://sap.github.io/spartacus-docs/how-to-debug-server-side-rendered-storefront/
Common set of theory to ensure that application has been configured correctly
SAP Commerce Cloud configuration for working with Spartacus https://sap.github.io/spartacus-docs/installing-sap-commerce-cloud/
Take a look on the guide https://sap.github.io/spartacus-docs/building-the-spartacus-storefront-from-libraries/ to ensure, that your frontend application has correct configuration
Double check your configuration which B2cStorefrontModule is using (here you can find an example project here https://github.com/SAP/spartacus/tree/develop/projects/storefrontapp)
Take a look on Network and Console browser tabs and try to resolve all errors
did you turn off PWA?
Turn PWA off.
As soon as Spartacus is installed in PWA mode, a service worker is installed, and it serves a cached version of index.html, along with the js files. This results in SSR being completely skipped. The following steps describe how to turn off PWA:
Check that there are no service workers registered in your app. If you do find any service workers, remove them.
Turn PWA off in your app module configuration, as follows:
StorefrontModule.withConfig({
backend: {
occ: {
baseUrl: 'https://[your_enpdoint],
},
},
pwa: {
enabled: false,
},
};
Rebuild your local Spartacus libraries by running the following command:
yarn build:core:lib
Build your local Spartacus shell app by running the following command:
yarn build --prod
Build the SSR version of your shell app by running the following command:
yarn build:ssr
Start Spartacus with the SSR server by running the following command:
yarn serve:ssr
If you are getting 504 after hitting the API service you need to check your API logs.
IF you have err log:
{"instant":{"epochSecond":1644915623,"nanoOfSecond":929833000},"thread":"hybrisHTTP1","level":"ERROR","loggerName":"org.springframework.web.servlet.DispatcherServlet","message":"Context initialization failed","thrown":{"commonElementCount":0,"localizedMessage":"Error creating bean with name 'cartEntriesController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultStockValidator' defined in ServletContext resource [/WEB-INF/config/v2/validators-v2-spring.xml]: Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [de.hybris.platform.ycommercewebservices.stock.impl.DefaultCommerceStockFacade] to required type [de.hybris.platform.commercewebservices.core.stock.CommerceStockFacade]: Failed to convert value of type 'de.hybris.platform.ycommercewebservices.stock.impl.DefaultCommerceStockFacade' to required type 'de.hybris.platform.commercewebservices.core.stock.CommerceStockFacade'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'de.hybris.platform.ycommercewebservices.stock.impl.DefaultCommerceStockFacade' to required type 'de.hybris.platform.commercewebservices.core.stock.CommerceStockFacade': no matching editors or conversion strategy found","message":"Error creating bean with name 'cartEntriesController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultStockValidator'
You can try resolution:
Remove template extension ycommercewebservices extension from manifest.json, rebuild and redeploy with "Migrate Data" mode.

Angular 8 differential loading failing due to auth issues with dotnet core

I recently updated from Angular 7 to Angular 8 using ng update. After following the expected migration path with no issues I built and deployed. Everything worked great until I started checking other browser versions and realized some were getting 401 unauthorized from the server in requesting the js files.
The issue is, the differential loading is done like this:
<script src="main-es2015.1234.js" type="module"></script>
It seems that some browsers, some of the time, don't want to pass auth info for <script type="module" .... It strikes me that there are several ways to work around this:
I can work around this by adding crossorigin="use-credentials" to the script tag but I haven't been able to find how to do that in ng build.
I can tweak the auth settings to somehow allow anonymous requests through to my JS files but I haven't been able to find the dotnet core method of doing this without a lot of complexity. Right now the entire app only allows windows auth. If I allow anonymous I don't want to have to worry somehow that I've left a controller open.
I'm thinking the former option is the cleaner solution but I'm open to alternatives.
Since the posting of the accepted answer the option to handle this in the first way McAden suggests by adding crossorigin="use-credentials" has been added to the Angular CLI options.
Original feature request
Angular CLI documentation
In your angular.json add
{
...,
"build": {
"builder": ...,
"options": {
...
"crossOrigin": "use-credentials"
}
}
}
I modified angular.json and used an explicit deployUrl under projects -> main -> architect -> build -> options:
"deployUrl": "/ClientApp/dist/",
That alters the script tags:
<script src="/ClientApp/dist/main-es2015.1234.js" type="module">
So it no longer goes through the dotnet core application to pull the js file. Then in IIS I set that folder to allow anonymous.

How to use npm start on remote dev box with create-react-app

I would like to know how to use the create-react-app "npm start" script when development takes place on a remote host.
Nginx is running as a reverse proxy. The external uri looks like:
https://my-dev-box/my-cra
which is set to proxy to:
http://localhost:3000
The CRA app is static (ie no API calls).
The errors appearing in the browser's web dev console are 404s related to /static/js/bundle.js and favicon. The app's index.html page is served with a 200 response.
When I build the app, "npm build" produces an index.html file with the correct paths (courtesy of the "homepage" setting in package.json). I have looked at the documentation/tickets surrounding "Invalid Host Header" and "DANGEROUSLY_DISABLE_HOST_CHECK" but have not found a combo which works for me.
It appears to me that the fundamental issue is that "npm start" does not seem aware (as "npm build" is aware) that the WebDevServer is behind a proxy and is thus not constructing correct paths for resources.
So to restate the question, does anyone know how to get "npm start" working nicely behind a reverse proxy on remote development box. (create-react-app version used: 1.5.2)
(Note: application works perfectly behind proxy when using "npm build".)
Update: Courtesy of this question I found this comment in "webpack.config.dev.js":
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
const publicPath = '/';
which I guess means that what I want to do is not going to be that practical unless I eject the project. (Which I'm a little reluctant to do - the reason for using create-react-app is newness to React.)

Support 2 base URL's in Vue

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.

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.