Overview
My javascript framework of choice is ember.js. Ember has been stable since version 1.0 and the upgrade path has been a focus of the core ember team between backwards compatibility and code-mods. Keeping ember up to date is one of the most under appreciated features.
Let’s add a new “client” service to our docker compose config we built from the phoenix getting started.
# docker-compose.yml
version: '3.7'
# ...
services:
# ...
client:
working_dir: /client/src
build:
context: ./client
dockerfile: Dockerfile
volumes:
- type: bind
source: ./client/src
target: /client/src
- node_modules:/client/src/node_modules
tmpfs: /client/src/tmp
depends_on:
- server
ports:
- '4200:4200' # ember server
- '7020:7020' # livereload
command: 'ember server'
# ...
volumes:
# ...
node_modules:
Some important notes about the client service config, we are adding a node_modules
volume to keep all installed modules local to the container and not install them in our host machine. We are also specifying a tmpfs
at /client/src/tmp
where all our tmp files are at to exclude them from being synced to our host maching and avoid slowing down our builds.
For our client/Dockerfile
we will include chrome for the ember test suite and watchman to automatically rebuild on file changes. Parts of this docker file are borrowed from danlynn/ember-cli. I wanted to build off of a slim
image to keep our container size to a minimum, I’m also adding ember-cli-update to help keep our ember project up to date.
# client/Dockerfile
FROM node:10.13-slim
### Install watchman build dependencies
RUN \
apt-get update -y &&\
apt-get install -y \
autoconf \
automake \
build-essential \
git \
libssl-dev \
libtool \
pkg-config \
python-dev
### set container bash prompt color to blue in order to
### differentiate container terminal sessions from host
### terminal sessions
RUN \
echo 'PS1="\[\\e[0;94m\]${debian_chroot:+($debian_chroot)}\\u@\\h:\\w\\\\$\[\\e[m\] "' >> ~/.bashrc
### update yarn
RUN curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
### install watchman
### Note: See the README.md to find out how to increase the
### fs.inotify.max_user_watches value so that watchman will
### work better with ember projects.
ENV WATCHMAN_VERSION v4.9.0
RUN \
git clone https://github.com/facebook/watchman.git &&\
cd watchman &&\
git checkout ${WATCHMAN_VERSION} &&\
./autogen.sh &&\
./configure &&\
make &&\
make install
### install ember-cli
ENV EMBER_VERSION 3.8
RUN \
yarn global add \
ember-cli@${EMBER_VERSION} \
ember-cli-update
Before we can start our new docker service, we need to create the client/src
folder by adding a client/src/.gitkeep
file.
Now we can run docker-compose up --detach --build
to create our new ember client container.
Now we can generate our ember application. We will use ember init
since we already have our project directory.
$ docker-compose run --rm client \
ember init \
--name get_social \
--welcome false \
--yarn true \
--skip-bower true
We should be able to restart our client container with docker-compose restart client
and visit localhost:4200 to see our new ember application.
Feature Flags
Once we have our ember project initialized, we need to set some feature flags. We can see the list of available feature flags by running:
$ docker-compose run --rm client \
ember feature:list
At the time of writing (ember-cli: 3.7.1), these are the features we will be flagging.
Template Only Glimmer Components
Introduce a low-level “flag” to remove the automatic wrapper <div> for template-only components (templates in the components folder that do not have a corresponding .js file).
$ docker-compose run --rm client \
ember feature:enable \
template-only-glimmer-components
Application Template Wrapper
Introduce a low-level “flag” to remove the automatic wrapper <div> around Ember apps and tests.
$ docker-compose run --rm client \
ember feature:disable \
application-template-wrapper
Disable jQuery Integration
For the past Ember has been relying and depending on jQuery. This RFC proposes making jQuery optional and having a well defined way for users to opt-out of bundling jQuery.
$ docker-compose run --rm client \
ember feature:disable \
jquery-integration
Then we need to remove jQuery from our package.json
.
$ docker-compose run --rm client \
yarn remove \
@ember/jquery
With jQuery removed, we need to configure ember-data to use fetch
instead of jQuery. This is done by adding ember-fetch
.
We will start by adding it to our package.json
.
$ docker-compose run --rm client \
yarn add \
ember-fetch
And then configure our application adapter.
$ docker-compose run --rm client \
ember g adapter application --pod
NOTE: I like to specify --pod
for all generators except for models
. This will group the files into the same folder as opposed to grouping them by type. (i.e. app/application/adapter.js
vs app/adapters/application.js
.
// project/client/src/app/application/adapter.js
import DS from 'ember-data';
import AdapterFetch from 'ember-fetch/mixins/adapter-fetch';
export default DS.JSONAPIAdapter.extend(AdapterFetch, {
});
With our option flags set and ember-data configured to use fetch over jQuery, we can restart our client with docker-compose restart client
and visit localhost:4200 to see our new ember application.
To see what’s going on in our client container we can run docker-compose logs -f client
to peek at the logs.
Bootstrap
In the same vein of leveraging frameworks for our client and server applications, I like to use bootstrap for my CSS framework base. For component styling I’ve been using css-modules
to help keep my component styles organized and prevent accidental side effects.
First, let’s install our dependencies.
$ docker-compose run --rm client \
yarn add \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected]
Now we need to rename our styles/app.css
to styles/app.scss
and import bootstrap:
$ mv client/src/app/styles/app.css client/src/app/styles/app.scss
// project/client/src/app/styles/app.scss
@import 'node_modules/bootstrap/scss/bootstrap';
Now we can restart our client with docker-compose restart client
and visit localhost:4200 to see our updated styles.
NOTE: ember-css-modules-sass
is needed to make ember-cli-sass
and ember-css-modules
play nice together.
Test Suite Setup
We can also run the test suite with:
$ docker-compose run --rm --publish "7357:7357" client \
ember test --server
And open http://localhost:7357 to run the tests.
Let’s commit our changes and carry on.
$ git add . --all
$ git commit -m "adding ember project"
Running Tests in CI Mode
If you want to run the ember tests in the docker container without having to open chrome, you’ll need to install chrome with the client/Dockerfile
.
# client/Dockerfile
# ...
# install watchman
# ...
### install chrome for default testem config (as of ember-cli 2.15.0)
RUN \
apt-get update &&\
apt-get install -y \
apt-transport-https \
gnupg \
--no-install-recommends &&\
curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add - &&\
echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list &&\
apt-get update &&\
apt-get install -y \
google-chrome-stable \
--no-install-recommends
### tweak chrome to run with flags
RUN \
sed -i 's/"$@"/-no-sandbox --disable-setuid-sandbox --headless --disable-gpu --remote-debugging-port=9222 "$@"/g' \
/opt/google/chrome/google-chrome
# ...
With chrome installed in the container we can run our tests in CI
mode which runs our tests in the container using chrome’s headless mode:
$ docker-compose run --rm --publish "7357:7357" -e CI=true client \
ember test --server