Technology Stack - ProjectEvergreen/create-evergreen-app GitHub Wiki

As the case usually is, we often do (and should!) rely on some external dependencies to assist in application development. Not everything should be done by hand, especially if it falls far outside the scope of delivering immediate business value.

Below are some key technologies that provide direct benefit to the development process, by making it easier to develop more robust applications while also lowering the risk of coupling too tightly to any one particular abstraction that isn't native to the web platform.

⚠️ We could use your help!

If you're interested in keeping an eye on new standards and browser features, checkout some of our issues we've made to follow those proposals, or submit your own!

We appreciate all contributions! 🙏

Developement Guide

NodeJS

NodeJS is a command line interface for running JavaScript and boasts a robust ecosystem of great open source projects. Install the LTS version and verify that it, and its package manager npm are working, by running the following in your terminal:

$ node -v
$ npm -v

Yarn

Yarn is my personal preference for Project Evergreen, so for contributors, please install it too.

Workflows

It is recommended that npm scripts be used to capture common, development related workflows used in maintaining an application, like:

  • develop - task for starting a development server with file change detection, live reload, HMR, etc
  • build - task for building a production version of the application
  • test a task for running tests

These scripts are defined in a project's package.json, like so:

{
  "name": "my-app",
  "version": "0.1.0",
  "scripts": {
    "build": "rimraf ./build && webpack --config webpack.config.prod.js",
    "develop": "webpack-dev-server --config webpack.config.develop.js --open",
    "serve": "yarn build && cd build && http-server"
  },
  "dependencies": {},
  "devDependencies": {}
}

Run them from the command line in the root of the project

$ yarn develop

# or
$ npm run develop

Note: all developer dependencies should be saved locally to the project!

Tools

Dependency Management

Yarn is a CLI package manager alternative to npm, which Project Evergreen favors. However, please consider npm first since it comes with NodeJS until you find issues (typically when running lots internal UI libraries and application's at scale). Either way, commit your .lock file! 👌

Module Bundling

webpack is a web application bundler designed to make the building of modern JavaScript applications easy and extensible for a developers, with a focus on performance and build optimization for users.

In particular, webpack has a robust ecosystem of plugins that can be used for optimizating and fine tuning a web application to take advantage of latest best practices like inlining critical CSS and building a Progressive Web Application.

Project Evergreen follows webpack's recommended best practice of splitting up configurations.

JavaScript

Babel transforms newer JavaScript features down to "older" JavaScript for those browsers that don't support the newer JavaScript features. babel-preset-env and babel-polyfill are used to ensure that transformations only happen for those specific browsers we are targetting that don't understand the newer JavaScript features we are using.

As browsers evolve automatically ("evergreen"), the build will evolve as well, to longer need to transpile down to older JavaScript if it becomes unnecessary. Shipping the newest code will always provide the best benefit to our users.

Features We ❤️
Sample JavaScript Code

Note: this example extends from HTMLElement

// sample code
import { html, render } from 'lit-html';
import css from './footer.css';

class FooterComponent extends HTMLElement {

  constructor() {
    super();
    
    this.root = this.attachShadow({ mode: 'closed' });
    render(this.template(), this.root);
  }

  template() {
    return html`
      <style>
        ${css}
      </style>
      
      <footer>
        <h3>&copy; Project Evergreen 2018</h3>
      </footer>
    `;
  }
}

customElements.define('x-footer', FooterComponent);

// Usage: <x-footer></x-footer>

CSS

PostCSS, like Babel for JavaScript (see above), transforms newer CSS to older CSS for those browsers that don't support the newer CSS features being used.

Features We ❤️
  • Flexbox / CSS Grid
  • Nested Selectors
  • @import
  • CSS Variables
  • :host and other new psuedo-selectors
Sample CSS Code
/* sample code*/
:host {
  display: flex;
  justify-content: center;
  text-align: center;
  margin-bottom: 40px;
  cursor: pointer;

  & .header-text {
    margin: 0 auto;
  }
}

Libraries

lit-html

lit-html is a client side library that improves upon the JavaScript feature of tagged template literals by allowing the creation of HTML Templates (<templates>) using JavaScript, that can then be efficiently rendered and re-rendered.

Note: We are currently evaluating the use of lit-html-element or other similar base class solutions.

// example: HTML-in-JS (think of JSX)
import {html, render} from 'lit-html';

const HelloWorldComponent = (name) => {
  const name = name || 'World';

  return html`
    <h1>Hello ${name}!</h1>
  `;
}

render(HelloWorldComponent, document.getElementById('app'));
// example: consuming an external template (like for Vue / Angular), using webpack
import {html, render} from 'lit-html';
import HelloWorldComponentTemplate from '!to-string-loader!html-loader!./hello-world.template.html';

const HelloWorldComponent = (name) => {
  const name = name || 'World';

  return html`${HelloWorldComponentTemplate}`;
}

render(HelloWorldComponent, document.getElementById('app'));

This nicely compliments the Component Driven Development approach from the Styleguide, as well as the potential of not being needed when future specfications come along.

lit-html is not the only option here however, so check out some of the others if you want, like hyperHTML. Keep in mind that whatever library you use choose, that it sticks to the use of JavaScript template string literals.

Note

We can also use lit-html to import our CSS! See the Component Driven Development guide above for examples!

Check out this great talk by Justin Fagnani about lit-html.

LitElement

LitElement is a base class provided by the Polymer team that provides some nice decoration on top of the raw HTMLTemplate class and additionally provides some nice lifecycle hooks, like a _render() method. It also exports html from lit-html.

Here is an extended example using the HelloComponent from above that accepts an input to display a greeting.

import { LitElement, html } from '@polymer/lit-element';

class GreetingComponent extends LitElement {
  
  static get properties() {
    return {
      name: {
        type: String,
        attrName: 'name'
      }
    };
  }

  _render(props) {
    return html`
      <style>
        :host .name {
          color: green;
        }
      </style>
      
      <h1>Hello <span class="name">${props.name}!</span></h1>
    `;
  }
}

customElements.define('x-greeting', GreetingComponent);

// Usage
// <x-greeting name="Owen"></x-greeting>

hyperHTML

// TODO

Recommended Documentation

⚠️ **GitHub.com Fallback** ⚠️