Front End Developer
@MeKimak
React
Chips & Tricks
React Ecosystem
fetch
Webpack
dev: npm start
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var config = require('./webpack.config.dev');
var app = express();
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
app.get('*/*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(8080, 'localhost', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://localhost:8080');
});
"start": "node devServer.js"
Webpack hot reload
NODE_ENV=production
warning(
'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
'This means that you are running a slower development build of Redux. ' +
'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
'to ensure you have the correct code for your production build.'
)
"build": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
prod: npm build
web_modules/
- Structure "à plat"
- Facilité de nommage
- "Easy refactoring"
css loader for webpack
//webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
plugins: [
new ExtractTextPlugin("styles.css")
],
//...
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(
"style-loader",
"css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
),
include: path.join(__dirname, 'web_modules')
}
]
},
};
localIndentName
"css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]"
//web_modules/Input/index.js
import styles from "./index.css";
export default class Input extends Component {
render() {
return (
<input type="text" className={styles.input}></input>
)
}
}
//web_modules/Input/index.css
.input{
margin: 10px;
}
//Browser DOM
<input type="text" class="index__input___2ohV8"></input>
Bye bye... INLINE STYLE !
Hello Css Loader.
Cool !
Et on peux importer du
?
Euh... oui mais on va faire mieux !
Postprocessor > PreProcessor
PostCss
PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more."
Plugin Autoprefixer
:fullscreen a {
display: flex
}
:-webkit-full-screen a {
display: -webkit-box;
display: -webkit-flex;
display: flex
}
:-moz-full-screen a {
display: flex
}
:-ms-fullscreen a {
display: -ms-flexbox;
display: flex
}
:fullscreen a {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex
}
compiles to:
Plugin Custom Properties
:root {
--color: red;
}
div {
color: var(--color);
}
div {
color: red;
}
compiles to:
Plugin Custom Media
@custom-media --small-viewport (max-width: 30em);
@media (--small-viewport) {
/* styles for small viewport */
}
@media (max-width: 30em) {
/* styles for small viewport */
}
compiles to:
Plugin Calc
:root {
--main-font-size: 16px;
}
body {
font-size: var(--main-font-size);
}
h1 {
font-size: calc(var(--main-font-size) * 2);
height: calc(100px - 2em);
}
body {
font-size: 16px
}
h1 {
font-size: 32px;
height: calc(100px - 2em)
}
compiles to:
Webpack config PostCss
//webpack.config.js
module.exports = {
postcss: [
require("autoprefixer"),
require("postcss-custom-properties"),
require("postcss-custom-media"),
require("postcss-calc")
],
};
"css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader"
Des variables globales ?
//webpack.config.js
var webpackPostcssTools = require("webpack-postcss-tools");
var globalMap = webpackPostcssTools.makeVarMap("web_modules/app/css/global.css");
module.exports = {
postcss: [
require("autoprefixer"),
require("postcss-custom-properties")({
require("postcss-custom-media"),
variables: globalMap.vars
}),
require("postcss-custom-media")({
extensions: globalMap.media
}),
],
};
package.json
"babel": {
"presets": [
"react",
"es2015"
//"stage-0"
],
"plugins": [
"transform-decorators-legacy",
"transform-object-rest-spread",
"transform-class-properties",
"transform-export-extensions",
"syntax-trailing-function-commas"
],
"env": {
"development": {
"presets": [
"react-hmre"
]
}
}
}
.babelrc
Decorators
// npm install babel-plugin-transform-decorators-legacy --save-dev
// "plugins": ["transform-decorators-legacy"]
@connect(
(state) => ({
artists : state.artists
}),
(dispatch) => ({
getArtists : (value) => dispatch(getArtists(value)),
})
)
export default class Artists extends Component {
Object Rest/Spread
// npm install babel-plugin-transform-object-rest-spread --save-dev
// "plugins": ["syntax-object-rest-spread"]
let a = {v:1, w:2};
let b = {x:3, y:4, z:5}
console.log({...a, ...b}) // {"v":1,"w":2,"x":3,"y":4,"z":5}
Class Properties
// npm install babel-plugin-transform-class-properties --save-dev
// "plugins": ["transform-class-properties"]
//Without plugin
class ReactCounter extends React.Component {
constructor(props) { // boilerplate
super(props); // boilerplate
this.state = {
count: 0
};
}
}
//With plugin
class ReactCounter extends React.Component {
state = {
count: 0
};
}
Export extensions
// npm install babel-plugin-transform-export-extensions --save-dev
// "plugins": ["transform-export-extensions"]
import React, {PropTypes, Component} from "react"
import v, {x, y as w} from "module"
Syntax trailing function commas
// npm install babel-plugin-syntax-trailing-function-commas --save-dev
// "plugins": ["syntax-trailing-function-commas"]
1: function clownPuppiesEverywhere(
2: param1, // updated to add a comma
3: param2 // updated to add new parameter
5: ) { /* ... */ }
1: function clownPuppiesEverywhere(
2: param1,
3: param2, // Next parameter that's added only has to add a new line, not modify this line
5: ) { /* ... */ }
fetch
Une requête AJAX hier
(Asynchronous JavaScript and XML)
Une requête AJAX aujourd'hui
https://fetch.spec.whatwg.org/
Can i use ?
fetch polyfill
//webpack.config.js
//$ npm install exports-loader --save-dev
module.exports = {
plugins: [
new webpack.ProvidePlugin({
fetch: "exports?self.fetch!whatwg-fetch"
})
],
};
Limitation de fetch ? Abort.
Utilisez superagent si besoin...
(superagent-bluebird-promise)
react-router
Params & optional
Multiple component
Architecture
STORE: "Single source of truth"
Reducer
counter(state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
<- ACTION
<- STATE
Sub-Reducer
Sub-Reducer
import { combineReducers } from "redux"
import settings from "./settings"
import geoblocking from "./geoblocking"
import feedback from "./feedback"
import storage from "./storage"
export default combineReducers ({
settings,
geoblocking,
feedback,
storage
});
npm deep-freeze
npm deep-freeze
"Beginner advice"
connect logique
"Beginner advice"
presentation component !=connected component
"Beginner advice"
connect performance
The end.
React Chips & Tricks
By Mickael Dumand
React Chips & Tricks
- 4,413