Angular 5 and Wordpress - node.js

I am attempting to setup a project that uses both Angular 5 and Wordpress. Currently my solution allows the serving of both applications using node. From the root directory I run "node index.js" to run wordpress, and in a separate terminal, in a subdirectory I run "ng serve" to run the angular implementation.
Is it possible to run both angular and wordpress on the same terminal window? An example being, by typing "node index.js" in the root directory, can I serve both the angular application in a subdirectory and the wordpress through that one console?
My projects are pretty bare but here is some base code:
/index.js
const express = require('express')
const epf = require('express-php-fpm')
const options = {
// root of your php files
documentRoot: __dirname + '/wordpress',
// extra env variables
env: {},
// connection to your php-fpm server
// https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener
socketOptions: { port: 9000 },
}
const app = express()
app.use('/', epf(options))
app.listen(3000)
/subproject/protractor.conf.js
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
Thank you.

I am working on a new plugin, Xo for Angular that may provide a solve for the use case above.
https://wordpress.org/plugins/xo-for-angular/
Xo gives you the option to load an Angular App as a theme with WordPress serving only as the management interface. Routes can be generated dynamically so all pages and posts are instantly viewable on the front-end without needing to recompile.
For local development I recommend setting up either apache or nginx using a tool like XAMPP. I have detailed the setup I use for my own local development here: https://github.com/WarriorRocker/angular-xo-material
Once you have wordpress running through a server like apache you can then just run ng build and let Xo load your App/theme through the main front-end. Alternatively you can also run with ng serve for rapid development.
In production you can either have Xo load your App and inject wp_head/wp_footer as necessary (Live Redirect Mode) or redirect all front-end requests to your App's dist index.html (Offline Redirect Mode).
Additional docs (work in progress): https://angularxo.io/

Related

File serve in shopify app dev not working

I've created shopify app with node.js app template
npm init #shopify/app#latest
Folder structure is at the bottom
And run npm run dev
It's ok for api endpoints.
What I wanna do is to serve static files. In fact, this is an express.js server and I created a static folder in web folder
app.use(serveStatic('static'));
But I can't access static files. I tried app.use(serveStatic("${process.cwd()}/static")). The above stuff is working on a normal express.js project. But it does not work with shopify cli and vite config.
Vite config is
const config = {
test: {
globals: true,
exclude: ["./frontend/**", "./node_modules/**"],
},
};
export default config;
I finally got it.
I noticed that:
It works if you were to load using localhost:PORT/path/to/static.file. You can print out PORT in your web/index.js.
This simple middleware doesn't get triggered when requesting your static file through ngrok but it does get triggered by number 1 above.
app.use((req, res, next) => {
console.log("Backend hit!");
next();
});
That means the backend never got the static file request. My understanding is vite receives all the requests then proxies some of them to the backend using a config.
The config Shopify gave is not proxying the static file request so you'll need to modify the proxy config.
vite.config
...
export default defineConfig({
...
server: {
host: "localhost",
port: process.env.FRONTEND_PORT,
hmr: hmrConfig,
proxy: {
"^/(\\?.*)?$": proxyOptions,
"^/api(/|(\\?.*)?$)": proxyOptions,
// The next line is what I added
"^/static/.*$": proxyOptions,
},
},
});
web/index.js
app.use("/static", express.static(`${process.cwd()}/public`));
I'm mounting my static files on "/static" but feel free to modify the proxy line to suit your needs.

office-js + outlook-web-addins + Webpack + Production

I am totally new to NodeJS, Webpack and specially to Outlook Addin. So, I created my Outlook Addin using basic tutorials from https://learn.microsoft.com/en-us/outlook/add-ins/addin-tutorial, all went well.
However, when it came to deployment on Production, I struggled a lot. I put all my code up on Production (Ubuntu instance). First tested a simple NodeJS "hello World" app on Port:8080 and it worked just fine. Then I tried to start my Outlook Addin, just like I was doing locally, it started on port 3000, but I needed to run it on 8080 and in the background. So, I used "PM2", and here comes the "WALL".
pm2 start src/index.js doesn't work for me, as the inside Office.onReady or any other reference to Office does not work, throws undefined Office error.
I tried pm2 run-script build, (after modifications in package.json and webpack.prod.js files)
However, I am still getting the same error when try to run pm2 start dist/app.bundle.js
So, please guide me which file should I reference to when using pm2 start {filename/path}?
Here are some configurations that I am using,
webpack.common.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
polyfill: 'babel-polyfill',
app: './src/index.js',
'function-file': './function-file/function-file.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.html$/,
exclude: /node_modules/,
use: 'html-loader'
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: 'file-loader'
}
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Production'
}),
new HtmlWebpackPlugin({
template: './index.html',
chunks: ['polyfill', 'app']
}),
new HtmlWebpackPlugin({
template: './function-file/function-file.html',
filename: 'function-file/function-file.html',
chunks: ['function-file']
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
});
Contents of an Add-in
The files that are produced from your project when building should be at least some JavaScript, then perhaps HTML and some CSS, depending on what kind of add-in you're building. The most common is probably building an add-in with a task pane - which is basically a web page. In any case, the built files is not a Node.js web server.
Hosting your Add-in
Making your add-in available inside Outlook or Office requires that you host your files somewhere. It can be done with any web server - a simple python web server, Apache, Node.js HTTP server, or anything similar. It can be done on either localhost or in some other hosting service. The add-in tutorial shows you how to run a Webpack development server to host the files on https://localhost:3000 while you are coding (npm run start).
In your manifest.xml file you'll notice that you specify the address where your files are hosted. In my development setup, for an add-in with a task pane, I've specified that the files are hosted on localhost, like this:
<FormSettings>
<Form xsi:type="ItemRead">
<DesktopSettings>
<SourceLocation DefaultValue="https://localhost:3000/index.html"/>
<RequestedHeight>250</RequestedHeight>
</DesktopSettings>
</Form>
</FormSettings>
Production
However, when running your app in production, the tutorial says that you should do npm run build. Those files that are produced, need to be hosted somewhere. I've hosted my add-in on Amazon S3, which is another way of hosting files.
To simulate it on localhost, follow these steps.
In the same folder as your project (where the dist/ folder is located):
Run npm install http-server -g
Run http-server dist/
Tools
To clarify what the tools are used for:
Webpack is what puts your app together, from your source code to a bundled version which can be run in a browser context. Webpack development server can be used to host files on localhost during development
Node.js HTTP server can also be used to host files on your localhost
pm2 is a process manager for Node.js. You can use it for hosting a Node.js server in production
#shahroon and I working on the issue together. We're still not able to get things to work and have now paid for a support with Microsoft. Sadly and very frustratingly Microsoft hasn't even acknowledge our support ticket and it's been 3 days.

Nodejs application integrate with Angular application

Nodejs application created using Express (express genrator) and used handlebars as view engine. Created couple of routes and works fine. Application running on port 3000.
Express routes:
...
app.use('/', index);
app.use('/landing', landing);
app.use('/home', home);
app.use('/api', api);
...
There is an admin panel separate application built on Angular
Currently Angular application running on port 4200 and uses APIs from NodeJs application which running on port 3000.
Angular application routes
const routes : Routes = [
{ path: '', redirectTo: '/user', pathMatch: 'full' },
{
path: 'user',
component : UserComponent,
children : [
{ path:'', redirectTo: '/account', pathMatch: 'full' },
{ path: 'account', component: AccountComponent },
]
},
]
NodeJs application folder structure
api/
api.js
bin/
www
modules/
mongoose.js
node_modules/
public/
css/
fonts/
img/
js/
ngapp/ => Angular resources created with ng build
inline.bundle.js
main.bundle.js
polyfills.bundle.js
styles.bundle.js
vendor.bundle.js
routes/
home.js
index.js
landing.js
views/
common/
header.hbs
footer.hbs
layouts/
master.hbs
ngapp/
index.html => Angular index.html file
index.hbs
landing.hbs
home.hbs
app.js
package.json
What I'm trying:
Want to run both NodeJs and Angular application on same port i.e. port 3000.
What I have done:
Ran ng build and placed index.html file inside /views/ngapp/ of nodejs folder structure.
Created one 'user' route in nodejs and serving that index.html file of angular application. (May be this is not a good way)
app.get('/user', function (req, res, next) {
res.sendFile(path.join(__dirname + '/views/ngapp/index.html'));
});
Somehow its loaded but encountered an error:
My question is about how we can integrate Angular Application (may be running on separate route but on the same port) with NodeJs application which already have some routes defined and used view engine to render pages.
There are two possible solutions.
Use your node application to serve the static frontend files. Then you can't really use ng serve (this is probably what you'd do when running live).
You should be able to tell Express to serve static content from an Angular build directory like this:
app.use(express.static('../angular/dist'));
Which would work if you had a file structure like so and were running serve.js with Node:
-node server
-serve.js
-angular
-dist/*
You can customize as needed by configuring the Angular build folder to be wherever you need it, or use Grunt/Gulp to move files around to the folders you prefer with a build task.
Use nodejs with a different port, and use Angular's proxy config, to have Angular think the api port is actually 4200 (this is probably best during development).
This is primarily a concern during development I reckon, since you most likely wont (and shouldn't) be using ng serve live, so option 2 would be my best recommendation.
To configure a proxy, you create a file in your angular application root directory called proxy.config.json with the following content:
{
"/api/*": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
}
}
Then when you run ng serve, you run it with ng serve --proxy-config proxy.config.json instead.

React UI and Node.js/Express app served/monitored with webpack

I am new to React and Node, trying to setup an environment to work.
I worked a little with Node.js/Express before and I used nodemon to monitor file changes and restart my app.
Also I recently started to work with React and I use webpack dev server (specifically webpack-dev-server --content-base src --inline --hot --history-api-fallback) setup that monitors file changes and reload the UI.
The problem
Now, I want to tie it together.
First solution I found was: Start my node app on specific port, say 3000 then start webpack dev server on 8080 port and proxy requests to specific urls to my backend app.
devServer: {
proxy: {
'/backend-api/': {
target: {
"host": "localhost",
"protocol": 'http:',
"port": 3000
},
ignorePath: false,
changeOrigin: true,
secure: false
}
}
},
It should work but i do not feel right starting two servers for single application.
Is there any way (and simple example i could understand) to start single server that would serve both: a server side app and React UI?
And of course, it should track file changes and restart server app if server code changes OR reload UI if client side code changes.
You can use webpack through Express middleware using this package: https://github.com/webpack/webpack-dev-middleware
You can use it by simply adding it to the app:
var webpackMiddleware = require("webpack-dev-middleware");
app.use(webpackMiddleware(webpack({/* webpack options */})));
In addition there's a package that builds on this to offer hotloading and "Create React App" style terminal display: https://www.npmjs.com/package/webpack-express-middleware

Can't change the base folder for lite-server in Angular 2 application

I am going through the 5 minute quickstart of Angular 2. However, my application resides in src/ folder instead of at the root of my repository, and when I run npm start the application is trying to find an index.html file at the root. I read up on lite-server and documentation shows that it uses BrowserSync and I can reconfigure BrowserSync with a bs-config.json in my repository. I did that and this is what my config looks like:
{
"port": 8123,
"server": { "baseDir": "./src" }
}
According to the log it's using the specified config:
[1] > todo-app-angular2#1.0.0 lite E:\GitHub\todo-app-angular2
[1] > lite-server "./bs-config.json"
I also tried an override through bs-config.js
module.exports = {
port: 8123,
server: {
baseDir: "./src"
}
};
However the Angular application is still opened on port 3000 and it's disregarding the baseDir defined in the config. What am I doing wrong?
You should use a file called bs-config.js (instead of a bs-config.json one) since lite-server tries to load a module using the require function. The configuration should be a valid Node module:
module.exports = {
"port": 8123,
"server": { "baseDir": "./src" }
};
See this line in the source code: https://github.com/johnpapa/lite-server/blob/master/lib/lite-server.js#L20.
This file by default is loaded from the user's project folder.
Edit
After digging a bit more, the first part of my answer relies on the code from github but not the one actually installed using npm install (version 1.3.4)
There are two options in this case:
port
baseDir
Using this command will fix your problem:
$ lite-server --baseDir ./src --port 3333
Hope it helps you,
Thierry
The answer from Thierry Templier is not quite correct (anymore), you can use either the bs-config.json or bs-config.js configuration to adjust your browser-sync configuration. This is what I came up initially for the angular2 quick start example with JIT(Just-In-Time) and AOT(Ahead-Of-Time) compilation support (bs-config.json)
{
"port": 8000,
"server": ["app", "."]
}
to host the project from multiple directories.
However, I did not like this solution because by overwriting the server section in the json file, the default middleware configuration was overwritten at the same time.
Therefore I ended with the following approach, I took the default lite-server's config-defaults.js files and modified it instead (bs-config.js):
'use strict';
var fallback = require('connect-history-api-fallback');
var log = require('connect-logger');
/*
| For up-to-date information about the options:
| http://www.browsersync.io/docs/options/
*/
module.exports = {
port: 8000,
injectChanges: false, // workaround for Angular 2 styleUrls loading
filters: ['./**/*.{html,htm,css,js}'],
watchOptions: {
ignored: 'node_modules'
},
server: ['./', 'app'],
middleware: [
log({ format: '%date %status %method %url' }),
fallback({
index: '/index.html',
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml'] // systemjs workaround
})
]
};

Resources