{ muddling through code } https://www.muddlingthroughcode.com Welcome to { muddling through code }. This is my journey to learn, grow, and /* occasionally */ muddle through code. Thu, 18 Jul 2019 02:51:16 GMT http://blogs.law.harvard.edu/tech/rss Feed for Node.js { muddling through code } https://www.muddlingthroughcode.com/images/see-no-evil-monkey-emoji--large.png https://www.muddlingthroughcode.com &copy; 2019 Eric Constantinides Node.js Express <![CDATA[New React Notes]]> https://www.muddlingthroughcode.com/new-react-notes https://www.muddlingthroughcode.com/new-react-notes Mon, 10 Jul 2017 00:00:00 GMT

In teaching myself React, these are my cheatsheet notes that I've taken. They are in no way complete, but they have helped me get off the ground using React.

Components

There are 2 types of React components:

  • Functional Component or Stateless function - Doesn't contain state. Start with this until you need something more
  • Class Component - uses ES6 class structure; primary type which can contain state

Functional Component

const MyComponent = () => {
  return (
    <div>
      [...JSX stuff...]
    </div>
  )
}

Class Component

import React, { Component } from 'react'
class MyComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {}
  }
  render() {
    return (
      <div>
        [...JSX stuff...]
      </div>
    )
  }
}
  • { Component } is a fancy ES6 way to pull out React.Component
  • if using state, it must be initialized in constructor()
  • JSX must be wrapped in an element (in this case, <div>) or a self closing element (like an <input />)

Component w/ Event Handler

class SearchBar extends Component {
  render() {
    return (
      <input onChange={this.onInputChange} />
    )
  }
  onInputChange(event) {
    console.dir(event.currentTarget)
  }
}
  • curly braces {} are used to compile the JSX as JS
  • Don't use quotes around curly braces
  • the onChange event handler is also a prop
  • we use this.onInputChange so it knows that its a function inside our class

State

State is a plain javascript object that is used to record and react to javascript events.

  • Each class-based component has its own state object
  • when component state is changed, it auto re-renders itself and its children
class SearchBar extends Component {
  constructor(props) {

    // this gives us the Components props
    super(props)

    // only place we'll use `this.state` to "initialize"
    this.state = { searchTerm: '' }
  }
  render() {
    return (
      <input onChange={event => this.setState({ searchTerm: event.target.value })} />
    )
  }
}
  • this is uninitialized inside constructor() if super() is not called
  • thus, if you call constructor() you must call super()
  • Call super(props) (as opposed to super()) only if you need this.props inside of constructor(props)

Fleshed out Component

class SearchBar extends Component {
  constructor(props) {

    // this gives us the Components props
    super(props)

    // to initialize state; only we use `this.state=`
    this.state = { searchTerm: 'Enter search here' }
  }
  render() {
    return (
      <div>
        <input
          value={this.state.searchTerm}
          onChange={this.onInputChange.bind(this)} />
      </div>
    )
  }
  onInputChange(event) {
    this.setState({ searchTerm: event.target.value })
  }
}
  • we need to .bind(this) so that this.setState() knows where to go

Downwards Data Flow - only the most parent component should be responsible for fetching data.

SENDING AND RECEIVING DATA

Send data down to child component:

render() {
  return (
    <VideoList videos={this.state.videos} />
  )
}
  • just pass it as a prop on VideoList element render

Receive data up from parent component

In a functional component:

const VideoList = (props) => {
    console.log(props)
}

In a class component

class VideoList extends Component {
    console.log(this.props)
}

REACT AUTOMAGICALLY RENDERS ARRAYS

const VideoList = (props) => {
  const videoItems = props.videos.map(video => <VideoListItem key={video.id.videoId} video={video} />)
  return (
    <ul className="col=md-4 list-group">
      {videoItems}
    </ul>
  )
}
  • See how we just use {videoItems} and it works!

To use a passed around function

  • from my-inner-component.js

    const myInnerComponent = (props) => {
    const thisCompsData = props.thisCompsData
    const myClickFn = props.myClickFn
    return (
      <li onClick={() => myClickFn(thisCompsData)}></li>
    )
    }
    
  • Glorious ES6 Destructuring gives us:

    const myInnerComponent = ({thisCompData, myClickFn}) => {
    // do stuff //
    

Patterns for Event Handling

bind this in render() event

render() { return <input onClick={this._hndlClk.bind(this)} /> }
_hndlClk() { console.log(this.state.something) }
  • minor performance hits
  • Avoid declaring arrow functions or binding in render for optimal performance. Use this ESLint rule.

use arrow function in render() event

render() { return <input onClick={() => this._hndlClk()} /> }
_hndlClk() { console.log(this.state.something) }
  • minor performance hits
  • Avoid declaring arrow functions or binding in render for optimal performance. Use this ESLint rule.

preestablish bind in constructor

class HelloWorld extends React.Component {
  constructor(props) {
    super(props)
    this._hndlClk = this._hndlClk.bind(this)
  }
  render() { return <input onClick={this_.hndlClk()} /> }
  _hndlClk() { console.log(this.state.message) }
}
  • Pro: Better performance
  • Con: Harder to read

use Big Arrow Function instead of function

_hndlClk = () => { console.log(this.state.message) }
render() { return <input onClick={this._hndlClk} /> }
  • Best approach
  • No performance hits
  • works because arrow functions don't affect this
  • must enable transform-class-properties or enable stage-2 in Babel.

JSX Spread Attributes

From: https://facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes

If you already have props as an object, and you want to pass it in JSX, you can use ... as a "spread" operator to pass the whole props object. These two components are equivalent:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'}
  return <Greeting {...props} />
}

Spread attributes can be useful when you are building generic containers. However, they can also make your code messy by making it easy to pass a lot of irrelevant props to components that don't care about them. We recommend that you use this syntax sparingly.

Your Apps's structure

  • App state is in the root
  • Visual/UI state will be in other components
  • App Functions will trickle down to child components to use in its props
  • Component Elements have native JavaScript events (onChange, onClick, etc)
  • native events can call inner functions (handleChange, handleClick, etc)
  • If they affect App State, have then execute a "trickled-down" App function
  • If they affect visual, they'll change a Component State

build process

  1. Break your app into components as you'd see on-screen
  2. Determine app's global state-changing functions
     1. Add as placeholder functions inside the parent app
    
  3. Create the components
     1. Pass app functions as props
     2. Don't worry about functionality
    
  4. Add in visual component state changes
  5. Add in event
]]>
eric@ericconstantinides.com (Eric Constantinides)
<![CDATA[Optimizing Images]]> https://www.muddlingthroughcode.com/optimizing-images https://www.muddlingthroughcode.com/optimizing-images Mon, 03 Jul 2017 00:00:00 GMT

For years I've been annoyed at websites having big beautiful PNGs taking monumental amount of time to load. Over the years, I've created this method to vastly cut down the size of PNGs while both retaining quality and maintaining alpha transparency.

These instructions show how to optimize PNGs for display on the web.

Setup

  1. These instructions are created for Mac users. Windows optimizations will be similar, but with different programs
  2. Download and install the following 2 open-source programs:

Instructions

  1. In PhotoShop or other image editing software, load the image you'd' to optimize.
    1. Remove any background so you have a transparent image
    2. Trim the image so there is absolutely no padding between the image side and the actual image
    3. Save for Web SHIFT-OPTION-COMMAND-S the image:
    4. Save as a PNG-24 transparent PNG. DO NOT save it as a 256 color, 8-bit PNG.
  2. After saving, open the image in ImageAlpha:
    1. On the left hand side of ImageAlpha, you'll see the following areas:
    2. Media Cut (pngquant) Leave this setting alone
    3. Colors This is the setting to change. Only change with the slider and not by finite numbers (ie, stay at 2,4,8,16,32,64,128,256 colors). Do not go above 256 colors as that defeats the purpose of optimization.
    4. Options
      • Dithered Keep checked. Only uncheck if there is an unintentional gradient you'd like to remove
      • IE6-friendly alpha_ Always keep unchecked. Nobody uses IE6 anymore.
    5. Backgrounds Used to test how the PNG will look on different backgrounds. The green usually work best but depends on the image.
    6. On the bottom you'll see the following areas:
    7. Image Size Shows your image optimization success
    8. Smooth scaling Always keep checked
    9. zoom slider Move to ½x on Retina systems to see the image Retinafied
    10. To optimize image:
    11. Choose a contrasting background to fully see the outlines
    12. Move the Colors slider as far left as possible without a noticeable loss in quality
      • Take special note on how the image outlines look against the background
      • More complex, non-gradient PNGs can look good down to 16 colors
      • Very simple non-gradient PNGs can look good down to 4 colors
      • Gradient PNGs may have to go as high as 128 colors and sometimes (rarely) 256 colors
    13. When satisfied, save the image:
    14. FileSave as -or- [SHIFT-COMMAND-S]
    15. Name it the same or overwrite the original file (I usually overwrite it)
    16. Check Optimize with ImageOptim
  3. ImageOptim will now optimize the image
  4. Celebrate!

Try it yourself!

Practice on the logo-monkey-with-a-banana-before.png and match it to the logo-monkey-with-a-banana-after.png

  1. Monkey is reduced and trimmed with PhotoShop.
  2. Monkey is optimized in ImageAlpha at 16 colors (8 colors show aberrations on the monkey's outline)
  3. After optimization, Monkey is 95% smaller with virtually no loss in quality

Before

70kb(!) before optimization

After

5kb(!) after optimization

]]>
eric@ericconstantinides.com (Eric Constantinides)
<![CDATA[CSS Breakout]]> https://www.muddlingthroughcode.com/css-breakout https://www.muddlingthroughcode.com/css-breakout Mon, 26 Jun 2017 00:00:00 GMT

CSS Breakout appears to be very simple. It "breaks" out of a normal container to either a skinny container, site container, or to the maximum browser boundaries. No closing and then reopening of a div tree is necessary. Absolutely no special HTML structure is required. And it's all done in pure CSS - no javascript is used whatsoever.

Why do I need this?

One of the primary uses of CSS Breakout is to break out of a content container created from within a WYSIWYG. Without CSS Breakout it is very messy and usually not even possible. By using CSS Breakout you can finally break out of containers gracefully. This solution relies on only CSS so it's fast and extremely portable.

CSS Breakout works because we have a few (newer) things at our disposal: SASS, calc, vw, media-queries. Combine them together with some logic and you get CSS Breakout.

The old way:

<div class="site-container">
  <div class="skinny-container">
    <!-- your text -->
  </div>
</div>
<img src="wide-image">
<div class="site-container">
  <div class="skinny-container">
    <!-- your text -->
  </div>
</div>

The new way:

<div class="site-container">
  <div class="skinny-container">
    <!-- your text -->
    <img class="breakout--to-max" src="wide-image">
    <!-- your text -->
  </div>
</div>

Live Demo

Move your browser in and out and see how it works.

New York City, Top of the Rock Panoramic .breakout--to-max

Will always "touch" the edge of the browser.

New York City, Top of the Rock Panoramic .breakout--to-site

Will always "touch" the site-width, but no further.

New York City, Top of the Rock Panoramic .breakout--to-skinny

Stays within the skinny-width. Only "touches" the sides on smaller viewports.

Works with Text just as well!

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras eu ornare velit, a porta dui. Pellentesque tincidunt, diam porttitor sodales eleifend, risus turpis porttitor felis, non aliquet sapien diam ullamcorper est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras eu ornare velit, a porta dui. Pellentesque tincidunt, diam porttitor sodales eleifend, risus turpis porttitor felis, non aliquet sapien diam ullamcorper est.

CSS-Breakout Setup

HTML structure

<div class="[site-container, skinny-container]">
  <YOUR_ELEMENT class="breakout--auto"></<YOUR_ELEMENT>
  <YOUR_ELEMENT class="breakout--to-skinny"></<YOUR_ELEMENT>
  <YOUR_ELEMENT class="breakout--to-site"></<YOUR_ELEMENT>
  <YOUR_ELEMENT class="breakout--to-max"></<YOUR_ELEMENT>
</div>

<!-- Can also be nested -->

<div class="site-container">
  <div class="skinny-container">
    [...]
  </div>
</div>

Classes to be used on the breakout items:

  • breakout--to-auto automatically breaks out on thinner viewports regardless of container.
  • breakout--to-skinny Stays within the skinny-width. Only "touches" the sides on smaller viewports.
  • breakout--to-site Will always "touch" the site-width, but no further.
  • breakout--to-max Will always "touch" the edge of the browser.

These are the variables that make CSS Breakout run. I've included my values but you can use whatever values you like.

  • $root-pixels: 18px How we go back and forth between ems, rems and pxs. Pixels only.
  • $site-width: 900px The maximum site width. Can use ems, rems, or px.
  • $site-padding: 0.5em The site's padding. Can use ems, rems, or px.
  • $skinny-width: 700px The inner body width. Can use ems, rems, or px.
  • $skinny-padding: 2em The inner body padding. Can use ems, rems, or px.

How CSS Breakout works

I use two containers on my sites. The primary one is site-container (other libraries call it container but I prefer site-container as container is too broad a term and makes troubleshooting more tedious). site-container is the outer limits to my content. I use skinny-container for blog content because blog content is easier to read on skinnier pages.

There are 3 levels of media-queries for the breakout: within the container and the padding, within the padding of the container, and outside of the container.

If we're within the container, we simply negate the site padding using margin-left: $[site,skinny]-padding * -1. Then we put width: 100vw and voila, it works!

If we're outside of the container, we put the width at 100vw as well. This is where the magic comes in. To get to the center of the container on a center-aligned site, all we have to do is margin-left: 50%. At this point, we have full-width item at exactly the center of the site. Now we have to pull back to the left edge of the page which is exactly -50vw away. So we can use CSS calc to do this automatically: margin-left: calc(50vw -50%).

The hardest part are the "tweener" areas - when the content is wider than the container, but still smaller than the site with padding. Tweener margins are calculated by halving the width of their container and then css calc with -50vw.

Caveats

  • make sure you don't have overflow: hidden on any of the containing elements.
  • if you change your padding using media queries, css-breakout will probably break. You'll have to adjust accordingly.
  • Safari sometimes displays CSS Breakout incorrectly at certain viewports. It seems to be a browser bug but it's not so bad that most people would notice.
  • CSS-breakout only works on center aligned sites.
]]>
eric@ericconstantinides.com (Eric Constantinides)
<![CDATA[Basic Express.js / Node.js Cheatsheet]]> https://www.muddlingthroughcode.com/basic-expressjs-nodejs-cheatsheet https://www.muddlingthroughcode.com/basic-expressjs-nodejs-cheatsheet Thu, 22 Jun 2017 00:00:00 GMT

This is a cheatsheet I created for myself when learning Node / Express. Relatively simple stuff but it helped me out.

  • declare Express
    • const express = require('express')
    • const app = express()
  • import JSON file
    • const myData = require('./myFile.json') // it's that easy!
  • use global template variables
    • in app:
      • app.locals.myVariable = 'hello moto'
      • app.locals.myHtmlVariable = '<p>hello moto</p>'
  • in template:
    • <%= myVariable %>
    • <%- myHtmlVariable %> this way doesn't escape HTML characters
  • Router
    • in app:
      app.get('/monkey/:monkeyName', (req, res) => {
        // .render() looks in 'views' folder; '.ejs' is OPTIONAL:
        res.render('myTemplate', {
            let thisMonkey = req.params.monkeyName
            title: 'Monkey Page',
            className: 'monkey',
            funkyArray: ['harry, 'barry', 'mary']
        })
      })
      
  • variables in template
    • <body class="<%= myTitle %>">
    • <h1><%= myTitle %></h1>
    • <ul><% funkyArray.forEach(funk => %><li><%= funk %></li><% ) %></ul>
  • ejs template includes
    • <% include partials/page/header.ejs %> note the lack of parens, and no dot-slash in front
  • require
    • in parent:
      • const myImportedVar = require('./some_module')
    • in module:
      • type A (using empty module.exports object):
        • exports.anything1 = something1 exports is an alias of module.exports
        • exports.anything2 = something2
      • type B (overwriting module.exports object):
        • anything = whatever_you_want
        • module.exports = whatever_you_want module.exports gets overridden and returned to caller
]]>
eric@ericconstantinides.com (Eric Constantinides)
<![CDATA[Why I'm leaving the LAMP stack and embracing the MERN stack]]> https://www.muddlingthroughcode.com/why-im-leaving-the-lamp-stack-and-embracing-the-mern-stack https://www.muddlingthroughcode.com/why-im-leaving-the-lamp-stack-and-embracing-the-mern-stack Mon, 19 Jun 2017 00:00:00 GMT

"Hi my name is Eric and I build websites."

I've said that to people for years. From the time I started web development I've been a LAMP (Linux, Apache, MySQL, PHP) stack developer. I've built well over 20 enterprise-level Drupal and Wordpress sites in addition to coding hundreds of thousands of lines of custom CSS and UI JavaScript. My entire professional life has been a back and forth between the front-end and the LAMP stack - getting pretty good at both but never mastering either. As the years have gone by I've gravitated towards the front-end but I've always maintained that I'm a true full LAMP stack developer - while never really mastering either the front-end or the back-end.

I _am_ good at "building websites." But companies like SquareSpace and Shopify are automating these skills and making me obsolete. In staying on the LAMP stack I have been holding on to an old and dying format. By teetering in the middle I was spearheading my own demise. To evolve I had to update my skills. I had to ditch what wasn't working and master what I really loved.

Today I'm officially ditching the LAMP stack and finding something new. This is the start of my journey into being a web application developer. I'm tackling this from the point of view of an expert and a complete novice. This is humbling and embarrassing and completely necessary for me.

"Hi my name is Eric and I build web apps."

My journey began 6 months ago when literally all I knew was that I needed to learn a front-end framework in order to update content on a Drupal site better. That led me to a standoff between either React or Angular (Vue wasn't much of a thing yet). After crunching some numbers, I found the general consensus was that React has more top-level tech companies using it. It was settled, I was learning React.

In order to learn React you need to know ES6/ES2015 and JSX. Uh oh. So the new first thing I had to do was to learn ES2015. Then I quickly moved on to learning React along with Webpack and Babel. I was quickly overwhelmed. I didn't even know what a router was. I didn't understand what an MVC was. I was trying to grock React before really grocking the stack. So I backed up. Way back. I had to understand the stack.

My new stack.

I have slowly fallen in love with JavaScript and after learning ES2015 I have been pushing myself to become an expert in it; I knew my stack would have to be full-time JS. So I chose Node.js for the backend.

And, the web framework that you use for Node is Express.js.

Then the database. Since I'm starting anew, I want to get away from rigid SQL databases and go with the most JavaScripty looking NoSQL option available: MongoDB. I'm going to love throwing JSON objects at it. After doing some cursory research on it, I'm absolutely loving it compared to relational databases. Bye-bye MySQL, don't let the tables hit you on the way out.

The MERN stack.

I decided my first site would be to convert ericconstantinides.com from static HTML / Apache / JS to a Node / Express / JS site. I didn't want to involve any React or anything too intense just yet. I just wanted to get used to having a simple site up and running with my new stack. I converted most of the data to JSON and was able to get it working in a few days. That wasn't so bad!

I also decided that all of my personal websites will now be up and running on my GitHub account. I want people to know who I am and what I'm about. No more playing in the dark.

Where do I host? I use Digital Ocean for all my Drupal sites, but I wanted something specific for my new stack. I looked into AWS but it is too complex (for now) to get up and running right away. For the time being I decided on Heroku. They have a nice freemium model that is easy to get up and going (I ended up paying $7/month so that the site would have instant spin-up (good job, Heroku)).

My next project is a simple Node To Do app. I already had a front-end only To Do app but I wanted this one to be on a Node server, work with Mongo, and have a full RESTful API. There are a ton of tutorials that tell you how to do a RESTful API but it ended up being a lot more work than I had intended. In the end though, I'm very happy with it.

I'm putting this site in Node. This will be my honarary post. I'm making it dead simple and putting all the blog posts in markdown files. I found an NPM package marked which enables me to load in all of my posts.

Next up, React. Oh but first, Webpack.

For the first time in a long time I'm excited again about code. It's been a long time.

]]>
eric@ericconstantinides.com (Eric Constantinides)