webpack

Webpack is the asset pipeline like tool that transforms and packages our js in development mode and production.

We are going to be seeing a default configuration that includes an express app. (since you would never write a react app on it's own without some kind of backend)

We'll walk through all of the features provided to you by this setup.

config files

This environment is being controlled at several different levels, from several different libraries.

package.json

Lists all of the npm commands

src/server/index.js

Is the normal express main js file. This is also where you run your webpack development server from.

Any server application code you write goes in the server directory.

webpack config

Is separated into common, production and development environments.

Babel & React

  • babel-core: Transforms your ES6 code into ES5
  • babel-loader: Webpack helper to transform your JavaScript dependencies (for example, when you import your components into other components) with Babel
  • babel-preset-react: Babel preset for all React plugins, for example turning JSX into functions
rules: [
  {
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    use: {
      loader: "babel-loader"
    }
  }

Webpack uses a library module to do each type of code transform. Each rule runs a loader according to the test. See here for a definitive list.

This rule is telling webpack to run babel.

.babelrc

Create a file that tells babel how to transpile the code it is given.

html-webpack-plugin

this plugin creates an index.html file that has all the correct script and link tags for us, and puts it in the static directory of the express app.

If you look inside the src/client/index.html you see what it looks like before it's transformed by webpack. Find the final version in build/client/index.html

webpack-dev-server

We can run the build and refresh the browser for each code change we make, or we can use the nodemon equivalent, webpack-dev-server.

We build upon webpack-dev-server to also include react-hot-loader for the complete react development environment.

Not only does the library know about any changes, but it will update your code on the fly- it doesn't require a refresh, and you don't lose the state of your app!

Note that certain kinds of changes or situations require you to refresh anyways. If your code is behaving strangely, try a refresh first.

webpack-dev-server express

nodemon is enabled for the server. webpack-dev-server will stop working, though, and you will have to reload the page.

sass in react

We can use sass in react, with some added features that aren't in rails.

We can isolate the css for each component so that we don't have to worry about over-writing styles for the button class.

Also, it allows us to write CSS any apply it using react-hot-loader, without refreshing the browser, or losing application state. -This is especially helpful for error states.

The sass / react CSS compiler will automatically prefix the styles for us.

See the settings for that here.

This means we need to change 3 things about the way we write CSS.

  1. styles for any component go in the directory for that component.
  2. we have to import and then use styles as a js object.
  3. naming anything has to change from hyphens to camel case, so that we can access it as js keys:
    import styles from './style.scss';
    
    return <p className={styles.titleName}>cheese and rice</p>;
    

react dev tools chrome extension

Find it here.

building for production

Create all the static files in build:

npm run build

Start the express server

npm run start

linting

Webpack allows us to setup a default environment that will also tell us if our code conforms to a styleguide.

propTypes

This is another safeguard to make sure that we don't put in any unexpected data types into our components. It's another workaround to the javascript falsy/truthy feature (== vs. ===)

Note that propTypes is NOT form validation. This is more about surfacing subtle == vs. === errors to you, the programmer, than it is about user messaging, i.e., your password length is too short.

Using propTypes

import PropTypes from 'prop-types';
class Monkey extends React.Component {
.
.
.
}
Monkey.propTypes ={
  message: PropTypes.string.isRequired
};

export default Monkey;

See a more complete list of types here: https://www.fullstackreact.com/p/appendix-a-proptypes/

destructuring

You should use this syntax for adding things into a state array or object.

destructuring arrays:

Since react forces us to replace state with a new state value every time, we can use destructuring ES6 syntax:

let banana = 'yellow';
const fruits = ['kiwi', 'apple'];
const newFruits = [banana, ...fruits];
console.log( fruits, newFruits );

destructuring objects

How do we add to the state object this.state.monkey?

constructor(){
  this.state = {
    monkey: {
      hair: "brown"
    }

  }
}

Key same name as variable:

let food = 'banana';
this.setState({monkey: {food, ...this.state.monkey}});

Named key:

let banana = 'ripe banana';
this.setState({monkey: {food: banana, ...this.state.monkey}});

Key name variable:

const keyName = 'food';
let stuff = 'banana';
this.setState({monkey: {[keyName]: stuff, ...this.state.monkey}});

See some more ES6 destructuring techniques here.

More Resources:

Do you want asset pipeline-like controls over asset urls? Check out the webpack file-loader

Webpack sass: https://github.com/webpack-contrib/sass-loader

Simplified starting app template:

A less opinionated express / webpack / react starting app: https://github.com/wdi-sg/react-express

Exercise: ES6 destructuring

Run these code snippets:

Variables from returned array

function f() {
  return [1, 2];
}

var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2

Spread operators

var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

Object spread operators

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10
b; // 20
rest; // { c: 30, d: 40 }

Variable assignment from keys

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

Variable key access to objects

let key = 'z';
let {[key]: foo} = {z: 'bar'};

console.log(foo); // "bar"

See also: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Also: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

results matching ""

    No results matching ""