├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── README.md
├── package.json
├── src
├── __test__
│ ├── actions.specs.js
│ └── reducer.specs.js
├── actionTypes.js
├── actions.js
├── helpers.js
├── index.js
├── reducer.js
└── simpleReduxForm.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "es2015", "stage-0"],
3 | "env": {
4 | "test" : {
5 | "plugins": [
6 | ["transform-class-properties"],
7 | ],
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 |
5 | insert_final_newline = true
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | webpack.config.js
2 | dist/*
3 | static/*
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint-config-airbnb",
3 | "parser": "babel-eslint",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | },
8 | "rules": {
9 | "react/no-multi-comp": 0,
10 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
11 | "import/default": 0,
12 | "import/no-duplicates": 0,
13 | "import/named": 0,
14 | "import/namespace": 0,
15 | "import/no-unresolved": 0,
16 | "comma-dangle": 0,
17 | "import/no-named-as-default": 2,
18 | "indent": [2, 2, {"SwitchCase": 1}],
19 | "no-console": 0,
20 | "no-underscore-dangle": ["error", { "allowAfterThis": true }],
21 | "no-alert": 0,
22 | "eqeqeq" : 1
23 | },
24 | "plugins": [
25 | "react"
26 | ],
27 | "settings": {
28 | "import/resolve": {
29 | moduleDirectory: ["node_modules", "src"]
30 | }
31 | },
32 | "globals": {
33 | "__DEVELOPMENT__": true,
34 | "__DEBUG__": true,
35 | "__SERVER__": true,
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
3 | dist/
4 | lib/
5 | coverage/
6 | *.iml
7 | *.log
8 | *.logs
9 | .DS_Store
10 | npm-debug.log
11 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | scripts
2 | docs
3 | .babelrc
4 | .eslint*
5 | .idea
6 | .editorconfig
7 | .npmignore
8 | .travis.yml
9 | webpack.*
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Simplest Redux Form
2 |
3 | > Higher order component for React Redux forms (inspired by [redux-form](https://github.com/erikras/redux-form))
4 |
5 | ## Note
6 |
7 | Idea of this library is 100% inspired from [redux-form](https://github.com/erikras/redux-form) (v5).
8 |
9 | This library is subset of [redux-form](https://github.com/erikras/redux-form) for small / few forms.
10 | If your application is form heavey with large / complex form please use [redux-form](https://github.com/erikras/redux-form).
11 |
12 | I have implemented this libray for following reasons :-
13 |
14 | * [redux-form](https://github.com/erikras/redux-form) is great way of managing forms within application with react and redux.
15 | * For small forms using large library will add up unnecessary bundle size increase, this library focus on simple and small version of `redux-from`
16 | * Scope of this library will be very minimal, if you want full fledge library please use `redux-form`.
17 |
18 | ## Installation
19 |
20 | ```
21 | $ npm install --save simple-redux-form
22 | ```
23 |
24 | ## Usage
25 |
26 | ### Step #1
27 |
28 | The first thing, you have to mount `simple-redux-form` reducer to your redux reducers.
29 | Configure this inside your rootReducers.
30 |
31 | ```js
32 | import {reducer as simpleFormReducer} from 'simple-redux-form';
33 | const reducers = {
34 | // your other reducers
35 | form: simpleFormReducer
36 | }
37 | ```
38 |
39 | ### Step #2
40 |
41 | You need to decorate your component with simpleReduxForm.
42 |
43 | ```js
44 | import simpleReduxForm from 'simple-redux-form'
45 | const fields = ['firstName', 'lastName'];
46 | function validate(values) {
47 | const errors = {};
48 | if (!values.firstName) {
49 | errors.firstName = 'Required';
50 | }
51 | if (!values.lastName) {
52 | errors.lastName = 'Required';
53 | }
54 | return errors;
55 | }
56 |
57 | const MyNewForm = ({ fields: {firstName, lastName } }) => (
58 |
62 | )
63 |
64 | export default simpleReduxForm(MyForm, {
65 | form: 'test'
66 | fields,
67 | validate,
68 | });
69 |
70 | ```
71 |
72 | Each field in the fields prop contains the `value` a `onChange`, `error` , `touched` as sugger props to each field.
73 |
74 | You can also pass fields as props.
75 |
76 | For custom Input components this library expose , `setValue` function with each field for setting vlaues manually.
77 |
78 |
79 | ### Todo
80 |
81 | * [ ] Docs
82 | * [ ] Examples
83 |
84 | ## License
85 |
86 | MIT
87 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simple-redux-form",
3 | "version": "0.0.5",
4 | "description": "This is simplest redux form",
5 | "main": "./lib/index.js",
6 | "scripts": {
7 | "build": "npm run build:lib && npm run build:npm && npm run build:min",
8 | "build:lib": "babel src --out-dir lib",
9 | "build:npm": "NODE_ENV=development webpack src/index.js dist/simple-redux-form.js",
10 | "build:min": "NODE_ENV=production webpack src/index.js dist/simple-redux-form.min.js",
11 | "test": "mocha --compilers js:babel-register --recursive 'src/__test__/*'",
12 | "test:coverage": "npm run build:lib && istanbul cover _mocha -- recursive 'lib/__test__/*'",
13 | "test:lint": "eslint src",
14 | "show:coverage": "open coverage/lcov-report/index.html",
15 | "clean": "rimraf lib coverage dist"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/mihirsoni/simple-redux-form.git"
20 | },
21 | "keywords": [
22 | "react",
23 | "reactjs",
24 | "flux",
25 | "redux",
26 | "react-redux",
27 | "tiny-redux-form",
28 | "simple-redux-form",
29 | "small-redux-form",
30 | "redux-form",
31 | "redux-form-validations",
32 | "forms",
33 | "decorator"
34 | ],
35 | "bugs": {
36 | "url": "https://github.com/mihirsoni/simple-redux-form/issues"
37 | },
38 | "npmName": "simple-redux-form",
39 | "dependencies": {
40 | "deep-equal": "^1.0.1",
41 | "react": "^15.3.0",
42 | "react-redux": "^4.4.5",
43 | "redux": "^3.5.2"
44 | },
45 | "devDependencies": {
46 | "babel": "^6.5.2",
47 | "babel-cli": "^6.11.4",
48 | "babel-core": "^6.13.2",
49 | "babel-eslint": "^6.1.2",
50 | "babel-loader": "^6.2.4",
51 | "babel-preset-es2015": "^6.13.2",
52 | "babel-preset-react": "^6.11.1",
53 | "babel-preset-stage-0": "^6.5.0",
54 | "babel-register": "^6.11.6",
55 | "deep-freeze": "0.0.1",
56 | "eslint": "^3.2.2",
57 | "eslint-config-airbnb": "^10.0.0",
58 | "eslint-plugin-import": "^1.12.0",
59 | "eslint-plugin-jsx-a11y": "^2.0.1",
60 | "eslint-plugin-react": "^6.0.0",
61 | "expect": "^1.20.2",
62 | "istanbul": "^0.4.4",
63 | "mocha": "^3.0.1",
64 | "rimraf": "^2.5.4",
65 | "webpack": "^1.13.1"
66 | },
67 | "author": "Mihir Soni (http://mihir.pro)",
68 | "license": "MIT"
69 | }
70 |
--------------------------------------------------------------------------------
/src/__test__/actions.specs.js:
--------------------------------------------------------------------------------
1 | /* global define, it, describe */
2 | /* eslint-disable import/no-extraneous-dependencies */
3 | import expect from 'expect';
4 | import { INITIALIZE, DESTROY, SET_FIELD, TOUCH_ALL } from '../actionTypes.js';
5 | import { initialize, setField, touchAll, destroy } from '../actions.js';
6 |
7 | describe('actions', () => {
8 | it('should create an action to initialize all form fields with an initial value', () => {
9 | const actionType = initialize(
10 | { field1: 'foo', field2: 'bar', field3: 'baz' },
11 | 'mockedForm',
12 | ['field1', 'field2', 'field3']);
13 | const action = {
14 | type: INITIALIZE,
15 | initialValue: { field1: 'foo', field2: 'bar', field3: 'baz' },
16 | form: 'mockedForm',
17 | fields: ['field1', 'field2', 'field3']
18 | };
19 | expect(actionType).toEqual(action);
20 | });
21 | it('should create action for setting a value to the form field', () => {
22 | const actionType = setField('mockedField', 'mockedValue', 'mockedForm');
23 | const action = {
24 | type: SET_FIELD,
25 | field: 'mockedField',
26 | value: 'mockedValue',
27 | form: 'mockedForm'
28 | };
29 | expect(actionType).toEqual(action);
30 | });
31 | it('should create action for touching all the values of the field', () => {
32 | const actionType = touchAll('mockedForm', ['field1', 'field2', 'field3']);
33 | const action = {
34 | type: TOUCH_ALL,
35 | form: 'mockedForm',
36 | fields: ['field1', 'field2', 'field3']
37 | };
38 | expect(actionType).toEqual(action);
39 | });
40 | it('should create action for destroying the form', () => {
41 | const actionType = destroy('mockedForm');
42 | const action = {
43 | type: DESTROY,
44 | form: 'mockedForm'
45 | };
46 | expect(actionType).toEqual(action);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/__test__/reducer.specs.js:
--------------------------------------------------------------------------------
1 | /* global define, it, describe */
2 | /* eslint-disable import/no-extraneous-dependencies */
3 | import expect from 'expect';
4 | import deepFreeze from 'deep-freeze';
5 | import { initialize, setField, touchAll, destroy } from '../actions.js';
6 | import reducer from '../reducer';
7 |
8 | describe('reducers', () => {
9 | it('should initial from with fields and given values', () => {
10 | const stateBefore = {};
11 | const action = initialize(
12 | { field1: 'foo', field2: 'bar', field3: 'baz' },
13 | 'mockedForm',
14 | ['field1', 'field2', 'field3']);
15 | const stateAfter = {
16 | mockedForm: {
17 | field1: { value: 'foo' },
18 | field2: { value: 'bar' },
19 | field3: { value: 'baz' },
20 | initialized: true
21 | }
22 | };
23 | deepFreeze(stateBefore);
24 | deepFreeze(stateAfter);
25 | expect(reducer(stateBefore, action)).toEqual(stateAfter);
26 | });
27 | it('should modify the value of the given field, if the field exists', () => {
28 | const stateBefore = {
29 | mockedForm: {
30 | field1: { value: 'foo' },
31 | field2: { value: 'bar' },
32 | field3: { value: 'baz' },
33 | initialized: true
34 | }
35 | };
36 | const action = setField('field1', 'modifiedFoo', 'mockedForm');
37 | const stateAfter = {
38 | mockedForm: {
39 | field1: { touched: true, value: 'modifiedFoo' },
40 | field2: { value: 'bar' },
41 | field3: { value: 'baz' },
42 | initialized: true
43 | }
44 | };
45 | deepFreeze(stateBefore);
46 | deepFreeze(stateAfter);
47 | expect(reducer(stateBefore, action)).toEqual(stateAfter);
48 | });
49 | it('should add a new field, if the given field does not exist', () => {
50 | const stateBefore = {
51 | mockedForm: {
52 | field1: { value: 'foo' },
53 | field2: { value: 'bar' },
54 | field3: { value: 'baz' },
55 | initialized: true
56 | }
57 | };
58 | const action = setField('field4', 'tar', 'mockedForm');
59 | const stateAfter = {
60 | mockedForm: {
61 | field1: { value: 'foo' },
62 | field2: { value: 'bar' },
63 | field3: { value: 'baz' },
64 | field4: { touched: true, value: 'tar' },
65 | initialized: true
66 | }
67 | };
68 | deepFreeze(stateBefore);
69 | deepFreeze(stateAfter);
70 | expect(reducer(stateBefore, action)).toEqual(stateAfter);
71 | });
72 | it('should add set touched propery of all fields to true, and if not exist add them', () => {
73 | const stateBefore = {
74 | mockedForm: {
75 | field1: { value: 'foo', touched: true },
76 | field2: { value: 'bar' },
77 | field3: { value: 'baz' },
78 | initialized: true
79 | }
80 | };
81 | const action = touchAll('mockedForm', ['field1', 'field2', 'field3']);
82 | const stateAfter = {
83 | mockedForm: {
84 | field1: { value: 'foo', touched: true },
85 | field2: { value: 'bar', touched: true },
86 | field3: { value: 'baz', touched: true },
87 | initialized: true
88 | }
89 | };
90 | deepFreeze(stateBefore);
91 | deepFreeze(stateAfter);
92 | expect(reducer(stateBefore, action)).toEqual(stateAfter);
93 | });
94 | it('should destory the mounted FORM, from the state tree', () => {
95 | const stateBefore = {
96 | mockedForm: {
97 | field1: { value: 'foo', touched: true },
98 | field2: { value: 'bar' },
99 | field3: { value: 'baz' },
100 | initialized: true
101 | },
102 | otherState: {
103 | viewState: 'VIEW_ALL'
104 | }
105 | };
106 | const action = destroy('mockedForm');
107 | const stateAfter = {
108 | otherState: {
109 | viewState: 'VIEW_ALL'
110 | },
111 | };
112 | deepFreeze(stateBefore);
113 | deepFreeze(stateAfter);
114 | expect(reducer(stateBefore, action)).toEqual(stateAfter);
115 | });
116 | });
117 |
118 |
--------------------------------------------------------------------------------
/src/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const INITIALIZE = 'simple-redux-form/INITIALIZE';
2 | export const DESTROY = 'simple-redux-form/DESTROY';
3 | export const SET_FIELD = 'simple-redux-form/SET_FIELD';
4 | export const TOUCH_ALL = 'simple-redux-form/TOUCH_ALL';
5 |
--------------------------------------------------------------------------------
/src/actions.js:
--------------------------------------------------------------------------------
1 | import { INITIALIZE, DESTROY, SET_FIELD, TOUCH_ALL } from './actionTypes';
2 |
3 | export function initialize(initialValue, form, fields) {
4 | return {
5 | type: INITIALIZE,
6 | initialValue,
7 | form,
8 | fields
9 | };
10 | }
11 |
12 | export function setField(field, value, form) {
13 | return {
14 | type: SET_FIELD, field, value, form
15 | };
16 | }
17 |
18 | export function touchAll(form, fields) {
19 | return {
20 | type: TOUCH_ALL, form, fields
21 | };
22 | }
23 |
24 | export function destroy(form) {
25 | return {
26 | type: DESTROY, form
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/helpers.js:
--------------------------------------------------------------------------------
1 | /*
2 | This are set of helpers function to make simpleReduxForm work
3 | */
4 | export function getFieldValue(field, formValues) {
5 | if (formValues && formValues[field]) {
6 | return formValues[field].value;
7 | }
8 | return undefined;
9 | }
10 | export function simplifiedVlaues(formValues, fields) {
11 | return fields.reduce((acc, field) => ({
12 | ...acc,
13 | [field]: getFieldValue(field, formValues)
14 | }), Object.create(null));
15 | }
16 | export function createField(field, onChange) {
17 | const fieldObject = {
18 | name: field,
19 | touched: false,
20 | onChange: ({ target: { type, checked, value } }) => {
21 | const isCheckbox = type && type.toLowerCase() === 'checkbox';
22 | onChange(field, isCheckbox ? checked : value);
23 | }
24 | };
25 | return {
26 | ...fieldObject,
27 | setValue(value) { // If custome component set value directly
28 | onChange(field, value);
29 | }
30 | };
31 | }
32 | export function hasSyncErrors(errors) {
33 | let allErrors = errors;
34 | if (allErrors == null) {
35 | allErrors = {};
36 | }
37 | let hasError = false;
38 | const fieldKeys = Object.keys(allErrors);
39 | for (let i = 0; i < fieldKeys.length; i++) {
40 | if (allErrors[fieldKeys[i]] !== undefined) {
41 | hasError = true;
42 | break;
43 | }
44 | }
45 | return hasError;
46 | }
47 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export reducer from './reducer';
2 | export * as formActions from './actionTypes';
3 | export simpleReduxForm from './simpleReduxForm';
4 |
--------------------------------------------------------------------------------
/src/reducer.js:
--------------------------------------------------------------------------------
1 | import { INITIALIZE, DESTROY, SET_FIELD, TOUCH_ALL } from './actionTypes';
2 |
3 | const initialState = {};
4 |
5 | export default function reducer(state = initialState, action) {
6 | switch (action.type) {
7 | case INITIALIZE :
8 | return {
9 | ...state,
10 | [action.form]: {
11 | ...action.fields.reduce((acc, field) => ({
12 | ...acc,
13 | [field]: {
14 | value: action.initialValue[field]
15 | }
16 | }), {}),
17 | initialized: true,
18 | }
19 | };
20 | case DESTROY : {
21 | const updateDState = { ...state };
22 | delete updateDState[action.form];
23 | return {
24 | ...updateDState
25 | };
26 | }
27 | case SET_FIELD: {
28 | const { field, value, form } = action;
29 | return {
30 | ...state,
31 | [form]: {
32 | ...state[form],
33 | [field]: {
34 | touched: true,
35 | value,
36 | }
37 | }
38 | };
39 | }
40 | case TOUCH_ALL: {
41 | const { fields, form } = action;
42 | return {
43 | ...state,
44 | [form]: {
45 | ...state[form],
46 | ...fields.reduce((prevField, field) => ({
47 | ...prevField,
48 | [field]: {
49 | value: state[form] && state[form][field] ? state[form][field].value : '',
50 | touched: true
51 | }
52 | }), {})
53 | }
54 | };
55 | }
56 | default:
57 | return state;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/simpleReduxForm.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes, Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import { bindActionCreators } from 'redux';
4 | import deepEqual from 'deep-equal';
5 | import { setField, initialize, touchAll } from './actions';
6 | import { simplifiedVlaues, createField, hasSyncErrors } from './helpers';
7 |
8 | // Higher order component for huge fast dynamic deeply nested universal forms.
9 | export default function simpleReduxForm(Wrapped, options) {
10 | const {
11 | form = '',
12 | fields: initFields = [],
13 | getInitialState,
14 | validate = () => {}
15 | } = options;
16 |
17 | class SimpleReduxForm extends Component {
18 | constructor(props) {
19 | super(props);
20 | this.state = {
21 | model: null
22 | };
23 | this.onFieldChange = this.onFieldChange.bind(this);
24 | this.validate = this.validate.bind(this);
25 | }
26 | componentWillMount() {
27 | this.createFields(this.props.fields); // Create all the fields
28 | this.setModel(); // set Current state of HOC
29 | }
30 | componentDidMount() {
31 | /*
32 | initialize the form on client side, as we can access storage easily and
33 | can avoid the Dom difference.
34 | */
35 | let initialState = getInitialState && getInitialState(this.props);
36 | if (!initialState) {
37 | initialState = {};
38 | }
39 | const state = this.props.currentForm;
40 | const initialized = state && state.initialized ? state.initialized : false;
41 | // Make initialized only if object is not empty
42 | if (!initialized && Object.keys(initialState).length > 0) {
43 | this.props.actions.initialize(initialState, form, this.props.fields);
44 | this.setModel();
45 | }
46 | }
47 | componentWillReceiveProps(nextProps) {
48 | // console.log('NextProps.currentForm', nextProps.currentForm);
49 | if (!deepEqual(this.props.currentForm, nextProps.currentForm)) {
50 | const currentFields = Object.keys(this.fields);
51 | if (!deepEqual(currentFields, nextProps.fields)) {
52 | this.createFields(nextProps.fields); // Create all the fields
53 | }
54 | this.setModel(nextProps.currentForm); // set Current state of HOC
55 | }
56 | // Need to compare and then do this thing
57 | const state = this.props.currentForm;
58 | const initialized = state && state.initialized ? state.initialized : false;
59 | if (!initialized) {
60 | const initialState = getInitialState && getInitialState(nextProps);
61 | if (initialState) {
62 | this.props.actions.initialize(initialState, form, this.props.fields);
63 | }
64 | }
65 | }
66 | componentWillUnmount() {
67 | this.fields = null;
68 | }
69 | onFieldChange(field, value) {
70 | this.props.actions.setField(field, value, form);
71 | }
72 | setModel(newState) {
73 | const fieldsKeys = Object.keys(this.fields);
74 | this.values = simplifiedVlaues(newState, fieldsKeys);
75 | // We are passing two arguments to validate function
76 | // Second can be used for dynamic validation usecase
77 | const errors = validate(this.values, this.props);
78 | fieldsKeys.forEach(field => {
79 | const { fields, values } = this;
80 | fields[field].value = values[field];
81 | fields[field].error = errors && errors[field] ? errors[field] : undefined;
82 | fields[field].touched = newState && newState[field] ? newState[field].touched : false;
83 | });
84 | this.fields = { ...this.fields };
85 | this.allValid = !hasSyncErrors(errors);
86 | // this.setState({ model: newState });
87 | }
88 | /*
89 | TODO::This needs to be triggred before every submit.
90 | We can commbine this to handle All submit which will
91 | make sure it validates and gives value back with returning
92 | promise.
93 | */
94 | validate() {
95 | this.props.actions.touchAll(form, this.props.fields);
96 | return this.allValid;
97 | }
98 | // Create all Fields with all sugar functions
99 | createFields(fieldList) {
100 | const formFields = fieldList.reduce((fields, field) => ({
101 | ...fields,
102 | [field]: createField(field, this.onFieldChange)
103 | }), {});
104 | this.fields = { ...formFields };
105 | }
106 | render() {
107 | return (
108 | );
115 | }
116 | }
117 | SimpleReduxForm.propTypes = {
118 | fields: PropTypes.array,
119 | actions: PropTypes.object,
120 | currentForm: PropTypes.object,
121 | };
122 | SimpleReduxForm.defaultProps = {
123 | fields: initFields // Take either from the Decorator or else as props
124 | };
125 | function mapStateToProps(state) {
126 | return {
127 | currentForm: state.forms[form]
128 | };
129 | }
130 | function mapDispatchToProps(dispatch) {
131 | return {
132 | actions: bindActionCreators({
133 | setField,
134 | initialize,
135 | touchAll,
136 | }, dispatch),
137 | dispatch
138 | };
139 | }
140 | return connect(mapStateToProps, mapDispatchToProps)(SimpleReduxForm);
141 | }
142 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var env = process.env.NODE_ENV;
3 |
4 | var reactExternal = {
5 | root: 'React',
6 | commonjs2: 'react',
7 | commonjs: 'react',
8 | amd: 'react'
9 | };
10 |
11 | var plugins = [
12 | new webpack.DefinePlugin({
13 | 'process.env.NODE_ENV': JSON.stringify(env)
14 | }),
15 | new webpack.optimize.OccurenceOrderPlugin()
16 | ];
17 |
18 | if (env === 'production') {
19 | plugins.push(
20 | new webpack.optimize.UglifyJsPlugin({
21 | compressor: {
22 | screw_ie8: true,
23 | warnings: false
24 | }
25 | })
26 | );
27 | }
28 |
29 | module.exports = {
30 | externals: {
31 | react: reactExternal
32 | },
33 | module: {
34 | loaders: [
35 | { test: /\.js$/, loaders: ['babel-loader'], exclude: /node_modules/ }
36 | ]
37 | },
38 | output: {
39 | library: 'SimpleReduxForm',
40 | libraryTarget: 'umd'
41 | },
42 | plugins: plugins,
43 | resolve: {
44 | extensions: ['', '.js']
45 | }
46 | };
47 |
--------------------------------------------------------------------------------