How I Setup Separate Production and Development Environment of imba.js with Hot Reload

imba icon from imba, reload icon from, webpack icon from webpack


git clone and follow the readme

Why imba

My friend Daniel Cheung shared me a newsletter on imba, saying that imba makes use of memorized dom which allows rendering speed is much faster than Vue and React which uses virtual dom:

As I see imba looks powerful and the syntax is quite clean, I’d like to try it out in my next project, which I am going to use imba for both backend and frontend.

Development Environment Setup

Although the sample starter hello-world-imba is quite handy, in addition to this, I would like to separate my development and production environment, and I separate the client and server to 2 folders to make its structure clean. Then I found that the server side development server is not a hot reload one. Therefore I tried to do it.

Pass Environment Variable

To do environment separation, first, we need to pass something like NODE_ENV=dev into program runtime. For the client side, it can be achieved by passing an additional flag--env.NODE_ENV=dev to the webpack command, then inside webpack.config.js, I can retrieve the env in the function parameter. Next, we can plug this environment variable into program runtime using webpack’s DefinePlugin.

/// webpack.config.js
const webpack = require('webpack')
module.exports = env => {
  console.log(env)   //{NODE_ENV:"dev"}
  return {
    /*original parameters in starter*/
    plugins: [
      new webpack.DefinePlugin({ 'process.env':JSON.stringify({NODE_ENV:'production',...env})
    entry: "./src/client/index.imba",
/// src/client/index.imba
console.log process:env   //{NODE_ENV:"dev"}

As for the server side, in order to support cross-platform development, I used a node module called cross-env, then the server start command will be cross-env NODE_ENV=dev imba src/server/index.imba , then the variable is retrievable by process:env.NODE_ENV .

Then I further played with it by making a config.js which plugs configurations to process:config in according to NODE_ENV

/// config.js
const configs = {
  dev: {
    MODE: 'dev'
  production: {
    MODE: 'production'
module.exports = (key = 'production') => configs[key]
/// webpack.config.js
const webpack = require('webpack')
const configs = require('./config')
module.exports = env => ({
    new webpack.DefinePlugin({
      "process.config": JSON.stringify(configs(env && env.NODE_ENV || 'production'))
/// src/server/index.imba
var config = require('../../config')(process:env.NODE_ENV)
process:config = config

And that’s how I make an easy switch in environment variables. maybe a bit hacky, but it works.

Server Hot Reload

The client-side come with a hot reload development server already, but not our express server in imba. Then I tried nodemon imba src/server/index.imba , it fails. It seems because nodemon is trying to use node to execute imba script, which fails for sure. By further googling, I found what I missed is just a --exec flag, and I further limit the hot reload listening directory to be src/.

nodemon --watch src/ --exec cross NODE_ENV=dev imba src/server/index.imba

Start Both Client and Server Development Server in One Command

My another friend mcreng shared me a package called concurrently which is very easy to use. And so the final scripts looks like this

"scripts": {
"start": "npm run build && cross-env NODE_ENV=production imba src/server/index.imba",
"dev": "concurrently --kill-others-on-fail \"npm run server-dev \" \"npm run client-dev\"",
"server-dev": "nodemon --watch src/ --exec cross-env NODE_ENV=dev imba src/server/index.imba",
"client-dev": "webpack-dev-server --env.NODE_ENV=dev --content-base dist/",
"build": "webpack",
"watch": "webpack --watch --progress --colors --display-modules"

Finally, start both client and server hot reload development server by running npm run dev

(PS: this is my first post in Medium, if you have any suggestions, please kindly tell me, thank you~)