How to add my own server code to webpack-dev-server execution - angularjs

Basic question about how to add my own server-based code to webpack-dev-server, or alternatively, replace webpack-dev-server with express (giving up hot module reloading). I expected to find a file called something like server.js, that I can add my own code to. This is a basic question, as every non-static application needs their own server code, but I haven't found a straight forward way of doing it. I'm using Angular 2 Webpack Starter. I would expect it to be easy to subsequently drop webpack-dev-server for straight express when going to production.

You can still use Express and have hot reloading, by using webpack-dev-middleware and webpack-hot-middleware.
Both middleware should not be loaded in production, for which you can use something like this:
// Webpack (when not running in production mode)
if (process.env.NODE_ENV !== 'production') {
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackConfig = require('./webpack.config');
const compiler = require('webpack')(webpackConfig);
app.use(webpackDevMiddleware(compiler, {
noInfo : true,
publicPath : webpackConfig.output.publicPath
}));
app.use(webpackHotMiddleware(compiler));
}
(app is an Express instance)

Related

How to run cubeJS-Backend application using express

I am trying to run cubeJs-backend application using express. I have added code changes like below.
I have created cube.js file with the below code
const express = require('express');
const path = require('path');
const expressApp = express();
const options = {
basePath: 'cube'
}
require('dotenv').config();
const core = CubejsServerCore.create(options);
core.initApp(expressApp);
I have used .env file for the environment variables. When I run the application using node cube.js the application got started and also connecting to the data base. But, when I try to load in the browser using http://localhost:4000 it is not loading.
Here is my .env values:
CUBEJS_DB_HOST=localhost
CUBEJS_DB_PORT=5438
CUBEJS_DB_NAME=test
CUBEJS_DB_USER=postgres
CUBEJS_DB_PASS=test
CUBEJS_DEV_MODE=true
CUBEJS_DB_TYPE=postgres
CUBEJS_API_SECRET=b6e176d3942fd2811bacfd2b5e5dd00b47aae3f07d92000961f17c60f4d9a30eca5bfde0e1f2d460d9e358a0a6be7b3fa6812f245713915a1effea402a716c13
CUBEJS_EXTERNAL_DEFAULT=true
CUBEJS_SCHEDULED_REFRESH_DEFAULT=true
CUBEJS_WEB_SOCKETS=true
Embedding Cube.js within Express (any other framework / in application) is deprecated.
I suggest you run Cube.js with Docker, as it’s a better solution than embedding it into an Express app.
This link might be helpful as well: https://cube.dev/blog/cubejs-loves-docker

How can we pass environment or config variables during run time in a cra(createreactapp)

How can we pass environment or config variables during run time in a cra(createreactapp). I do not want to build for different env but use one build with different configs in different env
You can add 2 environment variable files to the root of your project for development and production versions. They should be named;
.env.development - This will use npm start (dev stage)
.env.production - This will use for the build (prod stage)
A property can be added as bellow, give attention to the prefix REACT_APP_
REACT_APP_PROPERTY1=some_value
And this property can be read as,
<p>{process.env.REACT_APP_PROPERTY1}</p>
We build our create-react apps as static websites and we push them directly to a simple web server. That's why you can't use env variables there. We found a nice workaround and we plan to write a short post about it:
1. Start your app with (one) environment variable
Let's assume you have a development, staging and production environment, like we do most of our projects.
We set just one ENV variable REACT_APP_ENV in our start up scripts. Each environment has it's own start and build script.
# package.json
# ...
"scripts": {
"start": "REACT_APP_ENV=development react-scripts start",
"start:staging": "REACT_APP_ENV=staging react-scripts start",
"start:prod": "REACT_APP_ENV=production react-scripts start",
"build:staging": "REACT_APP_ENV=staging react-scripts build",
"build:prod": "REACT_APP_ENV=production react-scripts build"
},
2. Setup config file
In your create-react app you store a config file under src/config/index.js. In this config file you can define the values based on the environment.
# src/config/index.js
const env = process.env.REACT_APP_ENV
export const appConfig = {
api: {
networkInterface: ({
development: 'http://localhost:5000/graphql',
staging: 'https://project-staging.herokuapp.com/graphql',
production: 'https://project.herokuapp.com/graphql',
})[env],
// add more here
},
}
export default appConfig
3. Usage
In the app you access the config simple like this:
import config from './src/config'
# usage
config.api.networkInterface
I had the same question a couple of days ago and found a hacky, yet a potential solution. Basically, you use a config.js inside your /build/public directory. The config.js could be a simple code like this:-
window.DYNAMIC_PROPERTIES = {
"ENV": "UAT",
"API_ENDPOINT": "UAT"
}
You want this particular file to be a dynamically generated one (based on your environment). If you are interested in how I achieved this, read on till the end.
Now, to access this in react application, include this script in your index.html (head tags).
<script src="%PUBLIC_URL%/configs.js"></script>
Once this is done, you should be able to access the env variable dynamically in your application like this.
const envValue = window.DYNAMIC_PROPERTIES.ENV
const apiEndpoint = window.DYNAMIC_PROPERTIES.API_ENDPOINT
The basic idea here is that the HTML will execute the script in your build/public folder. This script will attach properties to the window scope and make them available to your application.
Now the whole point of doing all this is to be able to dynamically inject the environment variables. Here's how I achieved it:-
We use an nodejs (express) server to serve the UI, so I managed to dynamically create this simple js file in the /build/public/ folder. Sample code for the server.js:-
const path = require("path");
const express = require("express");
const fs = require('fs');
const app = express(); // create express app
fs.copyFile(`config.${process.env.ENVIRONMENT}.js`, "./build/config.js", (err) => {
if(err){console.log("Something went wrong while setting env variables", err)}
else{console.log("Env variables set for ",process.env.ENVIRONMENT )}
});
// add middlewares
app.use(express.static(path.join(__dirname, ".", "build")));
app.use(express.static("public"));
app.use((req, res, next) => {
res.sendFile(path.join(__dirname, ".", "build", "index.html"));
});
// start express server on port 5000
app.listen(5000, () => {
console.log("server started on port 5000");
});
Basically, I have separate config files like config.dev.js, config.uat.js and so on. The start command for this server would inject a property "ENVIRONMENT" as either dev or uat or prod and this node server will place the correct config files in the build/public at application startup (notice the fs.copyFile command).
Ok, hope this helps. If you find a better way to do this, do comment your solution.

How to parameterize variables in a React Webpack app for different environments?

I'm working on a React web app which was created by create-react-app and I am getting ready to deploy it.
The issue is, for development, the app uses the api instance running on my dev environment (localhost:{api-port}) but for the deployed app this should point to the server api instance (api.myapp.com).
Currently the host is just a variable in my networking component:
const hostname = 'localhost:9876'
I plan on using webpack to generate the static files which will be served by the production front-end, and I would like to continue developing using npm start as set up by create-react-app.
What would be the correct way to set up my project such that the host can be set automatically to the correct value based on whether I'm running the dev server or building for production?
A common solution is to check against process.env.NODE_ENV like this:
const hostname = process.env.NODE_ENV === "development" ? "localhost:9876" : "localhost:6789";
You may need to force the environment variable to be present in your Webpack configuration file using the DefinePlugin like this:
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV:JSON.stringify(process.env.NODE_ENV || "development")
}
})
]
An alternative solution might be to use the config package and provide your hostname string as a configuration parameter. config will inherit configurations from files based on the current NODE_ENV. It will start by using configuration from a default.json file, then override it with a development.json, or production.json, depending on your environment.
Note that you'll need for the config files to be copied to your output directory using CopyWebpackPlugin for it to work.
There are definitely many ways you could achieve that. One of those solutions would be to use webpacks's DefinePlugin. In your plugins section in webpack configuration you would add something like this:
new webpack.DefinePlugin({
API_HOST: process.env.NODE_ENV === 'production'
? JSON.stringify('localhost:8080')
: JSON.stringify('api.com')
}),
That creates a global variable API_HOST available everywhere in your codebase, which you can use. You can read more about the DefinePlugin here https://webpack.js.org/plugins/define-plugin/
you could use a relative path when you make any request to your api server instead of calling the full url for your app.
and for your development you could add a proxy property to your package.json file:
{
...
"proxy": {
"/api/*": {
"target" :"http://localhost:9876"
}
}
}
so whenever you make any request that prefixed with /api will be redirected to http://localhost:9876/api this is just in the development but in the production if you make a request prefixed with /api it won't be redirected it will be served normally because the proxy is just available in the dev server coming with create-react-app.

How to set different constants in angularjs app for prod / dev in webpack

I'd like to set a different url for an external api in an angularjs app depending on whether I am running in dev or prod mode:
a sketch of my app.js:
var API_URL = 'http://localhost:8000/api'; # dev config
...
app.constant("API_URL", API_URL)
I use webpack to locally serve the app on localhost:3000, and I also use it to build a prod version of the app (minified, etc) which consumes the api from a different location.
I was wondering if there is some way to configure the build process to set API_URL in the above to the desired production value:, ie:
var API_URL = 'http://app.example.com/api'; # prod config?
?
As answered in this SO question, you can solve this problem using Webpack's definePlugin to define environment variables:
webpack.github.io/docs/list-of-plugins.html#defineplugin

Webpack dev server run on different port

So I have IIS serving up my WebApi and AngularJS project on port 80, using a the alias mywebsite.local-dev.com in the hosts file.
I have webpack config setup for bundling, all I want to do now is stick webpack dev server over the top so that when I modify a file it re bundles everything and updates the browser.
I have browser-sync nearly working but require('./somehtmltemplate.html') seems to be causing issues. It's an Angular app so I use require in the ui-router template property. Here is my gulpfile:
var gulp = require('gulp'),
browserSync = require('browser-sync').create(),
watch = require('gulp-watch'),
webpack = require('webpack'),
webpackconfig = require('./webpack.config');
gulp.task("webpack", function(callback) {
// run webpack
webpack(
webpackconfig,
function(err, stats) {
if(err) throw new gutil.PluginError("webpack", err);
callback();
}
);
});
gulp.task('watch', function() {
browserSync.init({
proxy: "mywebsite.local-dev.com"
});
gulp.watch("App/**/*.js", ['webpack']).on('change', browserSync.reload);
gulp.watch("App/**/*.html", ['webpack']).on('change', browserSync.reload);
});
My question is, how do I get either one working.
edit
Because I am using .cshtml I can't use webpack-dev-server. So the question is, how can I get gulp working?
I solved a similar problem by having Browsersync proxy my external server (MAMP in my case, but it shouldn't matter) while using webpack-dev-middleware and webpack-hot-middleware as middleware on the proxy. With that setup, you can have your normal server take care of serving your app, and Browsersync+Webpack will just handle asset bundling & serving, and browser injections & reloads.
Here's a working example if you're interested: github.com/shanecav/webpack-browsersync-proxy

Resources