Summary of front-end technology stack of plaything circle (react + Redux)

Time:2022-5-6

Code template of this document:react-redux-webpack-boilerplate

A good memory is not as good as a bad pen. I have written several summaries about the technology stack used in the front end of the toy circle before. Now I’m here Plaything circle PC version Before going online, use the front end of the toy circle to the technology stack for a brief summary.

Front end basic frame diagram

Summary of front-end technology stack of plaything circle (react + Redux)

1、webpack

Webpack is a module loader and packaging tool. For details, please refer toOfficial documentsVery detailed

Main roles in the project:

  • Module management: modular management of JS, CSS, image and other files

  • Generate HTML according to template: the HTML webpack plugin is mainly used to generate HTML files according to the template and inject the specified chunks

  • Static resource management, MD5, path relocation

Production configuration

var webpack = require('webpack');
var path = require('path');
var entry = require('./entry.js');
var templateConfig = require('./html.template.config.js').pro;
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('vendor', 'static/js/vendor.[hash:8].js');

var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var config = {
  entry: entry,
  output: {
    path: __dirname + '/product',
    publicPath: 'http://cdn.xx.com/', 
    filename: 'static/js/[name].[chunkhash:8].js'
  },
  resolve: {
    Extensions: ['', '. JS','. JSX '], // configure the suffix name that can not be written
    root: path. Join (_dirname, 'public /') // configure the absolute path, which will be used in alias and entry
  },
  module: {
    loaders: [
      {
        test: /\.js[x]?$/,
        include: path.resolve(__dirname, 'public'),
        exclude: /node_modules/,
        loader: 'babel-loader'
      }, {
        test: /\.(jpg|png|gif)$/,
        loader: 'url? limit=1024&name=static/images/[hash]. [ext] '// images less than 1KB are converted to Base64. Other image addresses in CSS will be realized as packaged addresses. Publicpath is used here
      },
      {test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap')}
    ]
  },
  plugins: [
    commonsPlugin,
    new ExtractTextPlugin('static/css/[name].[chunkhash:8].css'),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"'
    }),
    commonsPlugin
  ]
};

for (var i = 0; i < templateConfig.length; i++) {
  config.plugins.push(new HtmlWebpackPlugin(templateConfig[i]));
}

module.exports = config;

Reference documents:

2、Babel

BabelIs a widely used transcoder, which can convert ES6 code to Es5 code and JSX syntax code to Es5 code.
Babel is mainly used in the project to transcode the source code ES6 and JSX to Es5.

3、React

React provides the view layer of the application, which is represented as a component. For details, please refer toOfficial documents

Main knowledge points:

  • JSX (optional)

  • Components (props, state, lifecycle, event, form, several APIs)

  • Virtual Dom

reference resources:

4. Redux (one-way data flow)

Redux is a JavaScript state container that provides predictable state management. It has nothing to do with react.

In addition to being used with react, Redux also supports other interface libraries.

4.1 basic ideas

Can refer toRedux: a more elegant implementation of flux

  • Action (normal action, asynchronous action)

    • Ordinary actions are JS ordinary objects in essence

    • Asynchronous action, using thunk middleware asynchronous action

  • Reducer

    • ( previousState, action ) => newState

    • Processing data logic

    • Split and merge reducer (it is very convenient to use the import and export syntax of ES6)

  • Store

    • Contact the object of action and reducer to provide state for the application

4.2 Middleware

Similar to middleware in express or koa framework. It provides an extension after the action is initiated and before it reaches the reducer.
The design of middleware uses a lot of functional programming ideas, including high-order functions, composite functions, coritization and ES6 syntax. The source code is only about 20 lines.
The project mainly uses three middleware to solve different problems.

  • Thunkmiddleware: handling asynchronous actions

  • Apimiddleware: handles API requests uniformly. Generally, each API request requires at least three different actions of dispatch (pre request, successful request and failed request), which can be handled easily through this middleware.

  • Loggermiddleware: debug the development environment and output the application state log from the console

reference resources:

5、react-redux

The function of react Redux is to connect the store and container components. Store is provided by Redux, and container component is provided by react.

5.1 organizational application components

  • Components for organizing applications

Container component: the component at the top of the application, which is used to connect with redux. Get data from Redux as props.
Presentation component: it is located in the middle or sub component of the application. It is a pure component and has nothing to do with redux. They get data from their parent component as props, and their common root component is the only container component of the application. The presentation component can maintain a small amount of its own state information.

5.2 connecting store and components

React Redux only provides two key modules: provider and connect.

Source code:

import Provider from './components/Provider'
import connect from './components/connect'

export { Provider, connect }
  • Provider: it is a component that accepts a store attribute and a sub component (that is, as mentioned above: store is provided by Redux and container component is provided by react)

example:

ReactDOM.render(
    <Provider store={store}>
      {/* note "routerState" here: important to pass it down */}
      <Handler routerState={routerState} />
    </Provider>,
    document.getElementById('root')
  );
  • Connect ([mapstatetoprops], [mapdispatchtoprops], [mergeprops], [options]): connect returns a function that accepts the constructor of a react component as the connection object and finally returns the connected component constructor.

example:

import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps, actionCreators)(MyRootComponent)

reference resources:

6、ES6

At present, the mainstream framework (angular2, react, KOA, Redux) has fully shifted to ES6. Some star features of ES6 are used in the project. At first I refused and was not used to it. Now I feel that it is very convenient and cool.

6.1 class and module

Modularization: components are written and used according to modules, action and reducer are split and merged according to modules, and third-party modules are used in the project. The module feature of ES6 is used in writing react components, in which the class feature of ES6 is used.

example:

import {Types} from '../constants/base/order';

export * from './base/user';
export {fetchCart} from './base/shopCart';
export {fetchOrder} from './base/order';

export function fetchPayResult(id) {
  return {
    url: '/mall/order/payResult/' + id,
    method: 'GET',
    types: ['REQUEST', Types.FETCH_PAY_RESULT, 'FAILURE']
  };
}

export function changePayType(payType) {
  return {
    type: Types.SELECT_PAY_TYPE, payType
  };
}
export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  tick() {
    this.setState({count: this.state.count + 1});
  }
  render() {
    return (
      <div onClick={this.tick.bind(this)}>
        Clicks: {this.state.count}
      </div>
    );
  }
}
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };

6.2 variable structure assignment

var {
      types,
      url = '',
      mockUrl = '',
      method = 'GET',
      dataType = 'json',
      data = {}
      } = action;

6.3 function extension: arrow function, default value of function parameter

  • Arrow function: arrow functions are also used more in projects, simplifying the preparation of functions and the preparation of react stateless function components.

const noop = ()=> false;

let createItem = (item, index) =><Order order={item} key={index}/>;

const Coupon = (props) => (
    <li>
      < div classname = "coupon tit" > voucher < / div >
      <div className="coupon-price"><span>¥</span><strong>{props.coupon.price}</strong></div>
      <div className="coupon-info">
        <p>{props.coupon.code}</p>

        Available before < p classname = "time" > {props. Coupling. Endtime}</p>
      </div>
    </li>
);
  • Default value of function parameters: a typical application is to write reducer.

export function address(state = {}, action) {
  switch (action.type) {
    case Types.SELECT_ADDRESS:
      return objectAssign({}, action.payload);
...

6.4 string extension: template string

href={`/pc/mall/order/confirm.html?${param}`}
return {
    mockUrl: '/static/mock/user.address.save.json',
    url: `/user/address/${id}`,
    method: 'PUT',
    data: {id, isDefault},
    types: ['REQUEST', Types.SET_DEFAULT_ADDRESS, 'FAILURE']
  };

6.5 object extension: concise representation of attributes

export const setVisibilityFilter = (filter) => {
  return {
    type: 'SET_VISIBILITY_FILTER',
    filter
  }
}
return {
    mockUrl: '/static/mock/user.address.save.json',
    url: `/user/address/${id}`,
    method: 'PUT',
    data: {id, isDefault},
    types: ['REQUEST', Types.SET_DEFAULT_ADDRESS, 'FAILURE']
  };
App.defaultProps = {
  user: {},
  tips: {visible: false},
  carts: [],
  visibleDropCart: false,
  visibleLoginDialog: false,
  switchLoginDialog() {
  },
  switchTips() {
  },
  switchDropCart() {
  }
};

6.6 let and Const

const noop = ()=> false;

let createItem = (item, index) =><Order order={item} key={index}/>;

reference resources:

7、Gulp

Gulp, like grunt, is also an automatic task runner. It fully draws lessons from the pipe idea of UNIX operating system. Many people believe that it is simpler than grunt in operation.

The main functions used in the project: using in combination with webpack, compressing JS, eslint code checking and compressing CSS.

var gulp = require("gulp");
var gutil = require("gulp-util");
var minifyCss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var eslint = require('gulp-eslint');
var reporter = require('eslint-html-reporter');
var fs = require('fs');
var path = require('path');

var webpack = require("webpack");

var webpackConfigProduct = require("./webpack.production.config.js");
var webpackConfigDevelop = require("./webpack.development.config.js");

gulp.task("webpack", function(callback) {
  webpack(webpackConfigProduct, function(err, stats) {
    if (err) throw new gutil.PluginError("webpack", err);
    callback();
  });
});

gulp.task("webpackDevelop", function(callback) {
  webpack(webpackConfigDevelop, function(err, stats) {
    if (err) throw new gutil.PluginError("webpack", err);
    callback();
  });
});

var srcJsDir = './public/static/js/';

gulp.task('lint', function() {
  return gulp.src([srcJsDir + '**/*.js'])
      .pipe(eslint())
      .pipe(eslint.format(reporter, function(results) {
            fs.writeFileSync(path.join(__dirname, 'lint-report.html'), results);
          })
      );
});

gulp.task("minifyJs", ['webpack'], function() {
  return gulp.src("./product/**/*.js")
      .pipe(uglify({
        output: {
          max_line_len: 100
        }
      }))
      .pipe(gulp.dest("./product"));
});

gulp.task("minifycssPro", ['webpack'], function() {
  return gulp.src("./product/**/*.css")
      .pipe(minifyCss())
      .pipe(gulp.dest("./product"));
});

gulp.task("minifycssDev", ['webpackDevelop'], function() {
  return gulp.src("./development/**/*.css")
      .pipe(minifyCss())
      .pipe(gulp.dest("./development"));
});

gulp.task('copyJson', function() {
  return gulp.src('./public/static/mock/**/*.json')
      .pipe(gulp.dest('./development/static/mock/'));
});

gulp.task('product', ['minifycssPro', 'minifyJs']);

gulp.task('default', ['minifycssDev', 'copyJson']);

reference resources: