Frontend: welcome to the future
Frontend future is already here. You just need to give it a chance.
Today I’m gonna show you how to bring future to your frontend development process. Some of that features were introduced just recently. So… no more missed cool features.
TLDR: repo, webpack, loaders, babel, postcss, css-modules, cssnext, autoprefixer, react, fetch, async/await, eslint, editorconfig.
webpack
Let’s start with webpack. Webpack is a module bundler. Remember requirejs and browserify? Just like them, but it could do a lot more. Browserify is about creating one huge file with a lot of modules inside. Webpack could bundle to 1 file too, but it could create a lot of small chunks for a real modular structure of your project. Webpack supports different loaders, so it could replace Grunt and Gulp as well.
npm i -D webpack
Webpack is a foundation of our setup. You could learn more about webpack and it’s configuration here.
babel
With babel you could use ES6 and ES7 syntax today. New syntax will be transpiled to ES5, so every modern browser will work with your code like it was written in ES5.
Install babel-loader:
npm i -D babel-loader
And add it to .js loaders:
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
]
}
ES7 syntax is disabled by default. To use some features like async/await and others you should install babel-runtime:
npm i -D babel-runtime
And add some params to babel-loader:
{ test: /\.js$/, loader: 'babel-loader?optional[]=runtime&stage=0', exclude: /node_modules/ }
Ok, now your js code is fine. You could write something like this:
const subjects = {
webpack: 'Module bundler',
babel: 'ES6/ES7 transpiler',
cssmodules: 'Css-classes isolation',
cssnext: 'Css-next transpiler'
};const descriptions = Object.keys(subjects).map(descr => `Our subject: ${descr}`);
css-modules
Your js is modular now. But css isn’t. Let’s fix it.
About a month ago one PostCSS plugin changed everything about css modules. local-scope (now deprecated) allowed us to use classes like .input without worrying about class conflicts. How? PostCSS converts real class names to something like _2kmzgPpC38oFMSmYndku2L if class wasn’t marked as :global. By default everything is local.
Webpack authors took that idea and implemented this inside of css-loader plugin.
UPD: I’m a little bit wrong about css-modules history:
Let’s install css-loader (and extract-text to export css file and not js):
npm i -D css-loader extract-text-webpack-plugin
Require Extract-text plugin:
ExtractTextPlugin = require('extract-text-webpack-plugin');
And add css loader with option module
{ test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader?module') }
And now your css is modular. But…
cssnext
… but you couldn’t use a lot of future-css cool features. Something like variables, hexa #rrggbbaa support and some other features.
PostCSS to the rescue again! Plugin called cssnext allows us to write future-css today. You don’t need to wait browser vendors anymore.
Install cssnext-loader:
npm i -D cssnext-loader
And add it to your css loaders list:
{ test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader?module!cssnext-loader') }
If you’re using Extract-text plugin, don’t forget to add it to webpack plugins section:
plugins: [
new ExtractTextPlugin('bundle.css')
]
A neat thing: autoprefixer is bundled with cssnext. No need to install it separately.
css example
Let’s create our module.css:
.blockFlex {
display: flex;
align-items: center;
justify-content: center;
}.text {
font-size: 2rem;
line-height: 1.5;
color: #000000cc;
}
And use .text class inside of React template:
import React, { Component } from 'react';import styles from './components/TextBlockExample/styles.css';class TextBlockExample extends Component {
constructor (props) {
super(props);
} render () {
return (
<div className={styles.blockFlex}>
<span className={styles.text}>text block example</span>
</div>
);
}
}React.render(<TextBlockExample/>, document.getElementById('content'));
Open html page and you’ll see something like:
<div class="_1CHkmbJYscABE2Nv8V2ieV" data-reactid=".0">
<span class="_3GEYl1yDLGsXGTnW9vVo21" data-reactid=".0.0">text block example</span>
</div>
And your css file will look like this:
._1CHkmbJYscABE2Nv8V2ieV {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; -webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center; -webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}._3GEYl1yDLGsXGTnW9vVo21 {
font-size: 32px;
font-size: 2rem;
line-height: 1.5;
color: #000000;
color: rgba(0, 0, 0, 0.8);
}
Ok, now your js and css are great. Could we do it even better? Sure.
fetch
Fetch is the new XmlHTTPRequest. It supports promises and could be combined with async/await.
Fetch isn’t supported by all modern browsers. But Github wrote a polyfill that you could use today. IE10 requires Promise polyfill, let’s install it too.
npm i -S es6-promise whatwg-fetch
You couldn’t import it from a modules as named objects, so just import it once and forget about importing process:
import 'es6-promise';
import 'whatwg-fetch';
And extend our previous react-component:
…
componentDidMount () {
this.getData();
} async getData () {
const rawData = await fetch('http://headers.jsontest.com/');
const data = await rawData.json(); console.log('data', data);
}
…
If you need to send user cookies to a server don’t forget to setup credentials settings:
fetch(`/api/site/${siteId}/`, {
credentials: 'include'
});
Enough with js and css features. Let’s talk about some tools.
sublime and eslint
I’m using Sublime Text 3. It’s blazingly fast and just awesome.
Linting code right inside of code editor is cool. You see all of your mistakes right here and right now without context switching.
ESLint is a modular linter with a lot of plugins. And it supports ES6 (and ES7 with babel-parser).
Follow Dan’s article and you’ll get awesome code linter 😊
And here is my .eslintrc config.
.editorconfig
It’s really important to write code consistently. Add your config to a repo and every code editor with .editorconfig support will use your style settings.
Summary
I hope that you got something new. Just a recap:
- We made our js modular with webpack and modern with babel
- We made our css modular with css-modules and modern with cssnext and autoprefixer
- React helped us to show some concepts really quick and easy
- Our code became more async with fetch polyfill and async/await
- Linting code became easy with Sublime and ESLint
- With .editorconfig our team now using same code-style settings
And here is github repo:
Happy coding!
UPD (07.07.2016): repo updated to use latest modules versions