▲ img
imba icon from imba, reload icon from https://www.freeiconspng.com/img/16893, webpack icon from webpack
TLDR;
git clone https://github.com/dipsywong98/imba-template 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: https://medium.freecodecamp.org/the-virtual-dom-is-slow-meet-the-memoized-dom-bb19f546cc52
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 => ({
...
plugins:[
...
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~)